From 824f7b0903de8ad7f6ee3d7656005e4c59155e06 Mon Sep 17 00:00:00 2001
From: Karl Berry
Date: Mon, 8 Apr 2013 00:43:40 +0000
Subject: context import for TL13, from
www.pragma-ade.com/context/beta/cont-tmf.zip
git-svn-id: svn://tug.org/texlive/trunk@29731 c570f23f-e606-0410-a88d-b1316a301751
---
Master/texmf-dist/bibtex/bst/context/cont-ab.bst | 1 +
Master/texmf-dist/bibtex/bst/context/cont-au.bst | 1 +
Master/texmf-dist/bibtex/bst/context/cont-no.bst | 1 +
Master/texmf-dist/bibtex/bst/context/cont-ti.bst | 1 +
.../lexers/data/scite-context-data-context.lua | 4 +-
.../lexers/data/scite-context-data-interfaces.lua | 4 +-
.../lexers/data/scite-context-data-metafun.lua | 4 +-
.../lexers/data/scite-context-data-metapost.lua | 2 +-
.../scite/lexers/data/scite-context-data-tex.lua | 4 +-
.../data/scite/lexers/scite-context-lexer-cld.lua | 1 -
.../lexers/scite-context-lexer-lua-longstring.lua | 8 +
.../data/scite/lexers/scite-context-lexer-lua.lua | 123 +-
.../data/scite/lexers/scite-context-lexer-mps.lua | 15 +-
.../data/scite/lexers/scite-context-lexer-tex.lua | 85 +-
.../data/scite/lexers/scite-context-lexer-txt.lua | 40 +-
.../data/scite/lexers/scite-context-lexer-web.lua | 155 +
.../lexers/scite-context-lexer-xml-comment.lua | 5 +-
.../lexers/scite-context-lexer-xml-script.lua | 30 +
.../data/scite/lexers/scite-context-lexer-xml.lua | 49 +-
.../data/scite/lexers/scite-context-lexer.lua | 643 +-
.../scite/lexers/themes/scite-context-theme.lua | 1 -
.../scite/scite-context-data-context.properties | 284 +-
.../scite/scite-context-data-interfaces.properties | 1666 +-
.../scite/scite-context-data-metafun.properties | 50 +-
.../scite/scite-context-data-metapost.properties | 110 +-
.../data/scite/scite-context-data-tex.properties | 384 +-
.../data/scite/scite-context-external.properties | 23 +-
.../data/scite/scite-context-internal.properties | 4 +
.../context/data/scite/scite-context-readme.pdf | Bin 205340 -> 212111 bytes
.../context/data/scite/scite-context-readme.tex | 22 +-
.../context/data/scite/scite-context.properties | 42 +-
Master/texmf-dist/context/data/scite/scite-ctx.lua | 67 +-
.../context/data/scite/scite-ctx.properties | 3 +
.../context/data/scite/scite-pragma.properties | 4 +-
Master/texmf-dist/doc/context/bib/bibmod-doc.pdf | Bin 284752 -> 0 bytes
Master/texmf-dist/doc/context/bib/bibmod-doc.tex | 750 -
.../doc/context/scripts/mkii/ctxtools.html | 58 +
.../doc/context/scripts/mkii/ctxtools.man | 75 +
.../doc/context/scripts/mkii/ctxtools.xml | 31 +
.../doc/context/scripts/mkii/imgtopdf.html | 49 +
.../doc/context/scripts/mkii/imgtopdf.man | 48 +
.../doc/context/scripts/mkii/imgtopdf.xml | 22 +
.../doc/context/scripts/mkii/mptopdf.html | 44 +
.../doc/context/scripts/mkii/mptopdf.xml | 17 +
.../doc/context/scripts/mkii/pdftools.html | 49 +
.../doc/context/scripts/mkii/pdftools.man | 48 +
.../doc/context/scripts/mkii/pdftools.xml | 22 +
.../doc/context/scripts/mkii/pstopdf.html | 43 +
.../doc/context/scripts/mkii/pstopdf.man | 30 +
.../doc/context/scripts/mkii/pstopdf.xml | 16 +
.../doc/context/scripts/mkii/rlxtools.html | 43 +
.../doc/context/scripts/mkii/rlxtools.man | 30 +
.../doc/context/scripts/mkii/rlxtools.xml | 16 +
.../doc/context/scripts/mkii/texexec.html | 57 +
.../doc/context/scripts/mkii/texexec.man | 72 +
.../doc/context/scripts/mkii/texexec.xml | 30 +
.../doc/context/scripts/mkii/texmfstart.html | 94 +
.../doc/context/scripts/mkii/texmfstart.man | 147 +
.../doc/context/scripts/mkii/texmfstart.xml | 78 +
.../doc/context/scripts/mkii/textools.html | 57 +
.../doc/context/scripts/mkii/textools.man | 72 +
.../doc/context/scripts/mkii/textools.xml | 30 +
.../doc/context/scripts/mkii/texutil.html | 48 +
.../doc/context/scripts/mkii/texutil.man | 45 +
.../doc/context/scripts/mkii/texutil.xml | 21 +
.../doc/context/scripts/mkii/tmftools.html | 44 +
.../doc/context/scripts/mkii/tmftools.man | 30 +
.../doc/context/scripts/mkii/tmftools.xml | 18 +
.../doc/context/scripts/mkii/xmltools.html | 48 +
.../doc/context/scripts/mkii/xmltools.man | 45 +
.../doc/context/scripts/mkii/xmltools.xml | 21 +
.../doc/context/scripts/mkiv/context.html | 104 +
.../doc/context/scripts/mkiv/context.man | 167 +
.../doc/context/scripts/mkiv/context.xml | 187 +
.../doc/context/scripts/mkiv/luatools.html | 59 +
.../doc/context/scripts/mkiv/luatools.man | 78 +
.../doc/context/scripts/mkiv/luatools.xml | 31 +
.../doc/context/scripts/mkiv/mtx-babel.html | 44 +
.../doc/context/scripts/mkiv/mtx-babel.man | 33 +
.../doc/context/scripts/mkiv/mtx-babel.xml | 17 +
.../doc/context/scripts/mkiv/mtx-base.html | 59 +
.../doc/context/scripts/mkiv/mtx-base.man | 78 +
.../doc/context/scripts/mkiv/mtx-base.xml | 32 +
.../doc/context/scripts/mkiv/mtx-cache.html | 46 +
.../doc/context/scripts/mkiv/mtx-cache.man | 36 +
.../doc/context/scripts/mkiv/mtx-cache.xml | 20 +
.../doc/context/scripts/mkiv/mtx-chars.html | 44 +
.../doc/context/scripts/mkiv/mtx-chars.man | 33 +
.../doc/context/scripts/mkiv/mtx-chars.xml | 17 +
.../doc/context/scripts/mkiv/mtx-check.html | 42 +
.../doc/context/scripts/mkiv/mtx-check.man | 27 +
.../doc/context/scripts/mkiv/mtx-check.xml | 15 +
.../doc/context/scripts/mkiv/mtx-colors.html | 44 +
.../doc/context/scripts/mkiv/mtx-colors.man | 27 +
.../doc/context/scripts/mkiv/mtx-colors.xml | 23 +
.../doc/context/scripts/mkiv/mtx-context.html | 104 +
.../doc/context/scripts/mkiv/mtx-context.man | 167 +
.../doc/context/scripts/mkiv/mtx-context.xml | 187 +
.../doc/context/scripts/mkiv/mtx-epub.html | 44 +
.../doc/context/scripts/mkiv/mtx-epub.man | 27 +
.../doc/context/scripts/mkiv/mtx-epub.xml | 23 +
.../doc/context/scripts/mkiv/mtx-fcd.html | 56 +
.../doc/context/scripts/mkiv/mtx-fcd.man | 54 +
.../doc/context/scripts/mkiv/mtx-fcd.xml | 35 +
.../doc/context/scripts/mkiv/mtx-flac.html | 45 +
.../doc/context/scripts/mkiv/mtx-flac.man | 27 +
.../doc/context/scripts/mkiv/mtx-flac.xml | 24 +
.../doc/context/scripts/mkiv/mtx-fonts.html | 71 +
.../doc/context/scripts/mkiv/mtx-fonts.man | 63 +
.../doc/context/scripts/mkiv/mtx-fonts.xml | 59 +
.../doc/context/scripts/mkiv/mtx-grep.html | 45 +
.../doc/context/scripts/mkiv/mtx-grep.man | 36 +
.../doc/context/scripts/mkiv/mtx-grep.xml | 21 +
.../doc/context/scripts/mkiv/mtx-interface.html | 60 +
.../doc/context/scripts/mkiv/mtx-interface.man | 69 +
.../doc/context/scripts/mkiv/mtx-interface.xml | 37 +
.../doc/context/scripts/mkiv/mtx-metapost.html | 50 +
.../doc/context/scripts/mkiv/mtx-metapost.man | 39 +
.../doc/context/scripts/mkiv/mtx-metapost.xml | 32 +
.../doc/context/scripts/mkiv/mtx-metatex.html | 43 +
.../doc/context/scripts/mkiv/mtx-metatex.man | 30 +
.../doc/context/scripts/mkiv/mtx-metatex.xml | 16 +
.../doc/context/scripts/mkiv/mtx-modules.html | 44 +
.../doc/context/scripts/mkiv/mtx-modules.man | 33 +
.../doc/context/scripts/mkiv/mtx-modules.xml | 17 +
.../doc/context/scripts/mkiv/mtx-package.html | 42 +
.../doc/context/scripts/mkiv/mtx-package.man | 27 +
.../doc/context/scripts/mkiv/mtx-package.xml | 15 +
.../doc/context/scripts/mkiv/mtx-patterns.html | 51 +
.../doc/context/scripts/mkiv/mtx-patterns.man | 39 +
.../doc/context/scripts/mkiv/mtx-patterns.xml | 30 +
.../doc/context/scripts/mkiv/mtx-pdf.html | 44 +
.../doc/context/scripts/mkiv/mtx-pdf.man | 33 +
.../doc/context/scripts/mkiv/mtx-pdf.xml | 17 +
.../doc/context/scripts/mkiv/mtx-profile.html | 43 +
.../doc/context/scripts/mkiv/mtx-profile.man | 30 +
.../doc/context/scripts/mkiv/mtx-profile.xml | 16 +
.../doc/context/scripts/mkiv/mtx-rsync.html | 44 +
.../doc/context/scripts/mkiv/mtx-rsync.man | 33 +
.../doc/context/scripts/mkiv/mtx-rsync.xml | 17 +
.../doc/context/scripts/mkiv/mtx-scite.html | 42 +
.../doc/context/scripts/mkiv/mtx-scite.man | 27 +
.../doc/context/scripts/mkiv/mtx-scite.xml | 15 +
.../doc/context/scripts/mkiv/mtx-server.html | 47 +
.../doc/context/scripts/mkiv/mtx-server.man | 42 +
.../doc/context/scripts/mkiv/mtx-server.xml | 20 +
.../doc/context/scripts/mkiv/mtx-texworks.html | 43 +
.../doc/context/scripts/mkiv/mtx-texworks.man | 30 +
.../doc/context/scripts/mkiv/mtx-texworks.xml | 16 +
.../doc/context/scripts/mkiv/mtx-timing.html | 44 +
.../doc/context/scripts/mkiv/mtx-timing.man | 33 +
.../doc/context/scripts/mkiv/mtx-timing.xml | 17 +
.../doc/context/scripts/mkiv/mtx-tools.html | 56 +
.../doc/context/scripts/mkiv/mtx-tools.man | 63 +
.../doc/context/scripts/mkiv/mtx-tools.xml | 31 +
.../doc/context/scripts/mkiv/mtx-unzip.html | 44 +
.../doc/context/scripts/mkiv/mtx-unzip.man | 33 +
.../doc/context/scripts/mkiv/mtx-unzip.xml | 17 +
.../doc/context/scripts/mkiv/mtx-update.html | 59 +
.../doc/context/scripts/mkiv/mtx-update.man | 78 +
.../doc/context/scripts/mkiv/mtx-update.xml | 32 +
.../doc/context/scripts/mkiv/mtx-watch.html | 49 +
.../doc/context/scripts/mkiv/mtx-watch.man | 48 +
.../doc/context/scripts/mkiv/mtx-watch.xml | 22 +
.../doc/context/scripts/mkiv/mtxrun.html | 94 +
.../texmf-dist/doc/context/scripts/mkiv/mtxrun.man | 147 +
.../texmf-dist/doc/context/scripts/mkiv/mtxrun.xml | 79 +
.../texmf-dist/doc/context/scripts/perl/texshow.1 | 70 -
.../doc/context/scripts/perl/texshow.html | 137 -
Master/texmf-dist/doc/man/man1/context.1 | 261 +-
Master/texmf-dist/doc/man/man1/ctxtools.1 | 148 +-
Master/texmf-dist/doc/man/man1/luatools.1 | 78 +
Master/texmf-dist/doc/man/man1/luatools.man1.pdf | Bin 0 -> 5105 bytes
Master/texmf-dist/doc/man/man1/mtx-babel.1 | 33 +
Master/texmf-dist/doc/man/man1/mtx-babel.man1.pdf | Bin 0 -> 3672 bytes
Master/texmf-dist/doc/man/man1/mtx-base.1 | 78 +
Master/texmf-dist/doc/man/man1/mtx-base.man1.pdf | Bin 0 -> 5124 bytes
Master/texmf-dist/doc/man/man1/mtx-cache.1 | 36 +
Master/texmf-dist/doc/man/man1/mtx-cache.man1.pdf | Bin 0 -> 3707 bytes
Master/texmf-dist/doc/man/man1/mtx-chars.1 | 33 +
Master/texmf-dist/doc/man/man1/mtx-chars.man1.pdf | Bin 0 -> 3566 bytes
Master/texmf-dist/doc/man/man1/mtx-check.1 | 27 +
Master/texmf-dist/doc/man/man1/mtx-check.man1.pdf | Bin 0 -> 3580 bytes
Master/texmf-dist/doc/man/man1/mtx-colors.1 | 27 +
Master/texmf-dist/doc/man/man1/mtx-colors.man1.pdf | Bin 0 -> 3442 bytes
Master/texmf-dist/doc/man/man1/mtx-context.1 | 167 +
.../texmf-dist/doc/man/man1/mtx-context.man1.pdf | Bin 0 -> 7542 bytes
Master/texmf-dist/doc/man/man1/mtx-epub.1 | 27 +
Master/texmf-dist/doc/man/man1/mtx-epub.man1.pdf | Bin 0 -> 3535 bytes
Master/texmf-dist/doc/man/man1/mtx-fcd.1 | 54 +
Master/texmf-dist/doc/man/man1/mtx-fcd.man1.pdf | Bin 0 -> 3960 bytes
Master/texmf-dist/doc/man/man1/mtx-flac.1 | 27 +
Master/texmf-dist/doc/man/man1/mtx-flac.man1.pdf | Bin 0 -> 3625 bytes
Master/texmf-dist/doc/man/man1/mtx-fonts.1 | 63 +
Master/texmf-dist/doc/man/man1/mtx-fonts.man1.pdf | Bin 0 -> 4206 bytes
Master/texmf-dist/doc/man/man1/mtx-grep.1 | 36 +
Master/texmf-dist/doc/man/man1/mtx-grep.man1.pdf | Bin 0 -> 3545 bytes
Master/texmf-dist/doc/man/man1/mtx-interface.1 | 69 +
.../texmf-dist/doc/man/man1/mtx-interface.man1.pdf | Bin 0 -> 4105 bytes
Master/texmf-dist/doc/man/man1/mtx-metapost.1 | 39 +
.../texmf-dist/doc/man/man1/mtx-metapost.man1.pdf | 110 +
Master/texmf-dist/doc/man/man1/mtx-metatex.1 | 30 +
.../texmf-dist/doc/man/man1/mtx-metatex.man1.pdf | Bin 0 -> 3630 bytes
Master/texmf-dist/doc/man/man1/mtx-modules.1 | 33 +
.../texmf-dist/doc/man/man1/mtx-modules.man1.pdf | Bin 0 -> 3760 bytes
Master/texmf-dist/doc/man/man1/mtx-package.1 | 27 +
.../texmf-dist/doc/man/man1/mtx-package.man1.pdf | Bin 0 -> 3568 bytes
Master/texmf-dist/doc/man/man1/mtx-patterns.1 | 39 +
.../texmf-dist/doc/man/man1/mtx-patterns.man1.pdf | Bin 0 -> 4013 bytes
Master/texmf-dist/doc/man/man1/mtx-pdf.1 | 33 +
Master/texmf-dist/doc/man/man1/mtx-pdf.man1.pdf | Bin 0 -> 3661 bytes
Master/texmf-dist/doc/man/man1/mtx-profile.1 | 30 +
.../texmf-dist/doc/man/man1/mtx-profile.man1.pdf | 117 +
Master/texmf-dist/doc/man/man1/mtx-rsync.1 | 33 +
Master/texmf-dist/doc/man/man1/mtx-rsync.man1.pdf | Bin 0 -> 3635 bytes
Master/texmf-dist/doc/man/man1/mtx-scite.1 | 27 +
Master/texmf-dist/doc/man/man1/mtx-scite.man1.pdf | Bin 0 -> 3446 bytes
Master/texmf-dist/doc/man/man1/mtx-server.1 | 42 +
Master/texmf-dist/doc/man/man1/mtx-server.man1.pdf | 113 +
Master/texmf-dist/doc/man/man1/mtx-texworks.1 | 30 +
.../texmf-dist/doc/man/man1/mtx-texworks.man1.pdf | Bin 0 -> 3557 bytes
Master/texmf-dist/doc/man/man1/mtx-timing.1 | 33 +
Master/texmf-dist/doc/man/man1/mtx-timing.man1.pdf | Bin 0 -> 3679 bytes
Master/texmf-dist/doc/man/man1/mtx-tools.1 | 63 +
Master/texmf-dist/doc/man/man1/mtx-tools.man1.pdf | Bin 0 -> 3967 bytes
Master/texmf-dist/doc/man/man1/mtx-unzip.1 | 33 +
Master/texmf-dist/doc/man/man1/mtx-unzip.man1.pdf | 111 +
Master/texmf-dist/doc/man/man1/mtx-update.1 | 78 +
Master/texmf-dist/doc/man/man1/mtx-update.man1.pdf | Bin 0 -> 5030 bytes
Master/texmf-dist/doc/man/man1/mtx-watch.1 | 48 +
Master/texmf-dist/doc/man/man1/mtx-watch.man1.pdf | Bin 0 -> 3867 bytes
Master/texmf-dist/doc/man/man1/mtxrun.1 | 147 +
Master/texmf-dist/doc/man/man1/mtxrun.man1.pdf | Bin 0 -> 7032 bytes
Master/texmf-dist/doc/man/man1/pstopdf.1 | 87 +-
Master/texmf-dist/doc/man/man1/texexec.1 | 656 +-
Master/texmf-dist/doc/man/man1/texmfstart.1 | 443 +-
.../fonts/map/pdftex/context/koeieletters.map | 8 -
.../fonts/opentype/context/tests/texmfhome.otf | Bin 1884 -> 0 bytes
.../fonts/pfm/hoekwater/context/contnav.pfm | Bin 0 -> 482 bytes
.../texmf-dist/metapost/context/base/metafun.mpiv | 7 +-
.../texmf-dist/metapost/context/base/mp-abck.mpiv | 2 +-
.../texmf-dist/metapost/context/base/mp-apos.mpiv | 2 +-
.../texmf-dist/metapost/context/base/mp-asnc.mpiv | 2 +-
.../texmf-dist/metapost/context/base/mp-butt.mpiv | 2 +-
.../texmf-dist/metapost/context/base/mp-char.mpiv | 2 +-
.../texmf-dist/metapost/context/base/mp-chem.mpiv | 2074 +-
.../texmf-dist/metapost/context/base/mp-core.mpiv | 2 +-
.../texmf-dist/metapost/context/base/mp-crop.mpiv | 14 +-
.../texmf-dist/metapost/context/base/mp-figs.mpiv | 2 +-
.../texmf-dist/metapost/context/base/mp-form.mpiv | 2 +-
.../texmf-dist/metapost/context/base/mp-func.mpiv | 2 +-
.../texmf-dist/metapost/context/base/mp-grap.mpiv | 526 +
.../texmf-dist/metapost/context/base/mp-grid.mpiv | 2 +-
.../texmf-dist/metapost/context/base/mp-grph.mpiv | 2 +-
.../texmf-dist/metapost/context/base/mp-mlib.mpiv | 94 +-
.../texmf-dist/metapost/context/base/mp-page.mpiv | 246 +-
.../texmf-dist/metapost/context/base/mp-shap.mpiv | 2 +-
.../texmf-dist/metapost/context/base/mp-step.mpiv | 2 +-
.../texmf-dist/metapost/context/base/mp-text.mpiv | 2 +-
.../texmf-dist/metapost/context/base/mp-tool.mpiv | 197 +-
.../texmf-dist/scripts/context/lua/mtx-babel.lua | 22 +-
Master/texmf-dist/scripts/context/lua/mtx-base.lua | 54 +-
.../texmf-dist/scripts/context/lua/mtx-cache.lua | 27 +-
.../texmf-dist/scripts/context/lua/mtx-chars.lua | 22 +-
.../texmf-dist/scripts/context/lua/mtx-check.lua | 18 +-
.../texmf-dist/scripts/context/lua/mtx-colors.lua | 30 +-
.../texmf-dist/scripts/context/lua/mtx-context.lua | 1726 +-
.../texmf-dist/scripts/context/lua/mtx-context.xml | 187 +
.../texmf-dist/scripts/context/lua/mtx-convert.lua | 34 +-
Master/texmf-dist/scripts/context/lua/mtx-epub.lua | 143 +-
Master/texmf-dist/scripts/context/lua/mtx-fcd.lua | 386 +
Master/texmf-dist/scripts/context/lua/mtx-flac.lua | 70 +-
.../texmf-dist/scripts/context/lua/mtx-fonts.lua | 148 +-
Master/texmf-dist/scripts/context/lua/mtx-grep.lua | 35 +-
.../scripts/context/lua/mtx-interface.lua | 60 +-
.../scripts/context/lua/mtx-metapost.lua | 53 +-
.../texmf-dist/scripts/context/lua/mtx-metatex.lua | 20 +-
.../texmf-dist/scripts/context/lua/mtx-mk-help.lua | 473 +
.../texmf-dist/scripts/context/lua/mtx-modules.lua | 22 +-
.../texmf-dist/scripts/context/lua/mtx-package.lua | 40 +-
.../scripts/context/lua/mtx-patterns.lua | 57 +-
Master/texmf-dist/scripts/context/lua/mtx-pdf.lua | 162 +-
.../texmf-dist/scripts/context/lua/mtx-profile.lua | 55 +-
.../texmf-dist/scripts/context/lua/mtx-rsync.lua | 31 +-
.../texmf-dist/scripts/context/lua/mtx-scite.lua | 48 +-
.../context/lua/mtx-server-ctx-fonttest.lua | 30 +-
.../scripts/context/lua/mtx-server-ctx-help.lua | 217 +-
.../texmf-dist/scripts/context/lua/mtx-server.lua | 82 +-
.../scripts/context/lua/mtx-texworks.lua | 20 +-
.../texmf-dist/scripts/context/lua/mtx-timing.lua | 25 +-
.../texmf-dist/scripts/context/lua/mtx-tools.lua | 53 +-
.../texmf-dist/scripts/context/lua/mtx-unzip.lua | 22 +-
.../texmf-dist/scripts/context/lua/mtx-update.lua | 87 +-
.../texmf-dist/scripts/context/lua/mtx-watch.lua | 45 +-
Master/texmf-dist/scripts/context/lua/mtxlibs.lua | 240 +
Master/texmf-dist/scripts/context/lua/mtxrun.lua | 29766 ++++++++++---------
.../texmf-dist/scripts/context/ruby/base/logger.rb | 3 +-
Master/texmf-dist/scripts/context/ruby/base/tex.rb | 3 +-
.../texmf-dist/scripts/context/ruby/fcd_start.rb | 472 -
Master/texmf-dist/scripts/context/ruby/mpstools.rb | 7 -
Master/texmf-dist/scripts/context/ruby/texexec.rb | 2 +-
Master/texmf-dist/scripts/context/ruby/texsync.rb | 206 -
.../scripts/context/stubs/mswin/ctxtools.exe | Bin 0 -> 6144 bytes
.../scripts/context/stubs/mswin/mptopdf.exe | Bin 6144 -> 0 bytes
.../scripts/context/stubs/mswin/mtxrun.dll | Bin 9216 -> 38400 bytes
.../scripts/context/stubs/mswin/mtxrun.exe | Bin 6144 -> 34816 bytes
.../scripts/context/stubs/mswin/mtxrun.lua | 29766 ++++++++++---------
.../scripts/context/stubs/mswin/pstopdf.exe | Bin 0 -> 6144 bytes
.../scripts/context/stubs/mswin/setuptex.bat | 34 +
.../texmf-dist/scripts/context/stubs/unix/ctxtools | 2 +
.../texmf-dist/scripts/context/stubs/unix/mtxrun | 29766 ++++++++++---------
.../texmf-dist/scripts/context/stubs/unix/pstopdf | 2 +
Master/texmf-dist/tex/context/base/anch-bar.mkiv | 150 +-
Master/texmf-dist/tex/context/base/anch-bck.mkvi | 14 +-
Master/texmf-dist/tex/context/base/anch-pgr.lua | 375 +-
Master/texmf-dist/tex/context/base/anch-pgr.mkiv | 120 +-
Master/texmf-dist/tex/context/base/anch-pos.lua | 76 +-
Master/texmf-dist/tex/context/base/anch-pos.mkiv | 8 +-
Master/texmf-dist/tex/context/base/anch-tab.mkiv | 188 +-
Master/texmf-dist/tex/context/base/attr-col.lua | 88 +-
Master/texmf-dist/tex/context/base/attr-eff.lua | 42 +-
Master/texmf-dist/tex/context/base/attr-eff.mkiv | 43 +-
Master/texmf-dist/tex/context/base/attr-ini.lua | 38 +-
Master/texmf-dist/tex/context/base/attr-ini.mkiv | 17 +-
Master/texmf-dist/tex/context/base/attr-lay.lua | 102 +-
Master/texmf-dist/tex/context/base/attr-lay.mkiv | 82 +-
Master/texmf-dist/tex/context/base/attr-mkr.lua | 26 +
Master/texmf-dist/tex/context/base/attr-mkr.mkiv | 25 +
Master/texmf-dist/tex/context/base/attr-neg.lua | 5 +-
Master/texmf-dist/tex/context/base/attr-neg.mkiv | 10 +-
Master/texmf-dist/tex/context/base/back-exp.lua | 391 +-
Master/texmf-dist/tex/context/base/back-exp.mkiv | 26 +-
Master/texmf-dist/tex/context/base/back-ini.lua | 14 +-
Master/texmf-dist/tex/context/base/back-ini.mkiv | 6 +-
Master/texmf-dist/tex/context/base/back-pdf.mkiv | 32 +-
Master/texmf-dist/tex/context/base/back-swf.mkiv | 14 +-
Master/texmf-dist/tex/context/base/back-u3d.mkiv | 7 +-
Master/texmf-dist/tex/context/base/bibl-bib.lua | 25 +-
Master/texmf-dist/tex/context/base/bibl-bib.mkiv | 7 +-
Master/texmf-dist/tex/context/base/bibl-tra.lua | 16 +-
Master/texmf-dist/tex/context/base/bibl-tra.mkiv | 342 +-
Master/texmf-dist/tex/context/base/blob-ini.lua | 2 +-
Master/texmf-dist/tex/context/base/buff-ini.lua | 193 +-
Master/texmf-dist/tex/context/base/buff-ini.mkii | 12 +-
Master/texmf-dist/tex/context/base/buff-ini.mkiv | 47 +-
Master/texmf-dist/tex/context/base/buff-par.lua | 29 +-
Master/texmf-dist/tex/context/base/buff-par.mkiv | 151 -
Master/texmf-dist/tex/context/base/buff-par.mkvi | 131 +
Master/texmf-dist/tex/context/base/buff-ver.lua | 43 +-
Master/texmf-dist/tex/context/base/buff-ver.mkiv | 32 +-
Master/texmf-dist/tex/context/base/catc-ctx.mkiv | 11 +-
Master/texmf-dist/tex/context/base/catc-def.mkiv | 7 +-
Master/texmf-dist/tex/context/base/catc-ini.lua | 21 +-
Master/texmf-dist/tex/context/base/catc-ini.mkiv | 64 +-
Master/texmf-dist/tex/context/base/char-cjk.lua | 23 +-
Master/texmf-dist/tex/context/base/char-def.lua | 8860 +++++-
Master/texmf-dist/tex/context/base/char-enc.lua | 41 +-
Master/texmf-dist/tex/context/base/char-ent.lua | 8 +-
Master/texmf-dist/tex/context/base/char-ini.lua | 1033 +-
Master/texmf-dist/tex/context/base/char-ini.mkiv | 6 +-
Master/texmf-dist/tex/context/base/char-map.lua | 3 +-
Master/texmf-dist/tex/context/base/char-tex.lua | 13 +-
Master/texmf-dist/tex/context/base/char-utf.lua | 260 +-
Master/texmf-dist/tex/context/base/chem-ini.lua | 66 +-
Master/texmf-dist/tex/context/base/chem-str.lua | 957 +-
Master/texmf-dist/tex/context/base/chem-str.mkiv | 354 +-
Master/texmf-dist/tex/context/base/cldf-bas.lua | 56 +-
Master/texmf-dist/tex/context/base/cldf-bas.mkiv | 1 +
Master/texmf-dist/tex/context/base/cldf-com.lua | 9 +-
Master/texmf-dist/tex/context/base/cldf-ini.lua | 240 +-
Master/texmf-dist/tex/context/base/cldf-ini.mkiv | 14 +-
Master/texmf-dist/tex/context/base/cldf-int.lua | 11 +-
Master/texmf-dist/tex/context/base/cldf-prs.lua | 54 +
Master/texmf-dist/tex/context/base/cldf-ver.lua | 6 +-
Master/texmf-dist/tex/context/base/colo-ext.mkiv | 10 +-
Master/texmf-dist/tex/context/base/colo-icc.lua | 18 +-
Master/texmf-dist/tex/context/base/colo-ini.lua | 202 +-
Master/texmf-dist/tex/context/base/colo-ini.mkiv | 83 +-
Master/texmf-dist/tex/context/base/colo-run.lua | 6 +-
Master/texmf-dist/tex/context/base/colo-run.mkiv | 28 +-
Master/texmf-dist/tex/context/base/cont-log.mkiv | 10 +-
Master/texmf-dist/tex/context/base/cont-new.mkii | 2 +-
Master/texmf-dist/tex/context/base/cont-new.mkiv | 501 +-
Master/texmf-dist/tex/context/base/cont-nop.mkiv | 22 +
Master/texmf-dist/tex/context/base/cont-yes.mkiv | 91 +
.../texmf-dist/tex/context/base/context-base.lmx | 69 +-
.../texmf-dist/tex/context/base/context-help.lmx | 6 +-
.../tex/context/base/context-version.pdf | Bin 4128 -> 4131 bytes
.../tex/context/base/context-version.png | Bin 105721 -> 40047 bytes
Master/texmf-dist/tex/context/base/context.mkii | 4 +-
Master/texmf-dist/tex/context/base/context.mkiv | 89 +-
Master/texmf-dist/tex/context/base/context.rme | 7 +-
Master/texmf-dist/tex/context/base/context.todo | 6 -
Master/texmf-dist/tex/context/base/core-con.lua | 469 +-
Master/texmf-dist/tex/context/base/core-con.mkiv | 188 +-
Master/texmf-dist/tex/context/base/core-ctx.ctx | 23 +
Master/texmf-dist/tex/context/base/core-ctx.lua | 342 +-
Master/texmf-dist/tex/context/base/core-ctx.mkiv | 17 +-
Master/texmf-dist/tex/context/base/core-dat.lua | 85 +-
Master/texmf-dist/tex/context/base/core-def.mkiv | 122 +-
Master/texmf-dist/tex/context/base/core-env.lua | 32 +-
Master/texmf-dist/tex/context/base/core-env.mkiv | 152 +-
Master/texmf-dist/tex/context/base/core-fnt.mkiv | 158 -
Master/texmf-dist/tex/context/base/core-ini.mkiv | 228 +-
Master/texmf-dist/tex/context/base/core-mis.mkiv | 738 -
Master/texmf-dist/tex/context/base/core-sys.lua | 90 +-
Master/texmf-dist/tex/context/base/core-sys.mkiv | 86 +-
Master/texmf-dist/tex/context/base/core-two.lua | 2 +-
Master/texmf-dist/tex/context/base/core-uti.lua | 99 +-
Master/texmf-dist/tex/context/base/core-uti.mkiv | 8 +-
Master/texmf-dist/tex/context/base/core-var.mkiv | 239 -
Master/texmf-dist/tex/context/base/data-aux.lua | 6 +-
Master/texmf-dist/tex/context/base/data-con.lua | 22 +-
Master/texmf-dist/tex/context/base/data-env.lua | 10 +-
Master/texmf-dist/tex/context/base/data-exp.lua | 20 +-
Master/texmf-dist/tex/context/base/data-fil.lua | 18 +-
Master/texmf-dist/tex/context/base/data-ini.lua | 36 +-
Master/texmf-dist/tex/context/base/data-lst.lua | 13 +-
Master/texmf-dist/tex/context/base/data-lua.lua | 241 +-
Master/texmf-dist/tex/context/base/data-met.lua | 14 +-
Master/texmf-dist/tex/context/base/data-pre.lua | 75 +-
Master/texmf-dist/tex/context/base/data-res.lua | 216 +-
Master/texmf-dist/tex/context/base/data-sch.lua | 80 +-
Master/texmf-dist/tex/context/base/data-tex.lua | 32 +-
Master/texmf-dist/tex/context/base/data-tmf.lua | 10 +-
Master/texmf-dist/tex/context/base/data-tmp.lua | 95 +-
Master/texmf-dist/tex/context/base/data-tre.lua | 6 +-
Master/texmf-dist/tex/context/base/data-use.lua | 10 +-
Master/texmf-dist/tex/context/base/data-vir.lua | 22 +-
Master/texmf-dist/tex/context/base/data-zip.lua | 62 +-
Master/texmf-dist/tex/context/base/enco-ini.mkiv | 115 +-
Master/texmf-dist/tex/context/base/file-ini.lua | 5 +-
Master/texmf-dist/tex/context/base/file-ini.mkvi | 20 +-
Master/texmf-dist/tex/context/base/file-job.lua | 515 +-
Master/texmf-dist/tex/context/base/file-job.mkvi | 26 +-
Master/texmf-dist/tex/context/base/file-lib.lua | 11 +-
Master/texmf-dist/tex/context/base/file-mod.lua | 45 +-
Master/texmf-dist/tex/context/base/file-mod.mkvi | 9 +-
Master/texmf-dist/tex/context/base/file-res.lua | 12 +-
Master/texmf-dist/tex/context/base/file-syn.lua | 7 +-
Master/texmf-dist/tex/context/base/font-afk.lua | 200 +
Master/texmf-dist/tex/context/base/font-afm.lua | 412 +-
Master/texmf-dist/tex/context/base/font-age.lua | 3 +-
Master/texmf-dist/tex/context/base/font-agl.lua | 2 +-
Master/texmf-dist/tex/context/base/font-aux.lua | 145 +-
Master/texmf-dist/tex/context/base/font-aux.mkvi | 26 +
Master/texmf-dist/tex/context/base/font-chk.lua | 5 +-
Master/texmf-dist/tex/context/base/font-chk.mkiv | 22 +
Master/texmf-dist/tex/context/base/font-cid.lua | 25 +-
Master/texmf-dist/tex/context/base/font-col.lua | 128 +-
Master/texmf-dist/tex/context/base/font-con.lua | 130 +-
Master/texmf-dist/tex/context/base/font-ctx.lua | 703 +-
Master/texmf-dist/tex/context/base/font-def.lua | 88 +-
Master/texmf-dist/tex/context/base/font-enh.lua | 52 +-
Master/texmf-dist/tex/context/base/font-ext.lua | 76 +-
Master/texmf-dist/tex/context/base/font-fbk.lua | 69 +-
Master/texmf-dist/tex/context/base/font-fea.mkvi | 190 +-
Master/texmf-dist/tex/context/base/font-gds.lua | 132 +-
Master/texmf-dist/tex/context/base/font-gds.mkiv | 83 -
Master/texmf-dist/tex/context/base/font-gds.mkvi | 83 +
Master/texmf-dist/tex/context/base/font-hsh.lua | 182 +
Master/texmf-dist/tex/context/base/font-ini.lua | 24 +-
Master/texmf-dist/tex/context/base/font-ini.mkvi | 62 +-
Master/texmf-dist/tex/context/base/font-ldr.lua | 4 +-
Master/texmf-dist/tex/context/base/font-lib.mkvi | 10 +-
Master/texmf-dist/tex/context/base/font-log.lua | 6 +-
Master/texmf-dist/tex/context/base/font-lua.lua | 2 +-
Master/texmf-dist/tex/context/base/font-map.lua | 55 +-
Master/texmf-dist/tex/context/base/font-mat.mkvi | 15 +-
Master/texmf-dist/tex/context/base/font-mis.lua | 4 +-
Master/texmf-dist/tex/context/base/font-nod.lua | 434 +
Master/texmf-dist/tex/context/base/font-odk.lua | 904 +
Master/texmf-dist/tex/context/base/font-odv.lua | 2074 ++
Master/texmf-dist/tex/context/base/font-ota.lua | 289 +-
Master/texmf-dist/tex/context/base/font-otb.lua | 107 +-
Master/texmf-dist/tex/context/base/font-otc.lua | 9 +-
Master/texmf-dist/tex/context/base/font-otd.lua | 157 +-
Master/texmf-dist/tex/context/base/font-otf.lua | 214 +-
Master/texmf-dist/tex/context/base/font-oti.lua | 13 +-
Master/texmf-dist/tex/context/base/font-otn.lua | 733 +-
Master/texmf-dist/tex/context/base/font-otp.lua | 323 +-
Master/texmf-dist/tex/context/base/font-ott.lua | 181 +-
Master/texmf-dist/tex/context/base/font-otx.lua | 393 +
Master/texmf-dist/tex/context/base/font-pat.lua | 24 +-
Master/texmf-dist/tex/context/base/font-pre.mkiv | 80 +-
Master/texmf-dist/tex/context/base/font-run.mkiv | 47 +-
Master/texmf-dist/tex/context/base/font-set.mkvi | 8 +-
Master/texmf-dist/tex/context/base/font-sol.lua | 884 +
Master/texmf-dist/tex/context/base/font-sol.mkvi | 123 +
Master/texmf-dist/tex/context/base/font-sty.mkvi | 50 +-
Master/texmf-dist/tex/context/base/font-sym.mkvi | 4 +-
Master/texmf-dist/tex/context/base/font-syn.lua | 592 +-
Master/texmf-dist/tex/context/base/font-tfm.lua | 19 +-
Master/texmf-dist/tex/context/base/font-tra.mkiv | 155 +-
Master/texmf-dist/tex/context/base/font-vf.lua | 16 +-
Master/texmf-dist/tex/context/base/grph-epd.lua | 1 -
Master/texmf-dist/tex/context/base/grph-epd.mkiv | 14 +-
Master/texmf-dist/tex/context/base/grph-fig.mkiv | 729 +-
Master/texmf-dist/tex/context/base/grph-fil.lua | 17 +-
Master/texmf-dist/tex/context/base/grph-inc.lua | 1052 +-
Master/texmf-dist/tex/context/base/grph-inc.mkiv | 969 +-
Master/texmf-dist/tex/context/base/grph-raw.lua | 5 +-
Master/texmf-dist/tex/context/base/grph-raw.mkiv | 14 +-
Master/texmf-dist/tex/context/base/grph-swf.lua | 35 +-
Master/texmf-dist/tex/context/base/grph-trf.mkiv | 492 +-
Master/texmf-dist/tex/context/base/grph-u3d.lua | 10 +-
Master/texmf-dist/tex/context/base/grph-wnd.lua | 6 +-
.../texmf-dist/tex/context/base/java-imp-fld.mkiv | 140 +-
Master/texmf-dist/tex/context/base/java-ini.lua | 70 +-
Master/texmf-dist/tex/context/base/l-boolean.lua | 45 +-
Master/texmf-dist/tex/context/base/l-dir.lua | 58 +-
Master/texmf-dist/tex/context/base/l-file.lua | 674 +-
Master/texmf-dist/tex/context/base/l-function.lua | 11 +
Master/texmf-dist/tex/context/base/l-io.lua | 125 +-
Master/texmf-dist/tex/context/base/l-lpeg.lua | 534 +-
Master/texmf-dist/tex/context/base/l-lua.lua | 393 +
Master/texmf-dist/tex/context/base/l-md5.lua | 90 +-
Master/texmf-dist/tex/context/base/l-number.lua | 241 +-
Master/texmf-dist/tex/context/base/l-os.lua | 93 +-
Master/texmf-dist/tex/context/base/l-pdfview.lua | 34 +-
Master/texmf-dist/tex/context/base/l-string.lua | 211 +-
Master/texmf-dist/tex/context/base/l-table.lua | 744 +-
Master/texmf-dist/tex/context/base/l-unicode.lua | 1001 +-
Master/texmf-dist/tex/context/base/l-url.lua | 129 +-
Master/texmf-dist/tex/context/base/lang-def.lua | 84 +-
Master/texmf-dist/tex/context/base/lang-def.mkiv | 34 +-
Master/texmf-dist/tex/context/base/lang-frd.mkiv | 143 +
Master/texmf-dist/tex/context/base/lang-frq-de.lua | 12 +
Master/texmf-dist/tex/context/base/lang-frq-en.lua | 26 +
Master/texmf-dist/tex/context/base/lang-frq-nl.lua | 12 +
Master/texmf-dist/tex/context/base/lang-frq.mkiv | 235 +
Master/texmf-dist/tex/context/base/lang-ini.lua | 179 +-
Master/texmf-dist/tex/context/base/lang-ini.mkiv | 93 +-
Master/texmf-dist/tex/context/base/lang-lab.lua | 166 +-
Master/texmf-dist/tex/context/base/lang-lab.mkiv | 74 +-
Master/texmf-dist/tex/context/base/lang-mis.mkiv | 31 +
Master/texmf-dist/tex/context/base/lang-txt.lua | 271 +-
Master/texmf-dist/tex/context/base/lang-url.lua | 10 +-
Master/texmf-dist/tex/context/base/lang-wrd.lua | 115 +-
Master/texmf-dist/tex/context/base/lpdf-ano.lua | 48 +-
Master/texmf-dist/tex/context/base/lpdf-col.lua | 139 +-
Master/texmf-dist/tex/context/base/lpdf-epa.lua | 160 +-
Master/texmf-dist/tex/context/base/lpdf-epd.lua | 52 +-
Master/texmf-dist/tex/context/base/lpdf-fld.lua | 72 +-
Master/texmf-dist/tex/context/base/lpdf-fmt.lua | 88 +-
Master/texmf-dist/tex/context/base/lpdf-grp.lua | 2 +-
Master/texmf-dist/tex/context/base/lpdf-ini.lua | 56 +-
Master/texmf-dist/tex/context/base/lpdf-nod.lua | 71 +-
Master/texmf-dist/tex/context/base/lpdf-ren.lua | 120 +-
Master/texmf-dist/tex/context/base/lpdf-swf.lua | 10 +-
Master/texmf-dist/tex/context/base/lpdf-tag.lua | 16 +-
Master/texmf-dist/tex/context/base/lpdf-u3d.lua | 4 +-
Master/texmf-dist/tex/context/base/lpdf-wid.lua | 10 +-
Master/texmf-dist/tex/context/base/lpdf-xmp.lua | 17 +-
Master/texmf-dist/tex/context/base/luat-bas.mkiv | 34 +-
Master/texmf-dist/tex/context/base/luat-bwc.lua | 2 +-
Master/texmf-dist/tex/context/base/luat-cbk.lua | 37 +-
Master/texmf-dist/tex/context/base/luat-cnf.lua | 91 +-
Master/texmf-dist/tex/context/base/luat-cod.lua | 34 +-
Master/texmf-dist/tex/context/base/luat-cod.mkiv | 24 +-
Master/texmf-dist/tex/context/base/luat-env.lua | 242 +-
Master/texmf-dist/tex/context/base/luat-exe.lua | 16 +-
Master/texmf-dist/tex/context/base/luat-fio.lua | 65 +-
Master/texmf-dist/tex/context/base/luat-fmt.lua | 65 +-
Master/texmf-dist/tex/context/base/luat-ini.lua | 267 +-
Master/texmf-dist/tex/context/base/luat-ini.mkiv | 112 +-
Master/texmf-dist/tex/context/base/luat-iop.lua | 6 +-
Master/texmf-dist/tex/context/base/luat-lib.mkiv | 19 +-
Master/texmf-dist/tex/context/base/luat-lua.lua | 34 +-
Master/texmf-dist/tex/context/base/luat-mac.lua | 120 +-
Master/texmf-dist/tex/context/base/luat-run.lua | 40 +-
Master/texmf-dist/tex/context/base/luat-soc.lua | 16 +-
Master/texmf-dist/tex/context/base/luat-sto.lua | 114 +-
Master/texmf-dist/tex/context/base/lxml-aux.lua | 45 +-
Master/texmf-dist/tex/context/base/lxml-css.lua | 48 +-
Master/texmf-dist/tex/context/base/lxml-css.mkiv | 2 +-
Master/texmf-dist/tex/context/base/lxml-ctx.lua | 2 +-
Master/texmf-dist/tex/context/base/lxml-ctx.mkiv | 3 -
Master/texmf-dist/tex/context/base/lxml-dir.lua | 41 +-
Master/texmf-dist/tex/context/base/lxml-ent.lua | 5 +-
Master/texmf-dist/tex/context/base/lxml-inf.lua | 2 +
Master/texmf-dist/tex/context/base/lxml-ini.mkiv | 12 +-
Master/texmf-dist/tex/context/base/lxml-lpt.lua | 189 +-
Master/texmf-dist/tex/context/base/lxml-tab.lua | 121 +-
Master/texmf-dist/tex/context/base/lxml-tex.lua | 190 +-
Master/texmf-dist/tex/context/base/m-barcodes.mkiv | 8 +-
Master/texmf-dist/tex/context/base/m-chart.lua | 179 +-
Master/texmf-dist/tex/context/base/m-chart.mkii | 2 +-
Master/texmf-dist/tex/context/base/m-chart.mkvi | 142 +-
Master/texmf-dist/tex/context/base/m-database.lua | 35 +-
Master/texmf-dist/tex/context/base/m-database.mkiv | 33 +-
Master/texmf-dist/tex/context/base/m-graph.mkiv | 153 +-
Master/texmf-dist/tex/context/base/m-ipsum.mkiv | 198 +
Master/texmf-dist/tex/context/base/m-json.mkiv | 30 +
Master/texmf-dist/tex/context/base/m-morse.mkvi | 25 +-
.../texmf-dist/tex/context/base/m-nodechart.mkvi | 257 +
Master/texmf-dist/tex/context/base/m-oldfun.mkiv | 714 +
Master/texmf-dist/tex/context/base/m-oldnum.mkiv | 416 +
Master/texmf-dist/tex/context/base/m-pstricks.lua | 8 +-
.../texmf-dist/tex/context/base/m-spreadsheet.lua | 332 +
.../texmf-dist/tex/context/base/m-spreadsheet.mkiv | 295 +-
Master/texmf-dist/tex/context/base/m-timing.mkiv | 22 +-
.../texmf-dist/tex/context/base/m-translate.mkiv | 27 +-
Master/texmf-dist/tex/context/base/m-visual.mkiv | 581 +-
Master/texmf-dist/tex/context/base/math-act.lua | 219 +-
Master/texmf-dist/tex/context/base/math-ali.mkiv | 187 +-
Master/texmf-dist/tex/context/base/math-arr.mkiv | 401 +-
Master/texmf-dist/tex/context/base/math-def.mkiv | 22 +-
Master/texmf-dist/tex/context/base/math-del.mkiv | 2 +
Master/texmf-dist/tex/context/base/math-dim.lua | 6 +-
Master/texmf-dist/tex/context/base/math-ext.lua | 130 +-
Master/texmf-dist/tex/context/base/math-fbk.lua | 312 +
Master/texmf-dist/tex/context/base/math-fen.mkiv | 108 +
Master/texmf-dist/tex/context/base/math-for.mkiv | 15 -
Master/texmf-dist/tex/context/base/math-frc.mkiv | 230 +-
Master/texmf-dist/tex/context/base/math-ini.lua | 404 +-
Master/texmf-dist/tex/context/base/math-ini.mkiv | 867 +-
Master/texmf-dist/tex/context/base/math-int.mkiv | 145 +-
Master/texmf-dist/tex/context/base/math-map.lua | 167 +-
Master/texmf-dist/tex/context/base/math-mis.mkiv | 60 +
Master/texmf-dist/tex/context/base/math-noa.lua | 748 +-
Master/texmf-dist/tex/context/base/math-stc.mkvi | 780 +
Master/texmf-dist/tex/context/base/math-tag.lua | 75 +-
Master/texmf-dist/tex/context/base/math-ttv.lua | 801 +
Master/texmf-dist/tex/context/base/math-vfu.lua | 1082 +-
Master/texmf-dist/tex/context/base/meta-fig.mkiv | 3 +-
Master/texmf-dist/tex/context/base/meta-fun.lua | 4 +-
Master/texmf-dist/tex/context/base/meta-grd.mkiv | 116 +
.../texmf-dist/tex/context/base/meta-imp-dum.mkiv | 124 +-
.../texmf-dist/tex/context/base/meta-imp-txt.mkiv | 30 +-
Master/texmf-dist/tex/context/base/meta-ini.lua | 127 +-
Master/texmf-dist/tex/context/base/meta-ini.mkiv | 429 +-
Master/texmf-dist/tex/context/base/meta-pag.mkiv | 12 +-
Master/texmf-dist/tex/context/base/meta-pdf.lua | 15 +-
Master/texmf-dist/tex/context/base/meta-pdh.mkiv | 2 +-
Master/texmf-dist/tex/context/base/meta-tex.lua | 2 +-
Master/texmf-dist/tex/context/base/mlib-ctx.lua | 99 +-
Master/texmf-dist/tex/context/base/mlib-pdf.lua | 138 +-
Master/texmf-dist/tex/context/base/mlib-pdf.mkiv | 45 +-
Master/texmf-dist/tex/context/base/mlib-pps.lua | 342 +-
Master/texmf-dist/tex/context/base/mlib-pps.mkiv | 24 +-
Master/texmf-dist/tex/context/base/mlib-run.lua | 367 +-
.../tex/context/base/mtx-context-copy.tex | 151 +
.../tex/context/base/mtx-context-select.tex | 3 +-
.../tex/context/base/mtx-context-timing.tex | 8 +-
Master/texmf-dist/tex/context/base/mult-aux.lua | 34 +-
Master/texmf-dist/tex/context/base/mult-aux.mkiv | 231 +-
Master/texmf-dist/tex/context/base/mult-chk.lua | 7 +-
Master/texmf-dist/tex/context/base/mult-chk.mkiv | 14 +-
Master/texmf-dist/tex/context/base/mult-de.mkii | 16 +
Master/texmf-dist/tex/context/base/mult-def.lua | 76 +-
Master/texmf-dist/tex/context/base/mult-def.mkiv | 86 +-
Master/texmf-dist/tex/context/base/mult-dim.mkvi | 3 +-
Master/texmf-dist/tex/context/base/mult-en.mkii | 16 +
Master/texmf-dist/tex/context/base/mult-fr.mkii | 16 +
Master/texmf-dist/tex/context/base/mult-fun.lua | 101 +
Master/texmf-dist/tex/context/base/mult-ini.lua | 134 +-
Master/texmf-dist/tex/context/base/mult-ini.mkiv | 78 +-
Master/texmf-dist/tex/context/base/mult-it.mkii | 16 +
Master/texmf-dist/tex/context/base/mult-low.lua | 122 +-
Master/texmf-dist/tex/context/base/mult-mes.lua | 1895 +-
Master/texmf-dist/tex/context/base/mult-mps.lua | 5 +-
Master/texmf-dist/tex/context/base/mult-nl.mkii | 16 +
Master/texmf-dist/tex/context/base/mult-pe.mkii | 16 +
Master/texmf-dist/tex/context/base/mult-prm.lua | 14 +-
Master/texmf-dist/tex/context/base/mult-prm.mkiv | 18 +
Master/texmf-dist/tex/context/base/mult-ro.mkii | 16 +
Master/texmf-dist/tex/context/base/mult-sys.mkiv | 574 +-
Master/texmf-dist/tex/context/base/node-acc.lua | 14 +-
Master/texmf-dist/tex/context/base/node-aux.lua | 110 +-
Master/texmf-dist/tex/context/base/node-bck.lua | 189 +-
Master/texmf-dist/tex/context/base/node-bck.mkiv | 26 +-
Master/texmf-dist/tex/context/base/node-dir.lua | 2 +-
Master/texmf-dist/tex/context/base/node-ext.lua | 4 +-
Master/texmf-dist/tex/context/base/node-fin.lua | 1198 +-
Master/texmf-dist/tex/context/base/node-fnt.lua | 29 +-
Master/texmf-dist/tex/context/base/node-ini.lua | 123 +-
Master/texmf-dist/tex/context/base/node-ini.mkiv | 4 +-
Master/texmf-dist/tex/context/base/node-inj.lua | 128 +-
Master/texmf-dist/tex/context/base/node-mig.lua | 12 +-
Master/texmf-dist/tex/context/base/node-par.lua | 118 -
Master/texmf-dist/tex/context/base/node-par.mkiv | 82 -
Master/texmf-dist/tex/context/base/node-pro.lua | 52 +-
Master/texmf-dist/tex/context/base/node-ref.lua | 153 +-
Master/texmf-dist/tex/context/base/node-res.lua | 35 +-
Master/texmf-dist/tex/context/base/node-rul.lua | 158 +-
Master/texmf-dist/tex/context/base/node-rul.mkiv | 40 +-
Master/texmf-dist/tex/context/base/node-ser.lua | 38 +-
Master/texmf-dist/tex/context/base/node-shp.lua | 106 +-
Master/texmf-dist/tex/context/base/node-snp.lua | 66 +
Master/texmf-dist/tex/context/base/node-spl.lua | 619 -
Master/texmf-dist/tex/context/base/node-spl.mkiv | 114 -
Master/texmf-dist/tex/context/base/node-tra.lua | 716 +-
Master/texmf-dist/tex/context/base/node-tsk.lua | 28 +-
Master/texmf-dist/tex/context/base/node-typ.lua | 11 +-
Master/texmf-dist/tex/context/base/norm-ctx.mkiv | 75 +-
Master/texmf-dist/tex/context/base/pack-bar.mkiv | 97 +-
Master/texmf-dist/tex/context/base/pack-bck.mkvi | 5 +-
Master/texmf-dist/tex/context/base/pack-box.mkiv | 883 +-
Master/texmf-dist/tex/context/base/pack-com.mkiv | 53 +-
Master/texmf-dist/tex/context/base/pack-cut.mkiv | 163 +
Master/texmf-dist/tex/context/base/pack-lyr.mkiv | 2 +-
Master/texmf-dist/tex/context/base/pack-mrl.mkiv | 922 +-
Master/texmf-dist/tex/context/base/pack-obj.lua | 25 +-
Master/texmf-dist/tex/context/base/pack-obj.mkiv | 143 +-
Master/texmf-dist/tex/context/base/pack-pos.mkiv | 190 +-
Master/texmf-dist/tex/context/base/pack-rul.mkiv | 1081 +-
Master/texmf-dist/tex/context/base/page-app.mkiv | 22 +-
Master/texmf-dist/tex/context/base/page-bck.mkiv | 396 +-
Master/texmf-dist/tex/context/base/page-box.mkvi | 8 +-
Master/texmf-dist/tex/context/base/page-brk.mkiv | 14 +-
Master/texmf-dist/tex/context/base/page-col.mkiv | 245 +-
Master/texmf-dist/tex/context/base/page-com.mkiv | 176 +-
Master/texmf-dist/tex/context/base/page-fac.mkiv | 48 +-
Master/texmf-dist/tex/context/base/page-flt.lua | 24 +-
Master/texmf-dist/tex/context/base/page-flt.mkiv | 214 +-
Master/texmf-dist/tex/context/base/page-flw.mkiv | 186 +-
Master/texmf-dist/tex/context/base/page-grd.mkiv | 6 +-
Master/texmf-dist/tex/context/base/page-imp.mkiv | 110 +-
Master/texmf-dist/tex/context/base/page-inf.mkiv | 6 +-
Master/texmf-dist/tex/context/base/page-ini.mkiv | 46 +-
Master/texmf-dist/tex/context/base/page-inj.lua | 101 +
Master/texmf-dist/tex/context/base/page-inj.mkvi | 217 +
Master/texmf-dist/tex/context/base/page-ins.lua | 97 +
Master/texmf-dist/tex/context/base/page-ins.mkiv | 197 +-
Master/texmf-dist/tex/context/base/page-lay.mkiv | 79 +-
Master/texmf-dist/tex/context/base/page-lin.lua | 32 +-
Master/texmf-dist/tex/context/base/page-lin.mkiv | 597 +-
Master/texmf-dist/tex/context/base/page-mak.mkvi | 40 +-
Master/texmf-dist/tex/context/base/page-mbk.mkvi | 4 +-
Master/texmf-dist/tex/context/base/page-mis.lua | 77 -
Master/texmf-dist/tex/context/base/page-mis.mkiv | 95 -
Master/texmf-dist/tex/context/base/page-mix.lua | 660 +
Master/texmf-dist/tex/context/base/page-mix.mkiv | 801 +
Master/texmf-dist/tex/context/base/page-mul.mkiv | 2259 +-
Master/texmf-dist/tex/context/base/page-not.mkiv | 20 +-
Master/texmf-dist/tex/context/base/page-one.mkiv | 259 +-
Master/texmf-dist/tex/context/base/page-otr.mkvi | 4 +-
Master/texmf-dist/tex/context/base/page-par.mkiv | 88 +-
Master/texmf-dist/tex/context/base/page-plg.mkiv | 110 +-
Master/texmf-dist/tex/context/base/page-pst.lua | 78 +
Master/texmf-dist/tex/context/base/page-pst.mkiv | 102 +
Master/texmf-dist/tex/context/base/page-run.mkiv | 8 +-
Master/texmf-dist/tex/context/base/page-sel.mkiv | 347 -
Master/texmf-dist/tex/context/base/page-sel.mkvi | 369 +
Master/texmf-dist/tex/context/base/page-set.mkiv | 616 +-
Master/texmf-dist/tex/context/base/page-sid.mkiv | 60 +-
Master/texmf-dist/tex/context/base/page-spr.mkiv | 90 +-
Master/texmf-dist/tex/context/base/page-str.lua | 18 +-
Master/texmf-dist/tex/context/base/page-str.mkiv | 39 +-
Master/texmf-dist/tex/context/base/page-txt.mkvi | 132 +-
Master/texmf-dist/tex/context/base/phys-dim.lua | 92 +-
Master/texmf-dist/tex/context/base/phys-dim.mkiv | 33 +-
Master/texmf-dist/tex/context/base/ppchtex.mkii | 3 +-
Master/texmf-dist/tex/context/base/ppchtex.mkiv | 18 +-
Master/texmf-dist/tex/context/base/prop-ini.mkiv | 2 +-
Master/texmf-dist/tex/context/base/regi-ini.lua | 181 +-
Master/texmf-dist/tex/context/base/s-abr-01.tex | 561 +-
Master/texmf-dist/tex/context/base/s-abr-04.tex | 3 +
Master/texmf-dist/tex/context/base/s-art-01.mkiv | 10 +-
Master/texmf-dist/tex/context/base/s-def-01.mkiv | 2 +-
Master/texmf-dist/tex/context/base/s-fnt-10.mkiv | 2 +-
Master/texmf-dist/tex/context/base/s-fnt-20.mkiv | 29 +-
Master/texmf-dist/tex/context/base/s-fnt-21.mkiv | 20 +-
Master/texmf-dist/tex/context/base/s-fnt-28.mkiv | 2 +-
Master/texmf-dist/tex/context/base/s-fnt-29.mkiv | 2 +-
Master/texmf-dist/tex/context/base/s-fnt-31.mkiv | 2 +-
Master/texmf-dist/tex/context/base/s-fnt-32.mkiv | 2 +-
.../texmf-dist/tex/context/base/s-fonts-tables.lua | 2 +-
Master/texmf-dist/tex/context/base/s-inf-01.mkvi | 46 +-
Master/texmf-dist/tex/context/base/s-inf-03.mkiv | 144 +-
Master/texmf-dist/tex/context/base/s-lan-04.mkiv | 2 +-
Master/texmf-dist/tex/context/base/s-lan-06.mkiv | 53 +
Master/texmf-dist/tex/context/base/s-mat-10.mkiv | 29 +-
Master/texmf-dist/tex/context/base/s-mat-11.mkiv | 22 +-
Master/texmf-dist/tex/context/base/s-mat-20.mkiv | 161 +
Master/texmf-dist/tex/context/base/s-mod-00.mkiv | 8 +-
Master/texmf-dist/tex/context/base/s-mod-01.mkiv | 3 +
Master/texmf-dist/tex/context/base/s-mod-02.mkiv | 8 +-
Master/texmf-dist/tex/context/base/s-mod.ctx | 1 -
Master/texmf-dist/tex/context/base/s-pre-05.tex | 14 +-
Master/texmf-dist/tex/context/base/s-pre-60.mkiv | 134 +-
Master/texmf-dist/tex/context/base/s-pre-61.tex | 3 +-
Master/texmf-dist/tex/context/base/s-pre-62.tex | 2 +-
Master/texmf-dist/tex/context/base/s-pre-63.tex | 1 +
Master/texmf-dist/tex/context/base/s-pre-67.tex | 2 +-
Master/texmf-dist/tex/context/base/s-pre-69.mkiv | 2 +-
Master/texmf-dist/tex/context/base/scrn-bar.mkvi | 6 +-
Master/texmf-dist/tex/context/base/scrn-but.lua | 4 +-
Master/texmf-dist/tex/context/base/scrn-but.mkvi | 36 +-
Master/texmf-dist/tex/context/base/scrn-fld.lua | 6 +-
Master/texmf-dist/tex/context/base/scrn-fld.mkvi | 12 +-
Master/texmf-dist/tex/context/base/scrn-hlp.lua | 3 +-
Master/texmf-dist/tex/context/base/scrn-ini.lua | 4 +-
Master/texmf-dist/tex/context/base/scrn-ini.mkvi | 33 +-
Master/texmf-dist/tex/context/base/scrn-pag.mkvi | 6 -
Master/texmf-dist/tex/context/base/scrn-ref.lua | 2 +-
Master/texmf-dist/tex/context/base/scrn-wid.lua | 18 +-
Master/texmf-dist/tex/context/base/scrn-wid.mkvi | 135 +-
Master/texmf-dist/tex/context/base/scrp-cjk.lua | 28 +-
Master/texmf-dist/tex/context/base/scrp-eth.lua | 5 +-
Master/texmf-dist/tex/context/base/scrp-ini.lua | 448 +-
Master/texmf-dist/tex/context/base/scrp-ini.mkiv | 16 +
Master/texmf-dist/tex/context/base/sort-ini.lua | 222 +-
Master/texmf-dist/tex/context/base/sort-lan.lua | 20 +-
Master/texmf-dist/tex/context/base/spac-adj.lua | 17 +-
Master/texmf-dist/tex/context/base/spac-ali.lua | 20 +-
Master/texmf-dist/tex/context/base/spac-ali.mkiv | 203 +-
Master/texmf-dist/tex/context/base/spac-cha.mkiv | 191 +
Master/texmf-dist/tex/context/base/spac-chr.lua | 30 +-
Master/texmf-dist/tex/context/base/spac-chr.mkiv | 38 +-
Master/texmf-dist/tex/context/base/spac-def.mkiv | 116 +-
Master/texmf-dist/tex/context/base/spac-flr.mkiv | 112 +
Master/texmf-dist/tex/context/base/spac-grd.mkiv | 61 +-
Master/texmf-dist/tex/context/base/spac-hor.mkiv | 182 +-
Master/texmf-dist/tex/context/base/spac-par.mkiv | 7 +
Master/texmf-dist/tex/context/base/spac-ver.lua | 802 +-
Master/texmf-dist/tex/context/base/spac-ver.mkiv | 414 +-
.../texmf-dist/tex/context/base/status-files.pdf | Bin 24413 -> 24764 bytes
Master/texmf-dist/tex/context/base/status-lua.pdf | Bin 180149 -> 211760 bytes
Master/texmf-dist/tex/context/base/status-mkiv.lua | 7488 ++++-
Master/texmf-dist/tex/context/base/status-mkiv.tex | 317 +-
Master/texmf-dist/tex/context/base/strc-bkm.lua | 4 +-
Master/texmf-dist/tex/context/base/strc-bkm.mkiv | 150 +-
Master/texmf-dist/tex/context/base/strc-blk.lua | 7 +-
Master/texmf-dist/tex/context/base/strc-blk.mkiv | 96 +-
Master/texmf-dist/tex/context/base/strc-con.mkvi | 244 +-
Master/texmf-dist/tex/context/base/strc-def.mkiv | 59 +-
Master/texmf-dist/tex/context/base/strc-des.mkii | 2 +-
Master/texmf-dist/tex/context/base/strc-des.mkvi | 52 +-
Master/texmf-dist/tex/context/base/strc-doc.lua | 185 +-
Master/texmf-dist/tex/context/base/strc-doc.mkiv | 234 +-
Master/texmf-dist/tex/context/base/strc-enu.mkvi | 127 +-
Master/texmf-dist/tex/context/base/strc-flt.mkvi | 1099 +-
Master/texmf-dist/tex/context/base/strc-ind.mkiv | 12 +-
Master/texmf-dist/tex/context/base/strc-ini.lua | 67 +-
Master/texmf-dist/tex/context/base/strc-itm.mkvi | 128 +-
Master/texmf-dist/tex/context/base/strc-lab.mkiv | 232 +-
Master/texmf-dist/tex/context/base/strc-lev.lua | 7 +-
Master/texmf-dist/tex/context/base/strc-lnt.mkvi | 133 +-
Master/texmf-dist/tex/context/base/strc-lst.lua | 156 +-
Master/texmf-dist/tex/context/base/strc-lst.mkvi | 42 +-
Master/texmf-dist/tex/context/base/strc-mar.lua | 92 +-
Master/texmf-dist/tex/context/base/strc-mar.mkiv | 8 +-
Master/texmf-dist/tex/context/base/strc-mat.mkii | 10 +-
Master/texmf-dist/tex/context/base/strc-mat.mkiv | 498 +-
Master/texmf-dist/tex/context/base/strc-not.lua | 212 +-
Master/texmf-dist/tex/context/base/strc-not.mkvi | 646 +-
Master/texmf-dist/tex/context/base/strc-num.lua | 307 +-
Master/texmf-dist/tex/context/base/strc-num.mkiv | 496 +-
Master/texmf-dist/tex/context/base/strc-pag.lua | 18 +-
Master/texmf-dist/tex/context/base/strc-pag.mkiv | 219 +-
Master/texmf-dist/tex/context/base/strc-ref.lua | 224 +-
Master/texmf-dist/tex/context/base/strc-ref.mkvi | 378 +-
Master/texmf-dist/tex/context/base/strc-reg.lua | 20 +-
Master/texmf-dist/tex/context/base/strc-reg.mkiv | 460 +-
Master/texmf-dist/tex/context/base/strc-ren.mkiv | 868 +-
Master/texmf-dist/tex/context/base/strc-sbe.mkiv | 102 +-
Master/texmf-dist/tex/context/base/strc-sec.mkiv | 833 +-
Master/texmf-dist/tex/context/base/strc-syn.lua | 2 +-
Master/texmf-dist/tex/context/base/strc-syn.mkiv | 4 +-
Master/texmf-dist/tex/context/base/strc-tag.lua | 1 +
Master/texmf-dist/tex/context/base/strc-tag.mkiv | 84 +-
Master/texmf-dist/tex/context/base/supp-ali.mkiv | 173 -
Master/texmf-dist/tex/context/base/supp-box.lua | 12 +-
Master/texmf-dist/tex/context/base/supp-box.mkiv | 100 +-
Master/texmf-dist/tex/context/base/supp-fun.mkiv | 716 -
Master/texmf-dist/tex/context/base/supp-mat.mkiv | 143 +-
Master/texmf-dist/tex/context/base/supp-num.mkiv | 416 -
Master/texmf-dist/tex/context/base/supp-ran.lua | 28 +-
Master/texmf-dist/tex/context/base/supp-ran.mkiv | 4 +-
Master/texmf-dist/tex/context/base/supp-vis.mkiv | 185 +-
.../texmf-dist/tex/context/base/symb-imp-cc.mkiv | 52 +
Master/texmf-dist/tex/context/base/symb-ini.lua | 10 +-
Master/texmf-dist/tex/context/base/symb-run.mkiv | 8 +-
Master/texmf-dist/tex/context/base/syst-aux.lua | 34 +-
Master/texmf-dist/tex/context/base/syst-aux.mkiv | 3670 ++-
Master/texmf-dist/tex/context/base/syst-con.lua | 23 +-
Master/texmf-dist/tex/context/base/syst-con.mkiv | 10 +-
Master/texmf-dist/tex/context/base/syst-fnt.mkiv | 2 +-
Master/texmf-dist/tex/context/base/syst-gen.mkii | 5 +
Master/texmf-dist/tex/context/base/syst-ini.mkiv | 340 +-
Master/texmf-dist/tex/context/base/syst-lua.lua | 52 +-
Master/texmf-dist/tex/context/base/syst-lua.mkiv | 20 +-
Master/texmf-dist/tex/context/base/tabl-ltb.mkiv | 8 +-
Master/texmf-dist/tex/context/base/tabl-mis.mkiv | 288 +
Master/texmf-dist/tex/context/base/tabl-ntb.mkiv | 1914 +-
Master/texmf-dist/tex/context/base/tabl-nte.mkiv | 67 +-
Master/texmf-dist/tex/context/base/tabl-pln.mkiv | 155 +-
Master/texmf-dist/tex/context/base/tabl-tab.mkiv | 240 +-
Master/texmf-dist/tex/context/base/tabl-tbl.lua | 7 +-
Master/texmf-dist/tex/context/base/tabl-tbl.mkiv | 385 +-
Master/texmf-dist/tex/context/base/tabl-tsp.mkiv | 470 +-
Master/texmf-dist/tex/context/base/tabl-xnt.mkvi | 2 +-
Master/texmf-dist/tex/context/base/tabl-xtb.lua | 24 +-
Master/texmf-dist/tex/context/base/tabl-xtb.mkvi | 108 +-
Master/texmf-dist/tex/context/base/task-ini.lua | 35 +-
Master/texmf-dist/tex/context/base/toks-ini.lua | 7 +-
Master/texmf-dist/tex/context/base/trac-ctx.lua | 48 +
Master/texmf-dist/tex/context/base/trac-ctx.mkiv | 60 +
Master/texmf-dist/tex/context/base/trac-deb.lua | 44 +-
Master/texmf-dist/tex/context/base/trac-deb.mkiv | 6 +-
Master/texmf-dist/tex/context/base/trac-exp.lua | 229 +
Master/texmf-dist/tex/context/base/trac-fil.lua | 214 +-
Master/texmf-dist/tex/context/base/trac-inf.lua | 86 +-
Master/texmf-dist/tex/context/base/trac-jus.lua | 136 +
Master/texmf-dist/tex/context/base/trac-jus.mkiv | 25 +
Master/texmf-dist/tex/context/base/trac-lmx.lua | 725 +-
Master/texmf-dist/tex/context/base/trac-log.lua | 340 +-
Master/texmf-dist/tex/context/base/trac-pro.lua | 8 +-
Master/texmf-dist/tex/context/base/trac-set.lua | 205 +-
Master/texmf-dist/tex/context/base/trac-tex.lua | 3 +-
Master/texmf-dist/tex/context/base/trac-tim.lua | 66 +-
Master/texmf-dist/tex/context/base/trac-vis.lua | 913 +
Master/texmf-dist/tex/context/base/trac-vis.mkiv | 886 +-
Master/texmf-dist/tex/context/base/trac-xml.lua | 183 +
.../tex/context/base/type-imp-husayni.mkiv | 290 +-
.../tex/context/base/type-imp-latinmodern.mkiv | 21 +-
.../tex/context/base/type-imp-lucida-opentype.mkiv | 4 +-
.../tex/context/base/type-imp-texgyre.mkiv | 64 +-
.../texmf-dist/tex/context/base/type-imp-xits.mkiv | 14 +-
Master/texmf-dist/tex/context/base/type-ini.lua | 23 +-
Master/texmf-dist/tex/context/base/type-ini.mkvi | 20 +-
Master/texmf-dist/tex/context/base/typo-bld.lua | 185 +
Master/texmf-dist/tex/context/base/typo-bld.mkiv | 64 +
Master/texmf-dist/tex/context/base/typo-brk.lua | 24 +-
Master/texmf-dist/tex/context/base/typo-brk.mkiv | 18 +-
Master/texmf-dist/tex/context/base/typo-cap.lua | 22 +-
Master/texmf-dist/tex/context/base/typo-cap.mkiv | 44 +-
Master/texmf-dist/tex/context/base/typo-cln.lua | 5 +-
Master/texmf-dist/tex/context/base/typo-del.mkiv | 58 +-
Master/texmf-dist/tex/context/base/typo-dig.lua | 67 +-
Master/texmf-dist/tex/context/base/typo-dir.lua | 26 +-
Master/texmf-dist/tex/context/base/typo-dir.mkiv | 10 +-
Master/texmf-dist/tex/context/base/typo-itc.lua | 25 +-
Master/texmf-dist/tex/context/base/typo-itc.mkvi | 2 +-
Master/texmf-dist/tex/context/base/typo-itm.mkiv | 273 +
Master/texmf-dist/tex/context/base/typo-krn.lua | 67 +-
Master/texmf-dist/tex/context/base/typo-krn.mkiv | 57 +-
Master/texmf-dist/tex/context/base/typo-lan.lua | 72 +
Master/texmf-dist/tex/context/base/typo-lan.mkiv | 63 +
Master/texmf-dist/tex/context/base/typo-mar.lua | 143 +-
Master/texmf-dist/tex/context/base/typo-mar.mkiv | 7 +-
Master/texmf-dist/tex/context/base/typo-pag.lua | 24 +-
Master/texmf-dist/tex/context/base/typo-par.lua | 11 +-
Master/texmf-dist/tex/context/base/typo-prc.lua | 19 +-
Master/texmf-dist/tex/context/base/typo-rep.lua | 9 +-
Master/texmf-dist/tex/context/base/typo-scr.mkiv | 250 +-
Master/texmf-dist/tex/context/base/typo-spa.lua | 42 +-
Master/texmf-dist/tex/context/base/typo-spa.mkiv | 19 +-
Master/texmf-dist/tex/context/base/typo-txt.mkvi | 174 +-
Master/texmf-dist/tex/context/base/unic-ini.mkiv | 2 +-
Master/texmf-dist/tex/context/base/util-deb.lua | 30 +-
Master/texmf-dist/tex/context/base/util-dim.lua | 20 +-
Master/texmf-dist/tex/context/base/util-env.lua | 258 +
Master/texmf-dist/tex/context/base/util-fmt.lua | 22 +-
Master/texmf-dist/tex/context/base/util-jsn.lua | 145 +
Master/texmf-dist/tex/context/base/util-lib.lua | 233 +
Master/texmf-dist/tex/context/base/util-lua.lua | 372 +-
Master/texmf-dist/tex/context/base/util-mrg.lua | 137 +-
Master/texmf-dist/tex/context/base/util-pck.lua | 32 +-
Master/texmf-dist/tex/context/base/util-prs.lua | 387 +-
Master/texmf-dist/tex/context/base/util-ran.lua | 107 +
Master/texmf-dist/tex/context/base/util-seq.lua | 15 +-
.../tex/context/base/util-sql-imp-client.lua | 256 +
.../tex/context/base/util-sql-imp-library.lua | 289 +
.../tex/context/base/util-sql-imp-swiglib.lua | 490 +
.../tex/context/base/util-sql-loggers.lua | 277 +
.../tex/context/base/util-sql-sessions.lua | 349 +
.../tex/context/base/util-sql-tickets.lua | 772 +
.../texmf-dist/tex/context/base/util-sql-users.lua | 410 +
Master/texmf-dist/tex/context/base/util-sql.lua | 443 +
Master/texmf-dist/tex/context/base/util-sta.lua | 342 +
Master/texmf-dist/tex/context/base/util-sto.lua | 81 +-
Master/texmf-dist/tex/context/base/util-str.lua | 708 +-
Master/texmf-dist/tex/context/base/util-tab.lua | 383 +-
Master/texmf-dist/tex/context/base/util-tpl.lua | 174 +
.../texmf-dist/tex/context/base/x-asciimath.mkiv | 4 +-
Master/texmf-dist/tex/context/base/x-calcmath.lua | 85 +-
Master/texmf-dist/tex/context/base/x-calcmath.mkiv | 2 +-
Master/texmf-dist/tex/context/base/x-chemml.lua | 6 +-
Master/texmf-dist/tex/context/base/x-chemml.mkiv | 24 +-
Master/texmf-dist/tex/context/base/x-dir-05.mkiv | 4 +-
Master/texmf-dist/tex/context/base/x-ldx.ctx | 4 +-
Master/texmf-dist/tex/context/base/x-ldx.lua | 10 +-
Master/texmf-dist/tex/context/base/x-ldx.mkiv | 11 +-
Master/texmf-dist/tex/context/base/x-mathml.lua | 54 +-
Master/texmf-dist/tex/context/base/x-mathml.mkiv | 184 +-
Master/texmf-dist/tex/context/base/x-res-01.mkiv | 71 +-
Master/texmf-dist/tex/context/base/x-steps.mkiv | 102 +
Master/texmf-dist/tex/context/base/x-udhr.mkiv | 2 +-
Master/texmf-dist/tex/context/base/x-xfdf.mkiv | 72 +
Master/texmf-dist/tex/context/base/xtag-ini.mkii | 50 +-
Master/texmf-dist/tex/context/base/xtag-pre.mkii | 13 +
.../tex/context/colors/icc/colorprofiles.lua | 14 -
.../tex/context/colors/icc/colorprofiles.xml | 427 -
.../context/colors/icc/context/colorprofiles.lua | 14 +
.../context/colors/icc/context/colorprofiles.xml | 427 +
Master/texmf-dist/tex/context/config/cont-de.ini | 2 -
Master/texmf-dist/tex/context/config/cont-en.ini | 2 -
Master/texmf-dist/tex/context/config/cont-fr.ini | 2 -
Master/texmf-dist/tex/context/config/cont-it.ini | 2 -
Master/texmf-dist/tex/context/config/cont-nl.ini | 2 -
Master/texmf-dist/tex/context/config/cont-ro.ini | 2 -
Master/texmf-dist/tex/context/fonts/cc-icons.lfg | 23 +
Master/texmf-dist/tex/context/fonts/demo.lfg | 29 +-
Master/texmf-dist/tex/context/fonts/husayni.lfg | 6 +-
Master/texmf-dist/tex/context/fonts/lm-math.lfg | 126 +-
Master/texmf-dist/tex/context/fonts/lm.lfg | 35 +
.../tex/context/fonts/lucida-opentype-math.lfg | 7 +-
Master/texmf-dist/tex/context/fonts/texgyre.lfg | 24 +
.../texmf-dist/tex/context/interface/keys-cs.xml | 16 +
.../texmf-dist/tex/context/interface/keys-de.xml | 16 +
.../texmf-dist/tex/context/interface/keys-en.xml | 16 +
.../texmf-dist/tex/context/interface/keys-fr.xml | 16 +
.../texmf-dist/tex/context/interface/keys-it.xml | 16 +
.../texmf-dist/tex/context/interface/keys-nl.xml | 16 +
.../texmf-dist/tex/context/interface/keys-pe.xml | 16 +
.../texmf-dist/tex/context/interface/keys-ro.xml | 16 +
Master/texmf-dist/tex/context/sample/d-res-01.xml | 50 +
Master/texmf-dist/tex/context/sample/lorem.tex | 11 +
.../texmf-dist/tex/context/test/pdf-x1a-2001.mkiv | 2 +-
.../texmf-dist/tex/context/test/pdf-x1a-2003.mkiv | 2 +-
.../texmf-dist/tex/context/test/pdf-x3-2002.mkiv | 2 +-
.../texmf-dist/tex/context/test/pdf-x3-2003.mkiv | 2 +-
Master/texmf-dist/tex/context/test/pdf-x4.mkiv | 2 +-
Master/texmf-dist/tex/context/test/pdf-x4p.mkiv | 4 +-
.../generic/context/luatex/luatex-basics-gen.lua | 84 +-
.../generic/context/luatex/luatex-basics-nod.lua | 9 +
.../generic/context/luatex/luatex-fonts-ext.lua | 16 +-
.../generic/context/luatex/luatex-fonts-merged.lua | 23233 +++++++--------
.../tex/generic/context/luatex/luatex-fonts.lua | 133 +-
.../generic/context/luatex/luatex-languages.lua | 45 +
.../generic/context/luatex/luatex-languages.tex | 17 +
.../tex/generic/context/luatex/luatex-mplib.tex | 11 +-
.../tex/generic/context/luatex/luatex-plain.tex | 7 +-
.../generic/context/luatex/luatex-swiglib-test.lua | 25 +
.../generic/context/luatex/luatex-swiglib-test.tex | 11 +
.../tex/generic/context/luatex/luatex-swiglib.lua | 62 +
.../tex/generic/context/luatex/luatex-swiglib.tex | 20 +
.../tex/generic/context/luatex/luatex-test.tex | 18 +-
Master/texmf-dist/tex/mptopdf/config/mptopdf.ini | 6 -
Master/tlpkg/libexec/ctan2tds | 4 +-
Master/tlpkg/libexec/mptopdf-extract | 8 +
1044 files changed, 155180 insertions(+), 103751 deletions(-)
create mode 100644 Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-web.lua
create mode 100644 Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-xml-script.lua
delete mode 100644 Master/texmf-dist/doc/context/bib/bibmod-doc.pdf
delete mode 100644 Master/texmf-dist/doc/context/bib/bibmod-doc.tex
create mode 100644 Master/texmf-dist/doc/context/scripts/mkii/ctxtools.html
create mode 100644 Master/texmf-dist/doc/context/scripts/mkii/ctxtools.man
create mode 100644 Master/texmf-dist/doc/context/scripts/mkii/ctxtools.xml
create mode 100644 Master/texmf-dist/doc/context/scripts/mkii/imgtopdf.html
create mode 100644 Master/texmf-dist/doc/context/scripts/mkii/imgtopdf.man
create mode 100644 Master/texmf-dist/doc/context/scripts/mkii/imgtopdf.xml
create mode 100644 Master/texmf-dist/doc/context/scripts/mkii/mptopdf.html
create mode 100644 Master/texmf-dist/doc/context/scripts/mkii/mptopdf.xml
create mode 100644 Master/texmf-dist/doc/context/scripts/mkii/pdftools.html
create mode 100644 Master/texmf-dist/doc/context/scripts/mkii/pdftools.man
create mode 100644 Master/texmf-dist/doc/context/scripts/mkii/pdftools.xml
create mode 100644 Master/texmf-dist/doc/context/scripts/mkii/pstopdf.html
create mode 100644 Master/texmf-dist/doc/context/scripts/mkii/pstopdf.man
create mode 100644 Master/texmf-dist/doc/context/scripts/mkii/pstopdf.xml
create mode 100644 Master/texmf-dist/doc/context/scripts/mkii/rlxtools.html
create mode 100644 Master/texmf-dist/doc/context/scripts/mkii/rlxtools.man
create mode 100644 Master/texmf-dist/doc/context/scripts/mkii/rlxtools.xml
create mode 100644 Master/texmf-dist/doc/context/scripts/mkii/texexec.html
create mode 100644 Master/texmf-dist/doc/context/scripts/mkii/texexec.man
create mode 100644 Master/texmf-dist/doc/context/scripts/mkii/texexec.xml
create mode 100644 Master/texmf-dist/doc/context/scripts/mkii/texmfstart.html
create mode 100644 Master/texmf-dist/doc/context/scripts/mkii/texmfstart.man
create mode 100644 Master/texmf-dist/doc/context/scripts/mkii/texmfstart.xml
create mode 100644 Master/texmf-dist/doc/context/scripts/mkii/textools.html
create mode 100644 Master/texmf-dist/doc/context/scripts/mkii/textools.man
create mode 100644 Master/texmf-dist/doc/context/scripts/mkii/textools.xml
create mode 100644 Master/texmf-dist/doc/context/scripts/mkii/texutil.html
create mode 100644 Master/texmf-dist/doc/context/scripts/mkii/texutil.man
create mode 100644 Master/texmf-dist/doc/context/scripts/mkii/texutil.xml
create mode 100644 Master/texmf-dist/doc/context/scripts/mkii/tmftools.html
create mode 100644 Master/texmf-dist/doc/context/scripts/mkii/tmftools.man
create mode 100644 Master/texmf-dist/doc/context/scripts/mkii/tmftools.xml
create mode 100644 Master/texmf-dist/doc/context/scripts/mkii/xmltools.html
create mode 100644 Master/texmf-dist/doc/context/scripts/mkii/xmltools.man
create mode 100644 Master/texmf-dist/doc/context/scripts/mkii/xmltools.xml
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/context.html
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/context.man
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/context.xml
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/luatools.html
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/luatools.man
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/luatools.xml
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-babel.html
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-babel.man
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-babel.xml
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-base.html
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-base.man
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-base.xml
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-cache.html
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-cache.man
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-cache.xml
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-chars.html
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-chars.man
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-chars.xml
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-check.html
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-check.man
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-check.xml
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-colors.html
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-colors.man
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-colors.xml
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-context.html
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-context.man
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-context.xml
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-epub.html
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-epub.man
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-epub.xml
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-fcd.html
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-fcd.man
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-fcd.xml
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-flac.html
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-flac.man
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-flac.xml
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-fonts.html
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-fonts.man
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-fonts.xml
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-grep.html
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-grep.man
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-grep.xml
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-interface.html
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-interface.man
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-interface.xml
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-metapost.html
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-metapost.man
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-metapost.xml
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-metatex.html
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-metatex.man
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-metatex.xml
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-modules.html
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-modules.man
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-modules.xml
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-package.html
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-package.man
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-package.xml
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-patterns.html
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-patterns.man
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-patterns.xml
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-pdf.html
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-pdf.man
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-pdf.xml
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-profile.html
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-profile.man
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-profile.xml
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-rsync.html
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-rsync.man
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-rsync.xml
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-scite.html
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-scite.man
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-scite.xml
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-server.html
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-server.man
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-server.xml
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-texworks.html
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-texworks.man
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-texworks.xml
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-timing.html
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-timing.man
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-timing.xml
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-tools.html
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-tools.man
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-tools.xml
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-unzip.html
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-unzip.man
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-unzip.xml
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-update.html
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-update.man
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-update.xml
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-watch.html
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-watch.man
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtx-watch.xml
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtxrun.html
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtxrun.man
create mode 100644 Master/texmf-dist/doc/context/scripts/mkiv/mtxrun.xml
delete mode 100644 Master/texmf-dist/doc/context/scripts/perl/texshow.1
delete mode 100644 Master/texmf-dist/doc/context/scripts/perl/texshow.html
create mode 100644 Master/texmf-dist/doc/man/man1/luatools.1
create mode 100644 Master/texmf-dist/doc/man/man1/luatools.man1.pdf
create mode 100644 Master/texmf-dist/doc/man/man1/mtx-babel.1
create mode 100644 Master/texmf-dist/doc/man/man1/mtx-babel.man1.pdf
create mode 100644 Master/texmf-dist/doc/man/man1/mtx-base.1
create mode 100644 Master/texmf-dist/doc/man/man1/mtx-base.man1.pdf
create mode 100644 Master/texmf-dist/doc/man/man1/mtx-cache.1
create mode 100644 Master/texmf-dist/doc/man/man1/mtx-cache.man1.pdf
create mode 100644 Master/texmf-dist/doc/man/man1/mtx-chars.1
create mode 100644 Master/texmf-dist/doc/man/man1/mtx-chars.man1.pdf
create mode 100644 Master/texmf-dist/doc/man/man1/mtx-check.1
create mode 100644 Master/texmf-dist/doc/man/man1/mtx-check.man1.pdf
create mode 100644 Master/texmf-dist/doc/man/man1/mtx-colors.1
create mode 100644 Master/texmf-dist/doc/man/man1/mtx-colors.man1.pdf
create mode 100644 Master/texmf-dist/doc/man/man1/mtx-context.1
create mode 100644 Master/texmf-dist/doc/man/man1/mtx-context.man1.pdf
create mode 100644 Master/texmf-dist/doc/man/man1/mtx-epub.1
create mode 100644 Master/texmf-dist/doc/man/man1/mtx-epub.man1.pdf
create mode 100644 Master/texmf-dist/doc/man/man1/mtx-fcd.1
create mode 100644 Master/texmf-dist/doc/man/man1/mtx-fcd.man1.pdf
create mode 100644 Master/texmf-dist/doc/man/man1/mtx-flac.1
create mode 100644 Master/texmf-dist/doc/man/man1/mtx-flac.man1.pdf
create mode 100644 Master/texmf-dist/doc/man/man1/mtx-fonts.1
create mode 100644 Master/texmf-dist/doc/man/man1/mtx-fonts.man1.pdf
create mode 100644 Master/texmf-dist/doc/man/man1/mtx-grep.1
create mode 100644 Master/texmf-dist/doc/man/man1/mtx-grep.man1.pdf
create mode 100644 Master/texmf-dist/doc/man/man1/mtx-interface.1
create mode 100644 Master/texmf-dist/doc/man/man1/mtx-interface.man1.pdf
create mode 100644 Master/texmf-dist/doc/man/man1/mtx-metapost.1
create mode 100644 Master/texmf-dist/doc/man/man1/mtx-metapost.man1.pdf
create mode 100644 Master/texmf-dist/doc/man/man1/mtx-metatex.1
create mode 100644 Master/texmf-dist/doc/man/man1/mtx-metatex.man1.pdf
create mode 100644 Master/texmf-dist/doc/man/man1/mtx-modules.1
create mode 100644 Master/texmf-dist/doc/man/man1/mtx-modules.man1.pdf
create mode 100644 Master/texmf-dist/doc/man/man1/mtx-package.1
create mode 100644 Master/texmf-dist/doc/man/man1/mtx-package.man1.pdf
create mode 100644 Master/texmf-dist/doc/man/man1/mtx-patterns.1
create mode 100644 Master/texmf-dist/doc/man/man1/mtx-patterns.man1.pdf
create mode 100644 Master/texmf-dist/doc/man/man1/mtx-pdf.1
create mode 100644 Master/texmf-dist/doc/man/man1/mtx-pdf.man1.pdf
create mode 100644 Master/texmf-dist/doc/man/man1/mtx-profile.1
create mode 100644 Master/texmf-dist/doc/man/man1/mtx-profile.man1.pdf
create mode 100644 Master/texmf-dist/doc/man/man1/mtx-rsync.1
create mode 100644 Master/texmf-dist/doc/man/man1/mtx-rsync.man1.pdf
create mode 100644 Master/texmf-dist/doc/man/man1/mtx-scite.1
create mode 100644 Master/texmf-dist/doc/man/man1/mtx-scite.man1.pdf
create mode 100644 Master/texmf-dist/doc/man/man1/mtx-server.1
create mode 100644 Master/texmf-dist/doc/man/man1/mtx-server.man1.pdf
create mode 100644 Master/texmf-dist/doc/man/man1/mtx-texworks.1
create mode 100644 Master/texmf-dist/doc/man/man1/mtx-texworks.man1.pdf
create mode 100644 Master/texmf-dist/doc/man/man1/mtx-timing.1
create mode 100644 Master/texmf-dist/doc/man/man1/mtx-timing.man1.pdf
create mode 100644 Master/texmf-dist/doc/man/man1/mtx-tools.1
create mode 100644 Master/texmf-dist/doc/man/man1/mtx-tools.man1.pdf
create mode 100644 Master/texmf-dist/doc/man/man1/mtx-unzip.1
create mode 100644 Master/texmf-dist/doc/man/man1/mtx-unzip.man1.pdf
create mode 100644 Master/texmf-dist/doc/man/man1/mtx-update.1
create mode 100644 Master/texmf-dist/doc/man/man1/mtx-update.man1.pdf
create mode 100644 Master/texmf-dist/doc/man/man1/mtx-watch.1
create mode 100644 Master/texmf-dist/doc/man/man1/mtx-watch.man1.pdf
create mode 100644 Master/texmf-dist/doc/man/man1/mtxrun.1
create mode 100644 Master/texmf-dist/doc/man/man1/mtxrun.man1.pdf
delete mode 100644 Master/texmf-dist/fonts/map/pdftex/context/koeieletters.map
delete mode 100644 Master/texmf-dist/fonts/opentype/context/tests/texmfhome.otf
create mode 100644 Master/texmf-dist/fonts/pfm/hoekwater/context/contnav.pfm
create mode 100644 Master/texmf-dist/metapost/context/base/mp-grap.mpiv
create mode 100644 Master/texmf-dist/scripts/context/lua/mtx-context.xml
create mode 100644 Master/texmf-dist/scripts/context/lua/mtx-fcd.lua
create mode 100644 Master/texmf-dist/scripts/context/lua/mtx-mk-help.lua
create mode 100644 Master/texmf-dist/scripts/context/lua/mtxlibs.lua
delete mode 100644 Master/texmf-dist/scripts/context/ruby/fcd_start.rb
delete mode 100644 Master/texmf-dist/scripts/context/ruby/mpstools.rb
delete mode 100644 Master/texmf-dist/scripts/context/ruby/texsync.rb
create mode 100755 Master/texmf-dist/scripts/context/stubs/mswin/ctxtools.exe
delete mode 100755 Master/texmf-dist/scripts/context/stubs/mswin/mptopdf.exe
create mode 100755 Master/texmf-dist/scripts/context/stubs/mswin/pstopdf.exe
create mode 100755 Master/texmf-dist/scripts/context/stubs/mswin/setuptex.bat
create mode 100644 Master/texmf-dist/scripts/context/stubs/unix/ctxtools
create mode 100644 Master/texmf-dist/scripts/context/stubs/unix/pstopdf
create mode 100644 Master/texmf-dist/tex/context/base/attr-mkr.lua
create mode 100644 Master/texmf-dist/tex/context/base/attr-mkr.mkiv
delete mode 100644 Master/texmf-dist/tex/context/base/buff-par.mkiv
create mode 100644 Master/texmf-dist/tex/context/base/buff-par.mkvi
create mode 100644 Master/texmf-dist/tex/context/base/cldf-prs.lua
create mode 100644 Master/texmf-dist/tex/context/base/cont-nop.mkiv
create mode 100644 Master/texmf-dist/tex/context/base/cont-yes.mkiv
delete mode 100644 Master/texmf-dist/tex/context/base/context.todo
create mode 100644 Master/texmf-dist/tex/context/base/core-ctx.ctx
delete mode 100644 Master/texmf-dist/tex/context/base/core-fnt.mkiv
delete mode 100644 Master/texmf-dist/tex/context/base/core-mis.mkiv
delete mode 100644 Master/texmf-dist/tex/context/base/core-var.mkiv
create mode 100644 Master/texmf-dist/tex/context/base/font-afk.lua
create mode 100644 Master/texmf-dist/tex/context/base/font-aux.mkvi
create mode 100644 Master/texmf-dist/tex/context/base/font-chk.mkiv
delete mode 100644 Master/texmf-dist/tex/context/base/font-gds.mkiv
create mode 100644 Master/texmf-dist/tex/context/base/font-gds.mkvi
create mode 100644 Master/texmf-dist/tex/context/base/font-hsh.lua
create mode 100644 Master/texmf-dist/tex/context/base/font-nod.lua
create mode 100644 Master/texmf-dist/tex/context/base/font-odk.lua
create mode 100644 Master/texmf-dist/tex/context/base/font-odv.lua
create mode 100644 Master/texmf-dist/tex/context/base/font-otx.lua
create mode 100644 Master/texmf-dist/tex/context/base/font-sol.lua
create mode 100644 Master/texmf-dist/tex/context/base/font-sol.mkvi
create mode 100644 Master/texmf-dist/tex/context/base/l-function.lua
create mode 100644 Master/texmf-dist/tex/context/base/l-lua.lua
create mode 100644 Master/texmf-dist/tex/context/base/lang-frd.mkiv
create mode 100644 Master/texmf-dist/tex/context/base/lang-frq-de.lua
create mode 100644 Master/texmf-dist/tex/context/base/lang-frq-en.lua
create mode 100644 Master/texmf-dist/tex/context/base/lang-frq-nl.lua
create mode 100644 Master/texmf-dist/tex/context/base/lang-frq.mkiv
create mode 100644 Master/texmf-dist/tex/context/base/m-ipsum.mkiv
create mode 100644 Master/texmf-dist/tex/context/base/m-json.mkiv
create mode 100644 Master/texmf-dist/tex/context/base/m-nodechart.mkvi
create mode 100644 Master/texmf-dist/tex/context/base/m-oldfun.mkiv
create mode 100644 Master/texmf-dist/tex/context/base/m-oldnum.mkiv
create mode 100644 Master/texmf-dist/tex/context/base/m-spreadsheet.lua
create mode 100644 Master/texmf-dist/tex/context/base/math-fbk.lua
create mode 100644 Master/texmf-dist/tex/context/base/math-fen.mkiv
create mode 100644 Master/texmf-dist/tex/context/base/math-mis.mkiv
create mode 100644 Master/texmf-dist/tex/context/base/math-stc.mkvi
create mode 100644 Master/texmf-dist/tex/context/base/math-ttv.lua
create mode 100644 Master/texmf-dist/tex/context/base/meta-grd.mkiv
create mode 100644 Master/texmf-dist/tex/context/base/mtx-context-copy.tex
create mode 100644 Master/texmf-dist/tex/context/base/mult-fun.lua
delete mode 100644 Master/texmf-dist/tex/context/base/node-par.lua
delete mode 100644 Master/texmf-dist/tex/context/base/node-par.mkiv
create mode 100644 Master/texmf-dist/tex/context/base/node-snp.lua
delete mode 100644 Master/texmf-dist/tex/context/base/node-spl.lua
delete mode 100644 Master/texmf-dist/tex/context/base/node-spl.mkiv
create mode 100644 Master/texmf-dist/tex/context/base/pack-cut.mkiv
create mode 100644 Master/texmf-dist/tex/context/base/page-inj.lua
create mode 100644 Master/texmf-dist/tex/context/base/page-inj.mkvi
create mode 100644 Master/texmf-dist/tex/context/base/page-ins.lua
delete mode 100644 Master/texmf-dist/tex/context/base/page-mis.lua
delete mode 100644 Master/texmf-dist/tex/context/base/page-mis.mkiv
create mode 100644 Master/texmf-dist/tex/context/base/page-mix.lua
create mode 100644 Master/texmf-dist/tex/context/base/page-mix.mkiv
create mode 100644 Master/texmf-dist/tex/context/base/page-pst.lua
create mode 100644 Master/texmf-dist/tex/context/base/page-pst.mkiv
delete mode 100644 Master/texmf-dist/tex/context/base/page-sel.mkiv
create mode 100644 Master/texmf-dist/tex/context/base/page-sel.mkvi
create mode 100644 Master/texmf-dist/tex/context/base/s-lan-06.mkiv
create mode 100644 Master/texmf-dist/tex/context/base/s-mat-20.mkiv
create mode 100644 Master/texmf-dist/tex/context/base/spac-cha.mkiv
create mode 100644 Master/texmf-dist/tex/context/base/spac-flr.mkiv
delete mode 100644 Master/texmf-dist/tex/context/base/supp-ali.mkiv
delete mode 100644 Master/texmf-dist/tex/context/base/supp-fun.mkiv
delete mode 100644 Master/texmf-dist/tex/context/base/supp-num.mkiv
create mode 100644 Master/texmf-dist/tex/context/base/symb-imp-cc.mkiv
create mode 100644 Master/texmf-dist/tex/context/base/tabl-mis.mkiv
create mode 100644 Master/texmf-dist/tex/context/base/trac-ctx.lua
create mode 100644 Master/texmf-dist/tex/context/base/trac-ctx.mkiv
create mode 100644 Master/texmf-dist/tex/context/base/trac-exp.lua
create mode 100644 Master/texmf-dist/tex/context/base/trac-jus.lua
create mode 100644 Master/texmf-dist/tex/context/base/trac-jus.mkiv
create mode 100644 Master/texmf-dist/tex/context/base/trac-vis.lua
create mode 100644 Master/texmf-dist/tex/context/base/trac-xml.lua
create mode 100644 Master/texmf-dist/tex/context/base/typo-bld.lua
create mode 100644 Master/texmf-dist/tex/context/base/typo-bld.mkiv
create mode 100644 Master/texmf-dist/tex/context/base/typo-itm.mkiv
create mode 100644 Master/texmf-dist/tex/context/base/typo-lan.lua
create mode 100644 Master/texmf-dist/tex/context/base/typo-lan.mkiv
create mode 100644 Master/texmf-dist/tex/context/base/util-env.lua
create mode 100644 Master/texmf-dist/tex/context/base/util-jsn.lua
create mode 100644 Master/texmf-dist/tex/context/base/util-lib.lua
create mode 100644 Master/texmf-dist/tex/context/base/util-ran.lua
create mode 100644 Master/texmf-dist/tex/context/base/util-sql-imp-client.lua
create mode 100644 Master/texmf-dist/tex/context/base/util-sql-imp-library.lua
create mode 100644 Master/texmf-dist/tex/context/base/util-sql-imp-swiglib.lua
create mode 100644 Master/texmf-dist/tex/context/base/util-sql-loggers.lua
create mode 100644 Master/texmf-dist/tex/context/base/util-sql-sessions.lua
create mode 100644 Master/texmf-dist/tex/context/base/util-sql-tickets.lua
create mode 100644 Master/texmf-dist/tex/context/base/util-sql-users.lua
create mode 100644 Master/texmf-dist/tex/context/base/util-sql.lua
create mode 100644 Master/texmf-dist/tex/context/base/util-sta.lua
create mode 100644 Master/texmf-dist/tex/context/base/util-tpl.lua
create mode 100644 Master/texmf-dist/tex/context/base/x-steps.mkiv
create mode 100644 Master/texmf-dist/tex/context/base/x-xfdf.mkiv
delete mode 100644 Master/texmf-dist/tex/context/colors/icc/colorprofiles.lua
delete mode 100644 Master/texmf-dist/tex/context/colors/icc/colorprofiles.xml
create mode 100644 Master/texmf-dist/tex/context/colors/icc/context/colorprofiles.lua
create mode 100644 Master/texmf-dist/tex/context/colors/icc/context/colorprofiles.xml
delete mode 100644 Master/texmf-dist/tex/context/config/cont-de.ini
delete mode 100644 Master/texmf-dist/tex/context/config/cont-en.ini
delete mode 100644 Master/texmf-dist/tex/context/config/cont-fr.ini
delete mode 100644 Master/texmf-dist/tex/context/config/cont-it.ini
delete mode 100644 Master/texmf-dist/tex/context/config/cont-nl.ini
delete mode 100644 Master/texmf-dist/tex/context/config/cont-ro.ini
create mode 100644 Master/texmf-dist/tex/context/fonts/cc-icons.lfg
create mode 100644 Master/texmf-dist/tex/context/fonts/texgyre.lfg
create mode 100644 Master/texmf-dist/tex/context/sample/d-res-01.xml
create mode 100644 Master/texmf-dist/tex/context/sample/lorem.tex
create mode 100644 Master/texmf-dist/tex/generic/context/luatex/luatex-languages.lua
create mode 100644 Master/texmf-dist/tex/generic/context/luatex/luatex-languages.tex
create mode 100644 Master/texmf-dist/tex/generic/context/luatex/luatex-swiglib-test.lua
create mode 100644 Master/texmf-dist/tex/generic/context/luatex/luatex-swiglib-test.tex
create mode 100644 Master/texmf-dist/tex/generic/context/luatex/luatex-swiglib.lua
create mode 100644 Master/texmf-dist/tex/generic/context/luatex/luatex-swiglib.tex
delete mode 100644 Master/texmf-dist/tex/mptopdf/config/mptopdf.ini
(limited to 'Master')
diff --git a/Master/texmf-dist/bibtex/bst/context/cont-ab.bst b/Master/texmf-dist/bibtex/bst/context/cont-ab.bst
index c524ff8ee08..e09da7ca56b 100644
--- a/Master/texmf-dist/bibtex/bst/context/cont-ab.bst
+++ b/Master/texmf-dist/bibtex/bst/context/cont-ab.bst
@@ -618,6 +618,7 @@ FUNCTION {misc}
format.t.title
format.key
"" "\city" address do.out
+ "" "\day" day do.out
"" "\month" month do.out
"" "\pubname" publisher do.out
"" "\howpublished" howpublished do.out
diff --git a/Master/texmf-dist/bibtex/bst/context/cont-au.bst b/Master/texmf-dist/bibtex/bst/context/cont-au.bst
index 2eba98b0ae2..d0b87186c66 100644
--- a/Master/texmf-dist/bibtex/bst/context/cont-au.bst
+++ b/Master/texmf-dist/bibtex/bst/context/cont-au.bst
@@ -618,6 +618,7 @@ FUNCTION {misc}
format.t.title
format.key
"" "\city" address do.out
+ "" "\day" day do.out
"" "\month" month do.out
"" "\pubname" publisher do.out
"" "\howpublished" howpublished do.out
diff --git a/Master/texmf-dist/bibtex/bst/context/cont-no.bst b/Master/texmf-dist/bibtex/bst/context/cont-no.bst
index dbeb8a45dcc..393d13db812 100644
--- a/Master/texmf-dist/bibtex/bst/context/cont-no.bst
+++ b/Master/texmf-dist/bibtex/bst/context/cont-no.bst
@@ -618,6 +618,7 @@ FUNCTION {misc}
format.t.title
format.key
"" "\city" address do.out
+ "" "\day" day do.out
"" "\month" month do.out
"" "\pubname" publisher do.out
"" "\howpublished" howpublished do.out
diff --git a/Master/texmf-dist/bibtex/bst/context/cont-ti.bst b/Master/texmf-dist/bibtex/bst/context/cont-ti.bst
index 734cbb4b6f3..34175a0ba84 100644
--- a/Master/texmf-dist/bibtex/bst/context/cont-ti.bst
+++ b/Master/texmf-dist/bibtex/bst/context/cont-ti.bst
@@ -618,6 +618,7 @@ FUNCTION {misc}
format.t.title
format.key
"" "\city" address do.out
+ "" "\day" day do.out
"" "\month" month do.out
"" "\pubname" publisher do.out
"" "\howpublished" howpublished do.out
diff --git a/Master/texmf-dist/context/data/scite/lexers/data/scite-context-data-context.lua b/Master/texmf-dist/context/data/scite/lexers/data/scite-context-data-context.lua
index aa36277b72b..dc44a6a597f 100644
--- a/Master/texmf-dist/context/data/scite/lexers/data/scite-context-data-context.lua
+++ b/Master/texmf-dist/context/data/scite/lexers/data/scite-context-data-context.lua
@@ -1,4 +1,4 @@
return {
- ["constants"]={ "zerocount", "minusone", "minustwo", "plusone", "plustwo", "plusthree", "plusfour", "plusfive", "plussix", "plusseven", "pluseight", "plusnine", "plusten", "plussixteen", "plushundred", "plusthousand", "plustenthousand", "plustwentythousand", "medcard", "maxcard", "zeropoint", "onepoint", "halfapoint", "onebasepoint", "maxdimen", "scaledpoint", "thousandpoint", "points", "halfpoint", "zeroskip", "pluscxxvii", "pluscxxviii", "pluscclv", "pluscclvi", "normalpagebox", "endoflinetoken", "outputnewlinechar", "emptytoks", "empty", "undefined", "voidbox", "emptybox", "emptyvbox", "emptyhbox", "bigskipamount", "medskipamount", "smallskipamount", "fmtname", "fmtversion", "texengine", "texenginename", "texengineversion", "luatexengine", "pdftexengine", "xetexengine", "unknownengine", "etexversion", "pdftexversion", "xetexversion", "xetexrevision", "activecatcode", "bgroup", "egroup", "endline", "conditionaltrue", "conditionalfalse", "attributeunsetvalue", "uprotationangle", "rightrotationangle", "downrotationangle", "leftrotationangle", "inicatcodes", "ctxcatcodes", "texcatcodes", "notcatcodes", "txtcatcodes", "vrbcatcodes", "prtcatcodes", "nilcatcodes", "luacatcodes", "tpacatcodes", "tpbcatcodes", "xmlcatcodes", "escapecatcode", "begingroupcatcode", "endgroupcatcode", "mathshiftcatcode", "alignmentcatcode", "endoflinecatcode", "parametercatcode", "superscriptcatcode", "subscriptcatcode", "ignorecatcode", "spacecatcode", "lettercatcode", "othercatcode", "activecatcode", "commentcatcode", "invalidcatcode", "tabasciicode", "newlineasciicode", "formfeedasciicode", "endoflineasciicode", "endoffileasciicode", "spaceasciicode", "hashasciicode", "dollarasciicode", "commentasciicode", "ampersandasciicode", "colonasciicode", "backslashasciicode", "circumflexasciicode", "underscoreasciicode", "leftbraceasciicode", "barasciicode", "rightbraceasciicode", "tildeasciicode", "delasciicode", "lessthanasciicode", "morethanasciicode", "doublecommentsignal", "atsignasciicode", "exclamationmarkasciicode", "questionmarkasciicode", "doublequoteasciicode", "singlequoteasciicode", "forwardslashasciicode", "primeasciicode", "activemathcharcode", "activetabtoken", "activeformfeedtoken", "activeendoflinetoken", "batchmodecode", "nonstopmodecode", "scrollmodecode", "errorstopmodecode", "bottomlevelgroupcode", "simplegroupcode", "hboxgroupcode", "adjustedhboxgroupcode", "vboxgroupcode", "vtopgroupcode", "aligngroupcode", "noaligngroupcode", "outputgroupcode", "mathgroupcode", "discretionarygroupcode", "insertgroupcode", "vcentergroupcode", "mathchoicegroupcode", "semisimplegroupcode", "mathshiftgroupcode", "mathleftgroupcode", "vadjustgroupcode", "charnodecode", "hlistnodecode", "vlistnodecode", "rulenodecode", "insertnodecode", "marknodecode", "adjustnodecode", "ligaturenodecode", "discretionarynodecode", "whatsitnodecode", "mathnodecode", "gluenodecode", "kernnodecode", "penaltynodecode", "unsetnodecode", "mathsnodecode", "charifcode", "catifcode", "numifcode", "dimifcode", "oddifcode", "vmodeifcode", "hmodeifcode", "mmodeifcode", "innerifcode", "voidifcode", "hboxifcode", "vboxifcode", "xifcode", "eofifcode", "trueifcode", "falseifcode", "caseifcode", "definedifcode", "csnameifcode", "fontcharifcode", "fontslantperpoint", "fontinterwordspace", "fontinterwordstretch", "fontinterwordshrink", "fontexheight", "fontemwidth", "fontextraspace", "slantperpoint", "interwordspace", "interwordstretch", "interwordshrink", "exheight", "emwidth", "extraspace", "mathsupdisplay", "mathsupnormal", "mathsupcramped", "mathsubnormal", "mathsubcombined", "mathaxisheight", "startmode", "stopmode", "startnotmode", "stopnotmode", "startmodeset", "stopmodeset", "doifmode", "doifmodeelse", "doifnotmode", "startallmodes", "stopallmodes", "startnotallmodes", "stopnotallmodes", "doifallmodes", "doifallmodeselse", "doifnotallmodes", "startenvironment", "stopenvironment", "environment", "startcomponent", "stopcomponent", "component", "startproduct", "stopproduct", "product", "startproject", "stopproject", "project", "starttext", "stoptext", "startnotext", "stopnotext", "startdocument", "stopdocument", "documentvariable", "startmodule", "stopmodule", "usemodule", "startTEXpage", "stopTEXpage", "enablemode", "disablemode", "preventmode", "pushmode", "popmode", "typescriptone", "typescripttwo", "typescriptthree", "mathsizesuffix", "mathordcode", "mathopcode", "mathbincode", "mathrelcode", "mathopencode", "mathclosecode", "mathpunctcode", "mathalphacode", "mathinnercode", "mathnothingcode", "mathlimopcode", "mathnolopcode", "mathboxcode", "mathchoicecode", "mathaccentcode", "mathradicalcode", "constantnumber", "constantnumberargument", "constantdimen", "constantdimenargument", "constantemptyargument", "continueifinputfile" },
- ["helpers"]={ "startsetups", "stopsetups", "startxmlsetups", "stopxmlsetups", "startluasetups", "stopluasetups", "starttexsetups", "stoptexsetups", "startrawsetups", "stoprawsetups", "startlocalsetups", "stoplocalsetups", "starttexdefinition", "stoptexdefinition", "starttexcode", "stoptexcode", "doifsetupselse", "doifsetups", "doifnotsetups", "setup", "setups", "texsetup", "xmlsetup", "luasetup", "directsetup", "newmode", "setmode", "resetmode", "newsystemmode", "setsystemmode", "resetsystemmode", "pushsystemmode", "popsystemmode", "booleanmodevalue", "newcount", "newdimen", "newskip", "newmuskip", "newbox", "newtoks", "newread", "newwrite", "newmarks", "newinsert", "newattribute", "newif", "newlanguage", "newfamily", "newfam", "newhelp", "then", "donothing", "dontcomplain", "donetrue", "donefalse", "htdp", "unvoidbox", "vfilll", "mathbox", "mathlimop", "mathnolop", "mathnothing", "mathalpha", "currentcatcodetable", "defaultcatcodetable", "catcodetablename", "newcatcodetable", "startcatcodetable", "stopcatcodetable", "startextendcatcodetable", "stopextendcatcodetable", "pushcatcodetable", "popcatcodetable", "restorecatcodes", "setcatcodetable", "letcatcodecommand", "defcatcodecommand", "uedcatcodecommand", "hglue", "vglue", "hfillneg", "vfillneg", "hfilllneg", "vfilllneg", "ruledhss", "ruledhfil", "ruledhfill", "ruledhfilneg", "ruledhfillneg", "normalhfillneg", "ruledvss", "ruledvfil", "ruledvfill", "ruledvfilneg", "ruledvfillneg", "normalvfillneg", "ruledhbox", "ruledvbox", "ruledvtop", "ruledvcenter", "ruledhskip", "ruledvskip", "ruledkern", "ruledmskip", "ruledmkern", "ruledhglue", "ruledvglue", "normalhglue", "normalvglue", "ruledpenalty", "scratchcounter", "globalscratchcounter", "scratchdimen", "globalscratchdimen", "scratchskip", "globalscratchskip", "scratchmuskip", "globalscratchmuskip", "scratchtoks", "globalscratchtoks", "scratchbox", "globalscratchbox", "nextbox", "dowithnextbox", "dowithnextboxcs", "dowithnextboxcontent", "dowithnextboxcontentcs", "scratchwidth", "scratchheight", "scratchdepth", "scratchoffset", "scratchdistance", "scratchhsize", "scratchvsize", "scratchcounterone", "scratchcountertwo", "scratchcounterthree", "scratchdimenone", "scratchdimentwo", "scratchdimenthree", "scratchskipone", "scratchskiptwo", "scratchskipthree", "scratchmuskipone", "scratchmuskiptwo", "scratchmuskipthree", "scratchtoksone", "scratchtokstwo", "scratchtoksthree", "scratchboxone", "scratchboxtwo", "scratchboxthree", "doif", "doifnot", "doifelse", "doifinset", "doifnotinset", "doifinsetelse", "doifnextcharelse", "doifnextoptionalelse", "doifnextbgroupelse", "doifnextparenthesiselse", "doiffastoptionalcheckelse", "doifundefinedelse", "doifdefinedelse", "doifundefined", "doifdefined", "doifelsevalue", "doifvalue", "doifnotvalue", "doifnothing", "doifsomething", "doifelsenothing", "doifsomethingelse", "doifvaluenothing", "doifvaluesomething", "doifelsevaluenothing", "doifdimensionelse", "doifnumberelse", "doifcommonelse", "doifcommon", "doifnotcommon", "doifinstring", "doifnotinstring", "doifinstringelse", "doifassignmentelse", "tracingall", "tracingnone", "loggingall", "appendtoks", "prependtoks", "appendtotoks", "prependtotoks", "to", "endgraf", "empty", "null", "space", "quad", "enspace", "obeyspaces", "obeylines", "normalspace", "executeifdefined", "singleexpandafter", "doubleexpandafter", "tripleexpandafter", "dontleavehmode", "removelastspace", "removeunwantedspaces", "wait", "writestatus", "define", "redefine", "setmeasure", "setemeasure", "setgmeasure", "setxmeasure", "definemeasure", "measure", "getvalue", "setvalue", "setevalue", "setgvalue", "setxvalue", "letvalue", "letgvalue", "resetvalue", "undefinevalue", "ignorevalue", "setuvalue", "setuevalue", "setugvalue", "setuxvalue", "globallet", "glet", "getparameters", "geteparameters", "getgparameters", "getxparameters", "forgetparameters", "copyparameters", "processcommalist", "processcommacommand", "quitcommalist", "quitprevcommalist", "processaction", "processallactions", "processfirstactioninset", "processallactionsinset", "unexpanded", "expanded", "startexpanded", "stopexpanded", "protected", "protect", "unprotect", "firstofoneargument", "firstoftwoarguments", "secondoftwoarguments", "firstofthreearguments", "secondofthreearguments", "thirdofthreearguments", "firstoffourarguments", "secondoffourarguments", "thirdoffourarguments", "fourthoffourarguments", "firstoffivearguments", "secondoffivearguments", "thirdoffivearguments", "fourthoffivearguments", "fifthoffivearguments", "firstofsixarguments", "secondofsixarguments", "thirdofsixarguments", "fourthofsixarguments", "fifthofsixarguments", "sixthofsixarguments", "firstofoneunexpanded", "gobbleoneargument", "gobbletwoarguments", "gobblethreearguments", "gobblefourarguments", "gobblefivearguments", "gobblesixarguments", "gobblesevenarguments", "gobbleeightarguments", "gobbleninearguments", "gobbletenarguments", "gobbleoneoptional", "gobbletwooptionals", "gobblethreeoptionals", "gobblefouroptionals", "gobblefiveoptionals", "dorecurse", "doloop", "exitloop", "dostepwiserecurse", "recurselevel", "recursedepth", "dofastloopcs", "newconstant", "setnewconstant", "newconditional", "settrue", "setfalse", "setconstant", "newmacro", "setnewmacro", "newfraction", "dosingleempty", "dodoubleempty", "dotripleempty", "doquadrupleempty", "doquintupleempty", "dosixtupleempty", "doseventupleempty", "dosingleargument", "dodoubleargument", "dotripleargument", "doquadrupleargument", "dosinglegroupempty", "dodoublegroupempty", "dotriplegroupempty", "doquadruplegroupempty", "doquintuplegroupempty", "nopdfcompression", "maximumpdfcompression", "normalpdfcompression", "modulonumber", "dividenumber", "getfirstcharacter", "doiffirstcharelse", "startnointerference", "stopnointerference", "strut", "setstrut", "strutbox", "strutht", "strutdp", "strutwd", "begstrut", "endstrut" },
+ ["constants"]={ "zerocount", "minusone", "minustwo", "plusone", "plustwo", "plusthree", "plusfour", "plusfive", "plussix", "plusseven", "pluseight", "plusnine", "plusten", "plussixteen", "plushundred", "plusthousand", "plustenthousand", "plustwentythousand", "medcard", "maxcard", "zeropoint", "onepoint", "halfapoint", "onebasepoint", "maxdimen", "scaledpoint", "thousandpoint", "points", "halfpoint", "zeroskip", "zeromuskip", "onemuskip", "pluscxxvii", "pluscxxviii", "pluscclv", "pluscclvi", "normalpagebox", "endoflinetoken", "outputnewlinechar", "emptytoks", "empty", "undefined", "voidbox", "emptybox", "emptyvbox", "emptyhbox", "bigskipamount", "medskipamount", "smallskipamount", "fmtname", "fmtversion", "texengine", "texenginename", "texengineversion", "luatexengine", "pdftexengine", "xetexengine", "unknownengine", "etexversion", "pdftexversion", "xetexversion", "xetexrevision", "activecatcode", "bgroup", "egroup", "endline", "conditionaltrue", "conditionalfalse", "attributeunsetvalue", "uprotationangle", "rightrotationangle", "downrotationangle", "leftrotationangle", "inicatcodes", "ctxcatcodes", "texcatcodes", "notcatcodes", "txtcatcodes", "vrbcatcodes", "prtcatcodes", "nilcatcodes", "luacatcodes", "tpacatcodes", "tpbcatcodes", "xmlcatcodes", "escapecatcode", "begingroupcatcode", "endgroupcatcode", "mathshiftcatcode", "alignmentcatcode", "endoflinecatcode", "parametercatcode", "superscriptcatcode", "subscriptcatcode", "ignorecatcode", "spacecatcode", "lettercatcode", "othercatcode", "activecatcode", "commentcatcode", "invalidcatcode", "tabasciicode", "newlineasciicode", "formfeedasciicode", "endoflineasciicode", "endoffileasciicode", "spaceasciicode", "hashasciicode", "dollarasciicode", "commentasciicode", "ampersandasciicode", "colonasciicode", "backslashasciicode", "circumflexasciicode", "underscoreasciicode", "leftbraceasciicode", "barasciicode", "rightbraceasciicode", "tildeasciicode", "delasciicode", "lessthanasciicode", "morethanasciicode", "doublecommentsignal", "atsignasciicode", "exclamationmarkasciicode", "questionmarkasciicode", "doublequoteasciicode", "singlequoteasciicode", "forwardslashasciicode", "primeasciicode", "activemathcharcode", "activetabtoken", "activeformfeedtoken", "activeendoflinetoken", "batchmodecode", "nonstopmodecode", "scrollmodecode", "errorstopmodecode", "bottomlevelgroupcode", "simplegroupcode", "hboxgroupcode", "adjustedhboxgroupcode", "vboxgroupcode", "vtopgroupcode", "aligngroupcode", "noaligngroupcode", "outputgroupcode", "mathgroupcode", "discretionarygroupcode", "insertgroupcode", "vcentergroupcode", "mathchoicegroupcode", "semisimplegroupcode", "mathshiftgroupcode", "mathleftgroupcode", "vadjustgroupcode", "charnodecode", "hlistnodecode", "vlistnodecode", "rulenodecode", "insertnodecode", "marknodecode", "adjustnodecode", "ligaturenodecode", "discretionarynodecode", "whatsitnodecode", "mathnodecode", "gluenodecode", "kernnodecode", "penaltynodecode", "unsetnodecode", "mathsnodecode", "charifcode", "catifcode", "numifcode", "dimifcode", "oddifcode", "vmodeifcode", "hmodeifcode", "mmodeifcode", "innerifcode", "voidifcode", "hboxifcode", "vboxifcode", "xifcode", "eofifcode", "trueifcode", "falseifcode", "caseifcode", "definedifcode", "csnameifcode", "fontcharifcode", "fontslantperpoint", "fontinterwordspace", "fontinterwordstretch", "fontinterwordshrink", "fontexheight", "fontemwidth", "fontextraspace", "slantperpoint", "interwordspace", "interwordstretch", "interwordshrink", "exheight", "emwidth", "extraspace", "mathsupdisplay", "mathsupnormal", "mathsupcramped", "mathsubnormal", "mathsubcombined", "mathaxisheight", "startmode", "stopmode", "startnotmode", "stopnotmode", "startmodeset", "stopmodeset", "doifmode", "doifmodeelse", "doifnotmode", "startallmodes", "stopallmodes", "startnotallmodes", "stopnotallmodes", "doifallmodes", "doifallmodeselse", "doifnotallmodes", "startenvironment", "stopenvironment", "environment", "startcomponent", "stopcomponent", "component", "startproduct", "stopproduct", "product", "startproject", "stopproject", "project", "starttext", "stoptext", "startnotext", "stopnotext", "startdocument", "stopdocument", "documentvariable", "setupdocument", "startmodule", "stopmodule", "usemodule", "usetexmodule", "useluamodule", "startTEXpage", "stopTEXpage", "enablemode", "disablemode", "preventmode", "globalenablemode", "globaldisablemode", "globalpreventmode", "pushmode", "popmode", "typescriptone", "typescripttwo", "typescriptthree", "mathsizesuffix", "mathordcode", "mathopcode", "mathbincode", "mathrelcode", "mathopencode", "mathclosecode", "mathpunctcode", "mathalphacode", "mathinnercode", "mathnothingcode", "mathlimopcode", "mathnolopcode", "mathboxcode", "mathchoicecode", "mathaccentcode", "mathradicalcode", "constantnumber", "constantnumberargument", "constantdimen", "constantdimenargument", "constantemptyargument", "continueifinputfile", "luastringsep", "!!bs", "!!es" },
+ ["helpers"]={ "startsetups", "stopsetups", "startxmlsetups", "stopxmlsetups", "startluasetups", "stopluasetups", "starttexsetups", "stoptexsetups", "startrawsetups", "stoprawsetups", "startlocalsetups", "stoplocalsetups", "starttexdefinition", "stoptexdefinition", "starttexcode", "stoptexcode", "startcontextcode", "stopcontextcode", "doifsetupselse", "doifsetups", "doifnotsetups", "setup", "setups", "texsetup", "xmlsetup", "luasetup", "directsetup", "doifelsecommandhandler", "doifnotcommandhandler", "doifcommandhandler", "newmode", "setmode", "resetmode", "newsystemmode", "setsystemmode", "resetsystemmode", "pushsystemmode", "popsystemmode", "booleanmodevalue", "newcount", "newdimen", "newskip", "newmuskip", "newbox", "newtoks", "newread", "newwrite", "newmarks", "newinsert", "newattribute", "newif", "newlanguage", "newfamily", "newfam", "newhelp", "then", "firstargumentfalse", "firstargumenttrue", "secondargumentfalse", "secondargumenttrue", "thirdargumentfalse", "thirdargumenttrue", "fourthargumentfalse", "fourthargumenttrue", "fifthargumentfalse", "fifthsargumenttrue", "sixthargumentfalse", "sixtsargumenttrue", "doglobal", "dodoglobal", "redoglobal", "resetglobal", "donothing", "dontcomplain", "forgetall", "donetrue", "donefalse", "htdp", "unvoidbox", "hfilll", "vfilll", "mathbox", "mathlimop", "mathnolop", "mathnothing", "mathalpha", "currentcatcodetable", "defaultcatcodetable", "catcodetablename", "newcatcodetable", "startcatcodetable", "stopcatcodetable", "startextendcatcodetable", "stopextendcatcodetable", "pushcatcodetable", "popcatcodetable", "restorecatcodes", "setcatcodetable", "letcatcodecommand", "defcatcodecommand", "uedcatcodecommand", "hglue", "vglue", "hfillneg", "vfillneg", "hfilllneg", "vfilllneg", "ruledhss", "ruledhfil", "ruledhfill", "ruledhfilneg", "ruledhfillneg", "normalhfillneg", "ruledvss", "ruledvfil", "ruledvfill", "ruledvfilneg", "ruledvfillneg", "normalvfillneg", "ruledhbox", "ruledvbox", "ruledvtop", "ruledvcenter", "ruledhskip", "ruledvskip", "ruledkern", "ruledmskip", "ruledmkern", "ruledhglue", "ruledvglue", "normalhglue", "normalvglue", "ruledpenalty", "filledhboxb", "filledhboxr", "filledhboxg", "filledhboxc", "filledhboxm", "filledhboxy", "filledhboxk", "scratchcounter", "globalscratchcounter", "scratchdimen", "globalscratchdimen", "scratchskip", "globalscratchskip", "scratchmuskip", "globalscratchmuskip", "scratchtoks", "globalscratchtoks", "scratchbox", "globalscratchbox", "availablehsize", "localhsize", "setlocalhsize", "nextbox", "dowithnextbox", "dowithnextboxcs", "dowithnextboxcontent", "dowithnextboxcontentcs", "scratchwidth", "scratchheight", "scratchdepth", "scratchoffset", "scratchdistance", "scratchhsize", "scratchvsize", "scratchxoffset", "scratchyoffset", "scratchhoffset", "scratchvoffset", "scratchxposition", "scratchyposition", "scratchtopoffset", "scratchbottomoffset", "scratchleftoffset", "scratchrightoffset", "scratchcounterone", "scratchcountertwo", "scratchcounterthree", "scratchdimenone", "scratchdimentwo", "scratchdimenthree", "scratchskipone", "scratchskiptwo", "scratchskipthree", "scratchmuskipone", "scratchmuskiptwo", "scratchmuskipthree", "scratchtoksone", "scratchtokstwo", "scratchtoksthree", "scratchboxone", "scratchboxtwo", "scratchboxthree", "scratchnx", "scratchny", "scratchmx", "scratchmy", "scratchunicode", "scratchleftskip", "scratchrightskip", "scratchtopskip", "scratchbottomskip", "doif", "doifnot", "doifelse", "doifinset", "doifnotinset", "doifinsetelse", "doifnextcharelse", "doifnextoptionalelse", "doifnextbgroupelse", "doifnextparenthesiselse", "doiffastoptionalcheckelse", "doifundefinedelse", "doifdefinedelse", "doifundefined", "doifdefined", "doifelsevalue", "doifvalue", "doifnotvalue", "doifnothing", "doifsomething", "doifelsenothing", "doifsomethingelse", "doifvaluenothing", "doifvaluesomething", "doifelsevaluenothing", "doifdimensionelse", "doifnumberelse", "doifnumber", "doifnotnumber", "doifcommonelse", "doifcommon", "doifnotcommon", "doifinstring", "doifnotinstring", "doifinstringelse", "doifassignmentelse", "docheckassignment", "tracingall", "tracingnone", "loggingall", "removetoks", "appendtoks", "prependtoks", "appendtotoks", "prependtotoks", "to", "endgraf", "endpar", "everyendpar", "reseteverypar", "finishpar", "empty", "null", "space", "quad", "enspace", "obeyspaces", "obeylines", "obeyedspace", "obeyedline", "normalspace", "executeifdefined", "singleexpandafter", "doubleexpandafter", "tripleexpandafter", "dontleavehmode", "removelastspace", "removeunwantedspaces", "keepunwantedspaces", "wait", "writestatus", "define", "redefine", "setmeasure", "setemeasure", "setgmeasure", "setxmeasure", "definemeasure", "freezemeasure", "measure", "installcorenamespace", "getvalue", "setvalue", "setevalue", "setgvalue", "setxvalue", "letvalue", "letgvalue", "resetvalue", "undefinevalue", "ignorevalue", "setuvalue", "setuevalue", "setugvalue", "setuxvalue", "globallet", "glet", "udef", "ugdef", "uedef", "uxdef", "getparameters", "geteparameters", "getgparameters", "getxparameters", "forgetparameters", "copyparameters", "getdummyparameters", "dummyparameter", "directdummyparameter", "setdummyparameter", "letdummyparameter", "usedummystyleandcolor", "usedummystyleparameter", "usedummycolorparameter", "processcommalist", "processcommacommand", "quitcommalist", "quitprevcommalist", "processaction", "processallactions", "processfirstactioninset", "processallactionsinset", "unexpanded", "expanded", "startexpanded", "stopexpanded", "protected", "protect", "unprotect", "firstofoneargument", "firstoftwoarguments", "secondoftwoarguments", "firstofthreearguments", "secondofthreearguments", "thirdofthreearguments", "firstoffourarguments", "secondoffourarguments", "thirdoffourarguments", "fourthoffourarguments", "firstoffivearguments", "secondoffivearguments", "thirdoffivearguments", "fourthoffivearguments", "fifthoffivearguments", "firstofsixarguments", "secondofsixarguments", "thirdofsixarguments", "fourthofsixarguments", "fifthofsixarguments", "sixthofsixarguments", "firstofoneunexpanded", "gobbleoneargument", "gobbletwoarguments", "gobblethreearguments", "gobblefourarguments", "gobblefivearguments", "gobblesixarguments", "gobblesevenarguments", "gobbleeightarguments", "gobbleninearguments", "gobbletenarguments", "gobbleoneoptional", "gobbletwooptionals", "gobblethreeoptionals", "gobblefouroptionals", "gobblefiveoptionals", "dorecurse", "doloop", "exitloop", "dostepwiserecurse", "recurselevel", "recursedepth", "dofastloopcs", "newconstant", "setnewconstant", "newconditional", "settrue", "setfalse", "setconstant", "newmacro", "setnewmacro", "newfraction", "newsignal", "dosingleempty", "dodoubleempty", "dotripleempty", "doquadrupleempty", "doquintupleempty", "dosixtupleempty", "doseventupleempty", "dosingleargument", "dodoubleargument", "dotripleargument", "doquadrupleargument", "doquintupleargument", "dosixtupleargument", "doseventupleargument", "dosinglegroupempty", "dodoublegroupempty", "dotriplegroupempty", "doquadruplegroupempty", "doquintuplegroupempty", "permitspacesbetweengroups", "dontpermitspacesbetweengroups", "nopdfcompression", "maximumpdfcompression", "normalpdfcompression", "modulonumber", "dividenumber", "getfirstcharacter", "doiffirstcharelse", "startnointerference", "stopnointerference", "twodigits", "threedigits", "strut", "setstrut", "strutbox", "strutht", "strutdp", "strutwd", "struthtdp", "begstrut", "endstrut", "lineheight", "ordordspacing", "ordopspacing", "ordbinspacing", "ordrelspacing", "ordopenspacing", "ordclosespacing", "ordpunctspacing", "ordinnerspacing", "opordspacing", "opopspacing", "opbinspacing", "oprelspacing", "opopenspacing", "opclosespacing", "oppunctspacing", "opinnerspacing", "binordspacing", "binopspacing", "binbinspacing", "binrelspacing", "binopenspacing", "binclosespacing", "binpunctspacing", "bininnerspacing", "relordspacing", "relopspacing", "relbinspacing", "relrelspacing", "relopenspacing", "relclosespacing", "relpunctspacing", "relinnerspacing", "openordspacing", "openopspacing", "openbinspacing", "openrelspacing", "openopenspacing", "openclosespacing", "openpunctspacing", "openinnerspacing", "closeordspacing", "closeopspacing", "closebinspacing", "closerelspacing", "closeopenspacing", "closeclosespacing", "closepunctspacing", "closeinnerspacing", "punctordspacing", "punctopspacing", "punctbinspacing", "punctrelspacing", "punctopenspacing", "punctclosespacing", "punctpunctspacing", "punctinnerspacing", "innerordspacing", "inneropspacing", "innerbinspacing", "innerrelspacing", "inneropenspacing", "innerclosespacing", "innerpunctspacing", "innerinnerspacing", "normalreqno", "startimath", "stopimath", "normalstartimath", "normalstopimath", "startdmath", "stopdmath", "normalstartdmath", "normalstopdmath", "uncramped", "cramped", "triggermathstyle", "mathstylefont", "mathsmallstylefont", "mathstyleface", "mathsmallstyleface", "mathstylecommand", "mathpalette", "mathstylehbox", "mathstylevbox", "mathstylevcenter", "mathstylevcenteredhbox", "mathstylevcenteredvbox", "mathtext", "setmathsmalltextbox", "setmathtextbox", "triggerdisplaystyle", "triggertextstyle", "triggerscriptstyle", "triggerscriptscriptstyle", "triggeruncrampedstyle", "triggercrampedstyle", "triggersmallstyle", "triggeruncrampedsmallstyle", "triggercrampedsmallstyle", "triggerbigstyle", "triggeruncrampedbigstyle", "triggercrampedbigstyle", "luaexpr", "expdoifelse", "expdoif", "expdoifnot", "expdoifcommonelse", "expdoifinsetelse", "ctxdirectlua", "ctxlatelua", "ctxsprint", "ctxwrite", "ctxcommand", "ctxdirectcommand", "ctxlatecommand", "ctxreport", "ctxlua", "luacode", "lateluacode", "directluacode", "registerctxluafile", "ctxloadluafile", "luaversion", "luamajorversion", "luaminorversion", "ctxluacode", "luaconditional", "luaexpanded", "startluaparameterset", "stopluaparameterset", "luaparameterset", "definenamedlua", "obeylualines", "obeyluatokens", "startluacode", "stopluacode", "startlua", "stoplua", "carryoverpar", "Umathbotaccent" },
}
\ No newline at end of file
diff --git a/Master/texmf-dist/context/data/scite/lexers/data/scite-context-data-interfaces.lua b/Master/texmf-dist/context/data/scite/lexers/data/scite-context-data-interfaces.lua
index ee7b7571841..b2c09b62a82 100644
--- a/Master/texmf-dist/context/data/scite/lexers/data/scite-context-data-interfaces.lua
+++ b/Master/texmf-dist/context/data/scite/lexers/data/scite-context-data-interfaces.lua
@@ -1,10 +1,10 @@
return {
["cs"]={ "CAP", "Cap", "Caps", "Cisla", "KAP", "Kap", "Kaps", "MESIC", "Rimskecislice", "SLOVA", "SLOVO", "Slova", "Slovo", "VSEDNIDEN", "Znak", "Znaky", "aktualnicislonadpisu", "aktualnidatum", "appendix", "arg", "atleftmargin", "atrightmargin", "barevnalista", "barva", "bilemisto", "bottomspace", "bublinkovanapoveda", "bydliste", "bypassblocks", "cap", "celkovypocetstran", "cernalinka", "cernelinky", "chapter", "chem", "cisla", "cislonadpisu", "cislopodrovnice", "cislorovnice", "cislostrany", "citace", "citovat", "comment", "completecombinedlist", "completelistoffloats", "completelistofsorts", "completelistofsynonyms", "completepagenumber", "completeregister", "coupledregister", "crlf", "cutspace", "datum", "decrementnumber", "definebodyfontDEF", "definebodyfontREF", "definecolumnbreak", "definecolumnset", "definecombination", "definedfont", "definefontfeature", "definefonthandling", "defineindentedtext", "defineinmargin", "defineitemgroup", "definelayer", "definelayout", "definemathalignment", "definepagebreak", "defineplacement", "definerawfont", "definerule", "definetextposition", "definetextvariable", "definetype", "definetypeface", "definuj", "definujakcent", "definujbarvu", "definujblok", "definujbloksekce", "definujbuffer", "definujfont", "definujformatodkazu", "definujhbox", "definujhlavnipole", "definujinterakcnimenu", "definujkombinovanyseznam", "definujkonverzi", "definujlogo", "definujnadpis", "definujobrazeksymbol", "definujodkaz", "definujodstavce", "definujopis", "definujoramovani", "definujoramovanytext", "definujpaletu", "definujplvouciobjekt", "definujpodpole", "definujpole", "definujpopis", "definujpopisek", "definujprekryv", "definujpreskok", "definujprikaz", "definujprofil", "definujprogram", "definujprostredizakladnihofontu", "definujrejstrik", "definujsablonutabulky", "definujsekci", "definujseznam", "definujseznamodkazu", "definujskupinubarev", "definujstartstop", "definujstyl", "definujstylfontu", "definujsymbol", "definujsynonumumfontu", "definujsynonyma", "definujtabelaci", "definujtext", "definujtrideni", "definujupravu", "definujvelikostpapiru", "definujverzi", "definujvycet", "definujvystup", "definujzakladnifont", "definujzasobnikpoli", "definujznaceni", "definujznak", "delkaseznamu", "description", "dodrzujprofil", "dodrzujverzi", "dodrzujverziprofilu", "dvoustrannypapir", "emptylines", "enumeration", "externiobraz", "fakt", "footnotetext", "forceblocks", "framedtext", "getnumber", "headsym", "hl", "hlavnijazyk", "hlavniuroven", "hodnotabarvy", "hodnotasedi", "immediatebetweenlist", "immediatetolist", "indentation", "ininner", "inneredgedistance", "inneredgewidth", "innermargindistance", "innermarginwidth", "inouter", "instalacejazyka", "interakcnilista", "interakcnitlacitka", "interaktivnimenu", "jazyk", "jdidolu", "jdina", "jdinabox", "jdinastranu", "jmeno", "kap", "klonujpole", "komponenta", "konvertujcislo", "kopirujpole", "korekcebilehomista", "labeling", "leg", "listsymbol", "loadsorts", "loadsynonyms", "maoramovani", "mapfontsize", "marginalnilinka", "marginalninadpis", "marginalnislovo", "marginalnitext", "matematika", "mazaramovani", "mediaeval", "meritko", "mesic", "mezera", "moveformula", "movesidefloat", "mrizka", "nadpis", "nadruhyokraj", "nalevo", "nalevyokraj", "name", "naokraj", "napravo", "napravyokraj", "nastavbarvu", "nastavbarvy", "nastavbilamista", "nastavblok", "nastavbloksekce", "nastavbuffer", "nastavcernelinky", "nastavcislonadpisu", "nastavcislostrany", "nastavcislovani", "nastavcislovaniodstavcu", "nastavcislovaniradku", "nastavcislovanistran", "nastavcitaci", "nastavdefinicipoznamekpodcarou", "nastavdeleniplvoucichobjektu", "nastavdelitko", "nastavdolnitexty", "nastaveni", "nastavexterniobrazy", "nastavhorejsek", "nastavhornitexty", "nastavinterakci", "nastavinterakcnilistu", "nastavinterakcnimenu", "nastavinterakcniobrazovku", "nastavjazyk", "nastavkapitalky", "nastavkombinovanyseznam", "nastavkomentar", "nastavkomentarstrany", "nastavlegendu", "nastavmarginalie", "nastavmarginalniblok", "nastavmarginalnilinky", "nastavmeziradkovoumezeru", "nastavnadpis", "nastavnadpisy", "nastavodkazovani", "nastavodsazovani", "nastavodstavce", "nastavopis", "nastavoramovanetexty", "nastavoramovani", "nastavorez", "nastavotoceni", "nastavpaletu", "nastavplvouciobjekt", "nastavplvouciobjekty", "nastavpodcislostrany", "nastavpodtrzeni", "nastavpole", "nastavpolozky", "nastavpopisek", "nastavpopisky", "nastavpopisy", "nastavpozadi", "nastavpoznamkypodcarou", "nastavprechodstrany", "nastavpreskok", "nastavprofily", "nastavprogramy", "nastavprostredizakladnihofontu", "nastavpublikace", "nastavradkovani", "nastavradky", "nastavrastr", "nastavrejstrik", "nastavrovnice", "nastavsadusymbolu", "nastavsekci", "nastavseznam", "nastavseznamodkazu", "nastavsirkucary", "nastavsloupce", "nastavspodek", "nastavspojeni", "nastavsynchronizaci", "nastavsynchronizacnilistu", "nastavsynonyma", "nastavsystem", "nastavtab", "nastavtabelaci", "nastavtabulky", "nastavtenkelinky", "nastavtext", "nastavtexthlavicky", "nastavtextovelinky", "nastavtextpopisku", "nastavtexttexty", "nastavtextyupati", "nastavtextyzahlavi", "nastavtlacitka", "nastavtoleranci", "nastavtrideni", "nastavtype", "nastavumisteniprotejsku", "nastavumistovani", "nastavupati", "nastavupravu", "nastavurl", "nastavusporadani", "nastavvelikostpapiru", "nastavverze", "nastavvsechnapole", "nastavvycty", "nastavvyplnovelinky", "nastavvyplnoveradky", "nastavvystup", "nastavvzhled", "nastavzahlavi", "nastavzakladnifont", "nastavzarovnani", "nastavznaceni", "nastavzuzeni", "nastrane", "navigating", "nejakyradek", "nekde", "nextsection", "neznamo", "nivy", "nizky", "nocap", "nokap", "nop", "numberofsubpages", "obrazovka", "odkaz", "odkaznadatum", "odkaznastranu", "odkaznatext", "odkazujici", "odsazenishora", "odsazenizleva", "odsazovani", "okr", "opakovat", "opis", "opissoubor", "oramovani", "oref", "orez", "otocit", "outeredgedistance", "outeredgewidth", "outermargindistance", "outermarginwidth", "overbar", "overbars", "overstrike", "overstrikes", "oznaceni", "oznacverzi", "pagedepth", "pageoffset", "paragraph", "parovastrana", "part", "pis", "placefloat", "placeheadnumber", "placeheadtext", "placelistoffloats", "placelistofsorts", "placelistofsynonyms", "placepagenumber", "placerawlist", "placereferencelist", "placerule", "placetextvariable", "plnezneni", "pol", "pole", "polozka", "polozky", "popisky", "poppisek", "porovnejpaletu", "porovnejskupinubarev", "positiontext", "pozadi", "pozice", "poznamka", "poznamkapodcarou", "pref", "prelozit", "premistinamrizku", "prepninazakladnifont", "preskoc", "prizpusobivepole", "prizpusobvzhled", "produkt", "program", "projekt", "propojeneznaceni", "propojenydokument", "propojenyrejstrik", "prostredi", "publikace", "ran", "ref", "register", "reservefloat", "reset", "resetnumber", "resettextcontent", "resetznaceni", "rimskecislice", "rozdelplvouciobjekt", "rozmer", "rozpojeneznaceni", "roztazene", "schovejbloky", "section", "sedabarva", "seeregister", "setnumber", "settextcontent", "settextvariable", "setupanswerarea", "setupcolumnset", "setupcolumnsetlines", "setupcolumnsetstart", "setupfonthandling", "setupfontsynonym", "setupforms", "setupindentedtext", "setupinterlinespace2", "setupitemgroup", "setuplistalternative", "setupmathalignment", "setupnumber", "setuppaper", "setupplacement", "setuprule", "setupstartstop", "setupstrut", "setuptextposition", "setuptextvariable", "sirkalevehookraje", "sirkalevemarginalie", "sirkamarginalie", "sirkaokraje", "sirkapapiru", "sirkapravehookraje", "sirkapravemarginalie", "sirkasazby", "sirkaseznamu", "sirkatextu", "sirkatiskpapiru", "sloupec", "slovovpravo", "sort", "spodek", "stanovcharakteristickuseznamu", "stanovcislonadpisu", "startalignment", "startbarva", "startbuffer", "startcislovaniradku", "startcitace", "startcolumnmakeup", "startcolumns", "startcolumnset", "startcombination", "startcomment", "startdescription", "startdocument", "startdokument", "startenumeration", "startfakt", "startfigure", "startfloattext", "startformula", "startframedtext", "startglobalni", "starthiding", "startinteraktivnimenu", "startitemgroup", "startkodovani", "startkomponenta", "startkorekceradku", "startlegend", "startline", "startlinecorrection", "startlinenumbering", "startlines", "startlocal", "startlocalenvironment", "startlocalfootnotes", "startlokalni", "startlokalnipoznamkypodcarou", "startmakeup", "startmarginalniblok", "startmarginalnilinka", "startmarginblock", "startnamemakeup", "startnarrower", "startnezhustene", "startobraz", "startopposite", "startoverlay", "startoverview", "startparagraph", "startpositioning", "startpostponing", "startpozadi", "startprehled", "startprekryv", "startprodukt", "startprofil", "startprofile", "startprojekt", "startprostredi", "startprotejsek", "startradek", "startradky", "startrastr", "startregister", "startsadasymbolu", "startsloupce", "startspojeni", "startsymbolset", "startsynchronizace", "startsynchronization", "starttable", "starttables", "starttabulate", "starttabulka", "starttabulky", "starttext", "starttextovalinka", "starttyping", "startumistovani", "startunpacked", "startuprava", "startverze", "startzarovnavani", "startzhustene", "startzuzeni", "stopalignment", "stopbarva", "stopbuffer", "stopcislovaniradku", "stopcitace", "stopcolumnmakeup", "stopcolumns", "stopcolumnset", "stopcombination", "stopcomment", "stopdescription", "stopdocument", "stopdokument", "stopenumeration", "stopfakt", "stopfigure", "stopfloattext", "stopformula", "stopframedtext", "stopglobalni", "stophiding", "stopinteraktivnimenu", "stopitemgroup", "stopkodovani", "stopkomponenta", "stopkorekceradku", "stoplegend", "stopline", "stoplinecorrection", "stoplinenumbering", "stoplines", "stoplocal", "stoplocalenvironment", "stoplocalfootnotes", "stoplokalni", "stoplokalnipoznamkypodcarou", "stopmakeup", "stopmarginalniblok", "stopmarginalnilinka", "stopmarginblock", "stopnamemakeup", "stopnarrower", "stopnezhustene", "stopopposite", "stopoverlay", "stopoverview", "stopparagraph", "stoppositioning", "stoppostponing", "stoppozadi", "stopprehled", "stopprekryv", "stopprodukt", "stopprofil", "stopprofile", "stopprojekt", "stopprostredi", "stopprotejsek", "stopradek", "stopradky", "stoprastr", "stopsloupce", "stopspojeni", "stopsymbolset", "stopsynchronizace", "stopsynchronization", "stoptable", "stoptables", "stoptabulate", "stoptabulka", "stoptabulky", "stoptext", "stoptextovalinka", "stoptyping", "stopumistovani", "stopunpacked", "stopuprava", "stopverze", "stopzarovnavani", "stopzhustene", "stopzuzeni", "strana", "sub", "subject", "subpagenumber", "subsection", "subsubject", "subsubsection", "subsubsubject", "switchtorawfont", "sym", "symbol", "synchronizacnilista", "synchronizovat", "synonym", "tab", "tecky", "tenkalinka", "tenkelinky", "testcolumn", "testpage", "tex", "texthlavicky", "textovalinka", "textpopisku", "textvariable", "title", "tlacitko", "tlacitkomenu", "tloustkacary", "tref", "tvrdamezera", "tvrdemezery", "txt", "typebuffer", "ukazbarvu", "ukazexterniobrazy", "ukazmrizku", "ukaznastaveni", "ukazpaletu", "ukazpodpery", "ukazpole", "ukazpostredizakladnihofontu", "ukazramecek", "ukazsadusymbolu", "ukazskupinubarev", "ukazupravu", "ukazvytisk", "ukazvzhled", "ukazzakladnifont", "umistikombinovanyseznam", "umistilegendu", "umistiloga", "umistilokalnipoznamkypodcarou", "umistinadsebe", "umistinamrizku", "umistipodrovnici", "umistipoznamkypodcarou", "umistirejstrik", "umistirovnici", "umistiseznam", "umistivedlesebe", "umistizalozky", "underbar", "underbars", "urcicharakteristikurejstriku", "useXMLfilter", "usedirectory", "usetypescript", "usetypescriptfile", "uzijJSscripts", "uzijURL", "uzijadresar", "uzijbloky", "uzijexternidokument", "uzijexterniobraz", "uzijexternisoubor", "uzijexternisoubory", "uzijexternizvuk", "uzijkodovani", "uzijmodul", "uzijmoduly", "uzijodkazy", "uzijprikazy", "uzijspeciality", "uzijsymbol", "uzijurl", "verze", "vl", "vlasovalinka", "vlevo", "vpravo", "vradku", "vsedniden", "vyberbloky", "vyberpapir", "vyberverzi", "vyplnenytext", "vyplnovelinky", "vyplnovepole", "vyplnovyradek", "vyskahorejsku", "vyskapapiru", "vyskasazby", "vyskaseznamu", "vyskaspodku", "vyskatextu", "vyskatiskpapiru", "vyskaupati", "vyskazahlavi", "vysoky", "vyznam", "vzdalenosthorejsku", "vzdalenostlevehookraje", "vzdalenostlevemarginalie", "vzdalenostmarginalie", "vzdalenostokraje", "vzdalenostpravehookraje", "vzdalenostpravemarginalie", "vzdalenostspodku", "vzdalenostupati", "vzdalenostzahlavi", "zablokujinterakcnimenu", "zachovejbloky", "zadnamezera", "zadnebilemisto", "zadnedalsibloky", "zadnedalsisoubory", "zadnehorniadolniradky", "zadneodsazovani", "zadnezahlaviaupati", "zadneznaceni", "zadnyrozmer", "zadnyseznam", "zadnytest", "zalozka", "zapisdorejstriku", "zapisdoseznamu", "zapisdoseznamuodkazu", "zapismeziseznam", "zaramovani", "zarovnanonastred", "zarovnanovlevo", "zarovnanovpravo", "zasobnikpoli", "zaznamovepole", "zhustene", "ziskejbuffer", "ziskejznaceni", "zlomek", "znaceni", "znak", "znaky", "zpracujbloky", "zpracujstranu", "zrcadlit", "zref", "zvysujicicislo" },
["de"]={ "Buchstabe", "Buchstaben", "CAP", "Cap", "Caps", "KAP", "Kap", "Kaps", "MONAT", "Roemischezahlen", "WOCHENTAG", "WOERTER", "WORT", "Woerter", "Wort", "Ziffern", "abstandlinkerrand", "abstandoben", "abstandrechterrand", "abstandunten", "amgitterausrichten", "amgitterneuausrichten", "appendix", "arg", "atleftmargin", "atrightmargin", "aufseite", "ausfuellfeld", "ausfuelltext", "ausschnitt", "bearbeitebloecke", "bearbeiteseite", "bedeutung", "behaltebloecke", "bei", "bemerkung", "benutzekodierung", "benutzespezielles", "benutzeverzeichnis", "beschrifteversion", "beschriftung", "bestimmekopfnummer", "bestimmelistencharakeristika", "bestimmeregistercharakteristika", "bildschirm", "blanko", "bookmark", "bottomspace", "breitelinkerrand", "breiterechterrand", "bruch", "buchstabe", "buchstaben", "but", "bypassblocks", "cap", "chapter", "chem", "comment", "completecombinedlist", "completelistoffloats", "completelistofsorts", "completelistofsynonyms", "completepagenumber", "completeregister", "coupledregister", "crlf", "cutspace", "datum", "decrementnumber", "definebodyfontDEF", "definebodyfontREF", "definecolumnbreak", "definecolumnset", "definecombination", "definedfont", "definefontfeature", "definefonthandling", "defineindentedtext", "defineinmargin", "defineitemgroup", "definelayer", "definelayout", "definemathalignment", "defineoutput", "definepagebreak", "defineplacement", "definerawfont", "definerule", "defineschriftsynonym", "definetextposition", "definetextvariable", "definetype", "definetypeface", "definiereabbsymbol", "definiereabsaetze", "definiereabschnitt", "definiereabschnittsblock", "definiereakzent", "definierebefehl", "definierebeschreibung", "definierebeschreibungen", "definierebeschriftung", "definiereblanko", "definiereblock", "definierefarbe", "definierefarbengruppe", "definierefeld", "definierefeldstapel", "definierefliesstext", "definierefliesstextumgebung", "definieregleitobjekt", "definierehauptfeld", "definierehbox", "definiereinteraktionsmenue", "definierekonversion", "definierelabel", "definiereliste", "definierelogo", "definieren", "definierenummerierung", "definiereoverlay", "definierepalette", "definierepapierformat", "definiereprofil", "definiereprogramme", "definierepuffer", "definierereferenz", "definierereferenzformat", "definierereferenzliste", "definiereregister", "definiereschrift", "definiereschriftstil", "definieresortieren", "definierestartstop", "definierestil", "definieresubfeld", "definieresymbol", "definieresynonyme", "definieretabellenvorlage", "definieretabulator", "definieretext", "definieretippen", "definiereueberschrift", "definiereumbruch", "definiereumrahmt", "definiereumrahmtertext", "definiereversion", "definierezeichen", "definierezusammengestellteliste", "description", "dimension", "doppelseite", "doppelseitigespapier", "drehen", "duennelinie", "duennerumriss", "einezeile", "einstellungen", "einziehen", "emptylines", "entknuepfebeschriftung", "enumeration", "externeabbildung", "farbbalken", "farbe", "farbewert", "feld", "feldstapel", "festesspatium", "folgeprofil", "folgeprofilversion", "folgeversion", "footnotetext", "forceblocks", "format", "formelnummer", "framedtext", "fussnote", "fusszeileabstand", "fusszeilenhoehe", "gefuelltesrechteck", "gefuelltezeile", "geg", "gesamtseitenanzahl", "gestreckt", "getnumber", "gitter", "graufarbe", "grauwert", "haarlinie", "hauptsprache", "headsym", "heutigesdatum", "heutigeskopfnummer", "hintergrund", "hl", "hoch", "hoeheoben", "hoeheunten", "holebeschriftung", "holepuffer", "imlinken", "imlinkenrand", "immaumrise", "immediatebetweenlist", "immediatetolist", "imrechten", "imrechtenrand", "imumriss", "in", "inaktiviereinteraktionsmenue", "inanderermarginale", "indentation", "ininner", "inlinkermarginale", "inmarginalie", "inneredgedistance", "inneredgewidth", "innermargindistance", "innermarginwidth", "inouter", "inrechtermarginale", "installieresprache", "interaktionsbalken", "interaktionsknopfe", "interaktionsmenue", "inzeile", "irgendwo", "its", "kap", "keindimension", "keinebeschriftung", "keinebloeckemehr", "keinedateienmehr", "keinekopfundfusszeilen", "keineliste", "keinspatium", "keintest", "keinzeilenobenundunten", "keinzwischenraum", "kleinerdurchschuss", "klonierefeld", "knopf", "komponente", "konvertierezahl", "kopf", "kopfniveau", "kopfnummer", "kopfweite", "kopfzeilenabstand", "kopfzeilenhoehe", "kopierefeld", "korrigierezwischenraum", "label", "labeling", "labels", "labeltext", "leg", "liniendicke", "linkemarginalafstand", "linkemarginalbreite", "linksbuendig", "listenbreite", "listenhoehe", "listenlaenge", "listsymbol", "loadsorts", "loadsynonyms", "mapfontsize", "mar", "marginalafstand", "marginalbreite", "marginallinie", "marginaltext", "marginaltitel", "marginalwort", "mathematik", "maumrise", "mediaeval", "menueknopf", "monat", "moveformula", "movesidefloat", "nachunten", "name", "navigating", "nextsection", "nichteinziehen", "nocap", "nokap", "nop", "notiz", "numberofsubpages", "nummererhoehen", "outeredgedistance", "outeredgewidth", "outermargindistance", "outermarginwidth", "overbar", "overbars", "overstrike", "overstrikes", "pagedepth", "pageoffset", "papierbreite", "papierhoehe", "paragraph", "part", "passelayoutan", "passendfeld", "placefloat", "placeheadnumber", "placeheadtext", "placelistoffloats", "placelistofsorts", "placelistofsynonyms", "placepagenumber", "placerawlist", "placereferencelist", "placerule", "placetextvariable", "platzierebookmarks", "platziereformel", "platzierefussnoten", "platzierelegende", "platziereliste", "platzierelogo", "platzierelokalefussnoten", "platzierenebeneinander", "platziereregister", "platziereuntereinander", "platziereunterformel", "platzierezusammengestellteliste", "pos", "position", "positiontext", "posten", "printpapierbreite", "printpapierhoehe", "produkt", "programm", "projekt", "publikation", "punkt", "ran", "randabstand", "randbreite", "rechteck", "rechtecke", "rechtemarginalafstand", "rechtemarginalbreite", "rechtsbuendig", "ref", "referenz", "referieren", "register", "registrierefelder", "reservefloat", "resetnumber", "resettextcontent", "roemischezahlen", "ruecksetzten", "ruecksetztenbeschriftung", "rumpfweite", "satzbreite", "satzhoehe", "schreibezumregister", "schreibezurliste", "schreibezurreferenzliste", "schreibezwischenliste", "section", "seeregister", "seite", "seitenreferenz", "seitenummer", "setnumber", "settext", "settextvariable", "setupanswerarea", "setupcolumnset", "setupcolumnsetlines", "setupcolumnsetstart", "setupfonthandling", "setupfontsynonym", "setupforms", "setupindentedtext", "setupinterlinespace2", "setupitemgroup", "setuplistalternative", "setupmathalignment", "setupnumber", "setuppaper", "setupplacement", "setuprule", "setupstartstop", "setupstrut", "setuptextposition", "setuptextvariable", "showsymbolset", "sort", "spalte", "spatium", "spiegeln", "sprache", "startabbildung", "startalignment", "startausrichtung", "startbuffer", "startcolumnmakeup", "startcolumns", "startcolumnset", "startcombination", "startcomment", "startdescription", "startdocument", "startdokument", "startenger", "startenumeration", "startfarbe", "startfigure", "startfloattext", "startformula", "startframedtext", "startgeg", "startgegenueber", "startglobal", "startgrosserdurchschuss", "starthiding", "starthintergrund", "startinteraktionsmenue", "startitemgroup", "startkleinerdurchschuss", "startkodierung", "startkombination", "startkomponente", "startlegend", "startline", "startlinecorrection", "startlinenumbering", "startlines", "startlocal", "startlocalenvironment", "startlocalfootnotes", "startlokal", "startlokalefussnoten", "startmakeup", "startmarginalblock", "startmarginallinie", "startmarginblock", "startnamemakeup", "startnarrower", "startopposite", "startoverlay", "startoverview", "startparagraph", "startpositionieren", "startpositioning", "startpostponing", "startprodukt", "startprofil", "startprofile", "startprojekt", "startraster", "startregister", "startspalten", "startsymbolset", "startsynchronisation", "startsynchronization", "starttabelle", "starttabellen", "starttable", "starttables", "starttabulate", "starttext", "starttextlinie", "starttyping", "startueberblick", "startumbruch", "startumgebung", "startunpacked", "startversion", "startzeile", "startzeilen", "startzeilenkorrektur", "startzeilennumerierung", "startzitat", "stelleabsaetzeein", "stelleabsatznummerierungein", "stelleabschnittein", "stelleabschnittsblockein", "stelleanordnenein", "stelleaufzaehlungenein", "stelleausgabeein", "stelleausrichtungein", "stelleausschnittein", "stellebeschreibungein", "stellebeschriftungein", "stellebilderunterschriftein", "stellebildunterschriftein", "stellebindestrichein", "stelleblankoein", "stelleblockein", "stelledrehenein", "stelleduennerumrissein", "stelleeinziehenein", "stelleengerein", "stelleexterneabbildungenein", "stellefarbeein", "stellefarbenein", "stellefeldein", "stellefelderin", "stellefliesstextein", "stellefliesstextumgebungein", "stelleformelnein", "stellefussnotendefinitionein", "stellefussnotenein", "stellefusszeileein", "stellefusszeilentextein", "stellegefuelltesrechteckein", "stellegefuelltezeileein", "stellegegenueberplatzierenein", "stellegleitobjekteein", "stellegleitobjektein", "stellehintergruendeein", "stellehintergrundein", "stelleinmarginalieein", "stelleinteraktionein", "stelleinteraktionsbalkenein", "stelleinteraktionsbildschirmein", "stelleinteraktionsmenueein", "stelleknopfein", "stellekombinationein", "stellekommentarein", "stellekopfzahlein", "stellekopfzeileein", "stellekopfzeilentextein", "stellelabeltextein", "stellelayoutein", "stellelegendeein", "stellelinienbreiteein", "stellelisteein", "stellemarginalblockein", "stellemarginallinieein", "stellenobenein", "stellenummerierungein", "stellepaletteein", "stellepapierformatein", "stelleplatziegeteiltegleitobjekt", "stellepositionierenein", "stellepostenein", "stelleprofilein", "stelleprogrammein", "stellepublikationein", "stellepufferein", "stellerasterein", "stellerechteckein", "stellereferenzierenein", "stellereferenzlisteein", "stelleregisterein", "stelleseitenkommentarein", "stelleseitennummerein", "stelleseitennummeriernungein", "stelleseitenuebergangein", "stellesortierenein", "stellespaltenein", "stellespatiumein", "stellespracheein", "stellesymbolsetein", "stellesynchronisationein", "stellesynchronisationsbalkenein", "stellesynonymein", "stellesystemein", "stelletabein", "stelletabellenein", "stelletabulatorein", "stelletextein", "stelletextobenein", "stelletexttexteein", "stelletextumrissein", "stelletextuntenein", "stelletipein", "stelletippenein", "stelletoleranzein", "stelleueberschriftein", "stelleueberschriftenein", "stelleueberschrifttextein", "stelleumbruchein", "stelleumrahmtein", "stelleumrahmtetexteein", "stelleuntenein", "stelleunterseitennummerein", "stelleunterstreichenein", "stelleurlein", "stelleversalienein", "stelleversionein", "stellezeilenabstandein", "stellezeilenein", "stellezeilennumerierungein", "stellezitierenein", "stellezusammengestelltelisteein", "stellezwischenraumein", "stopalignment", "stopausrichtung", "stopbuffer", "stopcolumnmakeup", "stopcolumns", "stopcolumnset", "stopcombination", "stopcomment", "stopdescription", "stopdocument", "stopdokument", "stopenger", "stopenumeration", "stopfarbe", "stopfigure", "stopfloattext", "stopformula", "stopframedtext", "stopgeg", "stopgegenueber", "stopglobal", "stopgrosserdurchschuss", "stophiding", "stophintergrund", "stopinteraktionsmenue", "stopitemgroup", "stopkleinerdurchschuss", "stopkodierung", "stopkombination", "stopkomponente", "stoplegend", "stopline", "stoplinecorrection", "stoplinenumbering", "stoplines", "stoplocal", "stoplocalenvironment", "stoplocalfootnotes", "stoplokal", "stoplokalefussnoten", "stopmakeup", "stopmarginalblock", "stopmarginallinie", "stopmarginblock", "stopnamemakeup", "stopnarrower", "stopopposite", "stopoverlay", "stopoverview", "stopparagraph", "stoppositionieren", "stoppositioning", "stoppostponing", "stopprodukt", "stopprofil", "stopprofile", "stopprojekt", "stopraster", "stopspalten", "stopsymbolset", "stopsynchronisation", "stopsynchronization", "stoptabelle", "stoptabellen", "stoptable", "stoptables", "stoptabulate", "stoptext", "stoptextlinie", "stoptyping", "stopueberblick", "stopumbruch", "stopumgebung", "stopunpacked", "stopversion", "stopzeile", "stopzeilen", "stopzeilenkorrektur", "stopzeilennumerierung", "stopzitat", "sub", "subject", "subpagenumber", "subsection", "subsubject", "subsubsection", "subsubsubject", "switchtorawfont", "sym", "symbol", "synchronisationsbalken", "synchronisieren", "synonym", "tab", "teilegleitobjekt", "testcolumn", "testpage", "tex", "textbreite", "texthoehe", "textlinie", "textreferenz", "textvariable", "tief", "tiho", "tip", "tippedatei", "tippen", "tippepuffer", "title", "tooltip", "txt", "ueber", "ueberschrifttext", "uebersetzten", "umgebung", "umrahmt", "unbekant", "underbar", "underbars", "unterformelnummer", "useXMLfilter", "usedirectory", "usetypescript", "usetypescriptfile", "verbergebloecke", "vergleichefarbengruppe", "vergleichepalette", "verknuepfebeschriftung", "verknuepfedokument", "verknuepfregister", "version", "verweis", "verweisdatum", "verwendeJSscript", "verwendeURL", "verwendebefehl", "verwendebloecke", "verwendeexteresdokument", "verwendeexterneabbildung", "verwendeexternedatei", "verwendeexternedateien", "verwendeexternestonstueck", "verwendemodul", "verwendemodule", "verwendereferenzen", "verwendesymbole", "verwendeurl", "vl", "volleswort", "von", "waehlebloeckeaus", "waehlepapieraus", "waehleversionaus", "wechselezumfliesstext", "wiederholen", "wochentag", "wohnort", "wortrechts", "zeigedruck", "zeigeeinstellungen", "zeigeexterneabbildungen", "zeigefarbe", "zeigefarbengruppe", "zeigefelder", "zeigefliesstext", "zeigefliesstextumgebung", "zeigegitter", "zeigelayout", "zeigepalette", "zeigerahmen", "zeigestruts", "zeigeumbruch", "zentriert", "ziffern", "zitat", "zitieren", "zu", "zurbox", "zurseite", "zwischenraum" },
- ["en"]={ "CAP", "Cap", "Caps", "Character", "Characters", "MONTH", "Numbers", "Romannumerals", "WEEKDAY", "WORD", "WORDS", "Word", "Words", "about", "adaptlayout", "adding", "appendix", "arg", "at", "atleftmargin", "atpage", "atrightmargin", "background", "backspace", "blackrule", "blackrules", "blank", "bookmark", "bottomdistance", "bottomheight", "bottomspace", "but", "button", "bypassblocks", "cap", "chapter", "character", "characters", "chem", "clip", "clonefield", "color", "colorbar", "colorvalue", "column", "comment", "comparecolorgroup", "comparepalet", "completecombinedlist", "completelistoffloats", "completelistofsorts", "completelistofsynonyms", "completepagenumber", "completeregister", "component", "convertnumber", "copyfield", "correctwhitespace", "coupledocument", "coupledregister", "couplemarking", "couplepage", "couplepaper", "coupleregister", "crlf", "currentdate", "currentheadnumber", "cutspace", "date", "decouplemarking", "decrementnumber", "define", "defineaccent", "defineblank", "defineblock", "definebodyfont", "definebodyfontDEF", "definebodyfontREF", "definebodyfontenvironment", "definebuffer", "definecharacter", "definecolor", "definecolorgroup", "definecolumnbreak", "definecolumnset", "definecombination", "definecombinedlist", "definecommand", "defineconversion", "definedescription", "definedfont", "defineenumeration", "definefield", "definefieldstack", "definefiguresymbol", "definefloat", "definefont", "definefontfeature", "definefonthandling", "definefontstyle", "definefontsynonym", "defineframed", "defineframedtext", "definehbox", "definehead", "defineindentedtext", "defineinmargin", "defineinteractionmenu", "defineitemgroup", "definelabel", "definelayer", "definelayout", "definelist", "definelogo", "definemainfield", "definemakeup", "definemarking", "definemathalignment", "defineoutput", "defineoverlay", "definepagebreak", "definepalet", "definepapersize", "defineparagraphs", "defineplacement", "defineprofile", "defineprogram", "definerawfont", "definereference", "definereferenceformat", "definereferencelist", "defineregister", "definerule", "definesection", "definesectionblock", "definesorting", "definestartstop", "definestyle", "definesubfield", "definesymbol", "definesynonyms", "definetabletemplate", "definetabulate", "definetext", "definetextposition", "definetextvariable", "definetype", "definetypeface", "definetyping", "defineversion", "description", "determineheadnumber", "determinelistcharacteristics", "determineregistercharacteristics", "dimension", "disableinteractionmenu", "domicile", "donttest", "edgedistance", "edgewidth", "emptylines", "enumeration", "environment", "externalfigure", "fact", "field", "fieldstack", "fillinfield", "fillinline", "fillinrules", "fillintext", "fitfield", "fixedspace", "fixedspaces", "followprofile", "followprofileversion", "followversion", "footerdistance", "footerheight", "footnote", "footnotetext", "forceblocks", "formulanumber", "fraction", "framed", "framedtext", "from", "getbuffer", "getmarking", "getnumber", "godown", "goto", "gotobox", "gotopage", "graycolor", "greyvalue", "grid", "hairline", "head", "headerdistance", "headerheight", "headlevel", "headnumber", "headsym", "headtext", "hideblocks", "high", "hl", "immediatebetweenlist", "immediatetolist", "in", "incrementnumber", "indentation", "indenting", "inframed", "infull", "ininner", "inleft", "inleftedge", "inleftmargin", "inline", "inmaframed", "inmargin", "inneredgedistance", "inneredgewidth", "innermargindistance", "innermarginwidth", "inothermargin", "inouter", "inright", "inrightedge", "inrightmargin", "installlanguage", "interactionbar", "interactionbuttons", "interactionmenu", "item", "items", "its", "keepblocks", "label", "labeling", "labels", "labeltext", "language", "leftaligned", "leftedgedistance", "leftedgewidth", "leftmargindistance", "leftmarginwidth", "leg", "linethickness", "listheight", "listlength", "listsymbol", "listwidth", "loadsorts", "loadsynonyms", "logfields", "lohi", "low", "maframed", "mainlanguage", "makeupheight", "makeupwidth", "mapfontsize", "mar", "margindistance", "marginrule", "margintext", "margintitle", "marginwidth", "marginword", "marking", "markversion", "mathematics", "mediaeval", "menubutton", "midaligned", "mirror", "month", "moveformula", "moveongrid", "movesidefloat", "name", "navigating", "nextsection", "nocap", "nodimension", "noheaderandfooterlines", "noindenting", "nolist", "nomarking", "nomoreblocks", "nomorefiles", "nop", "nospace", "note", "notopandbottomlines", "nowhitespace", "numberofsubpages", "numbers", "outeredgedistance", "outeredgewidth", "outermargindistance", "outermarginwidth", "overbar", "overbars", "overstrike", "overstrikes", "packed", "page", "pagedepth", "pagenumber", "pageoffset", "pagereference", "paperheight", "paperwidth", "paragraph", "part", "periods", "placebookmarks", "placecombinedlist", "placefloat", "placefootnotes", "placeformula", "placeheadnumber", "placeheadtext", "placelegend", "placelist", "placelistoffloats", "placelistofsorts", "placelistofsynonyms", "placelocalfootnotes", "placelogos", "placeongrid", "placeontopofeachother", "placepagenumber", "placerawlist", "placereferencelist", "placeregister", "placerule", "placesidebyside", "placesubformula", "placetextvariable", "position", "positiontext", "printpaperheight", "printpaperwidth", "processblocks", "processpage", "product", "program", "project", "publication", "quotation", "quote", "ran", "redo", "ref", "reference", "referral", "referraldate", "referring", "register", "remark", "reservefloat", "reset", "resetmarking", "resetnumber", "resettextcontent", "rightaligned", "rightedgedistance", "rightedgewidth", "rightmargindistance", "rightmarginwidth", "romannumerals", "rotate", "scale", "screen", "section", "seeregister", "selectblocks", "selectpaper", "selectversion", "setnumber", "settextcontent", "settextvariable", "setupalign", "setupanswerarea", "setuparranging", "setupbackground", "setupbackgrounds", "setupblackrules", "setupblank", "setupblock", "setupbodyfont", "setupbodyfontenvironment", "setupbottom", "setupbottomtexts", "setupbuffer", "setupbuttons", "setupcapitals", "setupcaption", "setupcaptions", "setupclipping", "setupcolor", "setupcolors", "setupcolumns", "setupcolumnset", "setupcolumnsetlines", "setupcolumnsetstart", "setupcombinations", "setupcombinedlist", "setupcomment", "setupdescriptions", "setupenumerations", "setupexternalfigures", "setupfield", "setupfields", "setupfillinlines", "setupfillinrules", "setupfloat", "setupfloats", "setupfloatsplitting", "setupfonthandling", "setupfontsynonym", "setupfooter", "setupfootertexts", "setupfootnotedefinition", "setupfootnotes", "setupforms", "setupformulae", "setupframed", "setupframedtexts", "setuphead", "setupheader", "setupheadertexts", "setupheadnumber", "setupheads", "setupheadtext", "setuphyphenmark", "setupindentedtext", "setupindenting", "setupinmargin", "setupinteraction", "setupinteractionbar", "setupinteractionmenu", "setupinteractionscreen", "setupinterlinespace", "setupinterlinespace2", "setupitemgroup", "setupitemizations", "setupitems", "setuplabeltext", "setuplanguage", "setuplayout", "setuplegend", "setuplinenumbering", "setuplines", "setuplinewidth", "setuplist", "setuplistalternative", "setupmakeup", "setupmarginblocks", "setupmarginrules", "setupmarking", "setupmathalignment", "setupnarrower", "setupnumber", "setupnumbering", "setupoppositeplacing", "setupoutput", "setuppagecomment", "setuppagenumber", "setuppagenumbering", "setuppagetransitions", "setuppalet", "setuppaper", "setuppapersize", "setupparagraphnumbering", "setupparagraphs", "setupplacement", "setuppositioning", "setupprofiles", "setupprograms", "setuppublications", "setupquote", "setupreferencelist", "setupreferencing", "setupregister", "setuprotate", "setuprule", "setups", "setupscreens", "setupsection", "setupsectionblock", "setupsorting", "setupspacing", "setupstartstop", "setupstrut", "setupsubpagenumber", "setupsymbolset", "setupsynchronization", "setupsynchronizationbar", "setupsynonyms", "setupsystem", "setuptab", "setuptables", "setuptabulate", "setuptext", "setuptextposition", "setuptextrules", "setuptexttexts", "setuptextvariable", "setupthinrules", "setuptolerance", "setuptop", "setuptoptexts", "setuptype", "setuptyping", "setupunderbar", "setupurl", "setupversions", "setupwhitespace", "showbodyfont", "showbodyfontenvironment", "showcolor", "showcolorgroup", "showexternalfigures", "showfields", "showframe", "showgrid", "showlayout", "showmakeup", "showpalet", "showprint", "showsetups", "showstruts", "showsymbolset", "someline", "somewhere", "sort", "space", "splitfloat", "startalignment", "startbackground", "startbuffer", "startcoding", "startcolor", "startcolumnmakeup", "startcolumns", "startcolumnset", "startcombination", "startcomment", "startcomponent", "startdescription", "startdocument", "startenumeration", "startenvironment", "startfact", "startfigure", "startfloattext", "startformula", "startframedtext", "startglobal", "starthiding", "startinteractionmenu", "startitemgroup", "startlegend", "startline", "startlinecorrection", "startlinenumbering", "startlines", "startlocal", "startlocalenvironment", "startlocalfootnotes", "startmakeup", "startmarginblock", "startmarginrule", "startnamemakeup", "startnarrower", "startopposite", "startoverlay", "startoverview", "startpacked", "startparagraph", "startpositioning", "startpostponing", "startproduct", "startprofile", "startproject", "startquotation", "startraster", "startregister", "startsymbolset", "startsynchronization", "starttable", "starttables", "starttabulate", "starttext", "starttextrule", "starttyping", "startunpacked", "startversion", "stopalignment", "stopbackground", "stopbuffer", "stopcoding", "stopcolor", "stopcolumnmakeup", "stopcolumns", "stopcolumnset", "stopcombination", "stopcomment", "stopcomponent", "stopdescription", "stopdocument", "stopenumeration", "stopenvironment", "stopfact", "stopfigure", "stopfloattext", "stopformula", "stopframedtext", "stopglobal", "stophiding", "stopinteractionmenu", "stopitemgroup", "stoplegend", "stopline", "stoplinecorrection", "stoplinenumbering", "stoplines", "stoplocal", "stoplocalenvironment", "stoplocalfootnotes", "stopmakeup", "stopmarginblock", "stopmarginrule", "stopnamemakeup", "stopnarrower", "stopopposite", "stopoverlay", "stopoverview", "stoppacked", "stopparagraph", "stoppositioning", "stoppostponing", "stopproduct", "stopprofile", "stopproject", "stopquotation", "stopraster", "stopsymbolset", "stopsynchronization", "stoptable", "stoptables", "stoptabulate", "stoptext", "stoptextrule", "stoptyping", "stopunpacked", "stopversion", "stretched", "sub", "subformulanumber", "subject", "subpagenumber", "subsection", "subsubject", "subsubsection", "subsubsubject", "switchtobodyfont", "switchtorawfont", "sym", "symbol", "synchronizationbar", "synchronize", "synonym", "tab", "testcolumn", "testpage", "tex", "textheight", "textreference", "textrule", "textvariable", "textwidth", "thinrule", "thinrules", "title", "tooltip", "topdistance", "topheight", "topspace", "totalnumberofpages", "translate", "txt", "typ", "type", "typebuffer", "typefile", "underbar", "underbars", "unitmeaning", "unknown", "useJSscripts", "useURL", "useXMLfilter", "useblocks", "usecommands", "usedirectory", "useencoding", "useexternaldocument", "useexternalfigure", "useexternalfile", "useexternalfiles", "useexternalsoundtrack", "usemodule", "usemodules", "usereferences", "usespecials", "usesymbols", "usetypescript", "usetypescriptfile", "useurl", "version", "vl", "weekday", "whitespace", "wordright", "writebetweenlist", "writetolist", "writetoreferencelist", "writetoregister" },
+ ["en"]={ "CAP", "Cap", "Caps", "Character", "Characters", "MONTH", "Numbers", "Romannumerals", "WEEKDAY", "WORD", "WORDS", "Word", "Words", "about", "adaptlayout", "adding", "appendix", "arg", "at", "atleftmargin", "atpage", "atrightmargin", "background", "backspace", "blackrule", "blackrules", "blank", "bookmark", "bottomdistance", "bottomheight", "bottomspace", "but", "button", "bypassblocks", "cap", "chapter", "character", "characters", "chem", "clip", "clonefield", "color", "colorbar", "colorvalue", "column", "comment", "comparecolorgroup", "comparepalet", "completecombinedlist", "completelistoffloats", "completelistofsorts", "completelistofsynonyms", "completepagenumber", "completeregister", "component", "convertnumber", "copyfield", "correctwhitespace", "coupledocument", "coupledregister", "couplemarking", "couplepage", "couplepaper", "coupleregister", "crlf", "currentdate", "currentheadnumber", "cutspace", "date", "decouplemarking", "decrementnumber", "define", "defineaccent", "defineblank", "defineblock", "definebodyfont", "definebodyfontDEF", "definebodyfontREF", "definebodyfontenvironment", "definebuffer", "definecharacter", "definecolor", "definecolorgroup", "definecolumnbreak", "definecolumnset", "definecombination", "definecombinedlist", "definecommand", "defineconversion", "definedescription", "definedfont", "defineenumeration", "definefield", "definefieldstack", "definefiguresymbol", "definefloat", "definefont", "definefontfeature", "definefonthandling", "definefontstyle", "definefontsynonym", "defineframed", "defineframedtext", "definehbox", "definehead", "defineindentedtext", "defineinmargin", "defineinteractionmenu", "defineitemgroup", "definelabel", "definelayer", "definelayout", "definelist", "definelogo", "definemainfield", "definemakeup", "definemarking", "definemathalignment", "defineoutput", "defineoverlay", "definepagebreak", "definepalet", "definepapersize", "defineparagraphs", "defineplacement", "defineprofile", "defineprogram", "definerawfont", "definereference", "definereferenceformat", "definereferencelist", "defineregister", "definerule", "definesection", "definesectionblock", "definesorting", "definestartstop", "definestyle", "definesubfield", "definesymbol", "definesynonyms", "definetabletemplate", "definetabulate", "definetext", "definetextposition", "definetextvariable", "definetype", "definetypeface", "definetyping", "defineversion", "description", "determineheadnumber", "determinelistcharacteristics", "determineregistercharacteristics", "dimension", "disableinteractionmenu", "domicile", "donttest", "edgedistance", "edgewidth", "emptylines", "enumeration", "environment", "externalfigure", "fact", "field", "fieldstack", "fillinfield", "fillinline", "fillinrules", "fillintext", "fitfield", "fixedspace", "fixedspaces", "followprofile", "followprofileversion", "followversion", "footerdistance", "footerheight", "footnote", "footnotetext", "forceblocks", "formulanumber", "fraction", "framed", "framedtext", "from", "getbuffer", "getmarking", "getnumber", "godown", "goto", "gotobox", "gotopage", "graycolor", "greyvalue", "grid", "hairline", "head", "headerdistance", "headerheight", "headlevel", "headnumber", "headsym", "headtext", "hideblocks", "high", "hl", "immediatebetweenlist", "immediatetolist", "in", "incrementnumber", "indentation", "indenting", "inframed", "infull", "ininner", "inleft", "inleftedge", "inleftmargin", "inline", "inmaframed", "inmargin", "inneredgedistance", "inneredgewidth", "innermargindistance", "innermarginwidth", "inothermargin", "inouter", "inright", "inrightedge", "inrightmargin", "installlanguage", "interactionbar", "interactionbuttons", "interactionmenu", "item", "items", "its", "keepblocks", "label", "labeling", "labels", "labeltext", "language", "leftaligned", "leftedgedistance", "leftedgewidth", "leftmargindistance", "leftmarginwidth", "leg", "linethickness", "listheight", "listlength", "listsymbol", "listwidth", "loadsorts", "loadsynonyms", "logfields", "lohi", "low", "maframed", "mainlanguage", "makeupheight", "makeupwidth", "mapfontsize", "mar", "margindistance", "marginrule", "margintext", "margintitle", "marginwidth", "marginword", "marking", "markversion", "mathematics", "mediaeval", "menubutton", "midaligned", "mirror", "month", "moveformula", "moveongrid", "movesidefloat", "name", "navigating", "nextsection", "nocap", "nodimension", "noheaderandfooterlines", "noindenting", "nolist", "nomarking", "nomoreblocks", "nomorefiles", "nop", "nospace", "note", "notopandbottomlines", "nowhitespace", "numberofsubpages", "numbers", "outeredgedistance", "outeredgewidth", "outermargindistance", "outermarginwidth", "overbar", "overbars", "overstrike", "overstrikes", "packed", "page", "pagedepth", "pagenumber", "pageoffset", "pagereference", "paperheight", "paperwidth", "paragraph", "part", "periods", "placebookmarks", "placecombinedlist", "placefloat", "placefootnotes", "placeformula", "placeheadnumber", "placeheadtext", "placelegend", "placelist", "placelistoffloats", "placelistofsorts", "placelistofsynonyms", "placelocalfootnotes", "placelogos", "placeongrid", "placeontopofeachother", "placepagenumber", "placerawlist", "placereferencelist", "placeregister", "placerule", "placesidebyside", "placesubformula", "placetextvariable", "position", "positiontext", "printpaperheight", "printpaperwidth", "processblocks", "processpage", "product", "program", "project", "publication", "quotation", "quote", "ran", "redo", "ref", "reference", "referral", "referraldate", "referring", "register", "remark", "reservefloat", "reset", "resetmarking", "resetnumber", "resettextcontent", "rightaligned", "rightedgedistance", "rightedgewidth", "rightmargindistance", "rightmarginwidth", "romannumerals", "rotate", "scale", "screen", "section", "seeregister", "selectblocks", "selectpaper", "selectversion", "setnumber", "settextcontent", "settextvariable", "setupalign", "setupanswerarea", "setuparranging", "setupbackground", "setupbackgrounds", "setupblackrules", "setupblank", "setupblock", "setupbodyfont", "setupbodyfontenvironment", "setupbottom", "setupbottomtexts", "setupbuffer", "setupbuttons", "setupcapitals", "setupcaption", "setupcaptions", "setupclipping", "setupcolor", "setupcolors", "setupcolumns", "setupcolumnset", "setupcolumnsetlines", "setupcolumnsetstart", "setupcombinations", "setupcombinedlist", "setupcomment", "setupdescriptions", "setupenumerations", "setupexternalfigures", "setupfield", "setupfields", "setupfillinlines", "setupfillinrules", "setupfloat", "setupfloats", "setupfloatsplitting", "setupfonthandling", "setupfontsynonym", "setupfooter", "setupfootertexts", "setupfootnotedefinition", "setupfootnotes", "setupforms", "setupformulae", "setupframed", "setupframedtexts", "setuphead", "setupheader", "setupheadertexts", "setupheadnumber", "setupheads", "setupheadtext", "setuphyphenmark", "setupindentedtext", "setupindenting", "setupinmargin", "setupinteraction", "setupinteractionbar", "setupinteractionmenu", "setupinteractionscreen", "setupinterlinespace", "setupinterlinespace2", "setupitemgroup", "setupitemizations", "setupitems", "setuplabeltext", "setuplanguage", "setuplayout", "setuplegend", "setuplinenumbering", "setuplines", "setuplinewidth", "setuplist", "setuplistalternative", "setupmakeup", "setupmarginblocks", "setupmarginrules", "setupmarking", "setupmathalignment", "setupnarrower", "setupnumber", "setupnumbering", "setupoppositeplacing", "setupoutput", "setuppagecomment", "setuppagenumber", "setuppagenumbering", "setuppagetransitions", "setuppalet", "setuppaper", "setuppapersize", "setupparagraphnumbering", "setupparagraphs", "setupplacement", "setuppositioning", "setupprofiles", "setupprograms", "setuppublications", "setupquote", "setupreferencelist", "setupreferencing", "setupregister", "setuprotate", "setuprule", "setups", "setupscreens", "setupsection", "setupsectionblock", "setupsorting", "setupspacing", "setupstartstop", "setupstrut", "setupsubpagenumber", "setupsymbolset", "setupsynchronization", "setupsynchronizationbar", "setupsynonyms", "setupsystem", "setuptab", "setuptables", "setuptabulate", "setuptext", "setuptextposition", "setuptextrules", "setuptexttexts", "setuptextvariable", "setupthinrules", "setuptolerance", "setuptop", "setuptoptexts", "setuptype", "setuptyping", "setupunderbar", "setupurl", "setupversions", "setupwhitespace", "showbodyfont", "showbodyfontenvironment", "showcolor", "showcolorgroup", "showexternalfigures", "showfields", "showframe", "showgrid", "showlayout", "showmakeup", "showpalet", "showprint", "showsetups", "showstruts", "showsymbolset", "someline", "somewhere", "sort", "space", "splitfloat", "startalignment", "startbackground", "startbuffer", "startcoding", "startcolor", "startcolumnmakeup", "startcolumns", "startcolumnset", "startcombination", "startcomment", "startcomponent", "startdescription", "startdocument", "startenumeration", "startenvironment", "startfact", "startfigure", "startfloattext", "startformula", "startframedtext", "startglobal", "starthiding", "startinteractionmenu", "startitemgroup", "startlegend", "startline", "startlinecorrection", "startlinenumbering", "startlines", "startlocal", "startlocalenvironment", "startlocalfootnotes", "startmakeup", "startmarginblock", "startmarginrule", "startnamemakeup", "startnarrower", "startopposite", "startoverlay", "startoverview", "startpacked", "startparagraph", "startpositioning", "startpostponing", "startproduct", "startprofile", "startproject", "startquotation", "startraster", "startregister", "startsymbolset", "startsynchronization", "starttable", "starttables", "starttabulate", "starttext", "starttextrule", "starttyping", "startunpacked", "startversion", "stopalignment", "stopbackground", "stopbuffer", "stopcoding", "stopcolor", "stopcolumnmakeup", "stopcolumns", "stopcolumnset", "stopcombination", "stopcomment", "stopcomponent", "stopdescription", "stopdocument", "stopenumeration", "stopenvironment", "stopfact", "stopfigure", "stopfloattext", "stopformula", "stopframedtext", "stopglobal", "stophiding", "stopinteractionmenu", "stopitemgroup", "stoplegend", "stopline", "stoplinecorrection", "stoplinenumbering", "stoplines", "stoplocal", "stoplocalenvironment", "stoplocalfootnotes", "stopmakeup", "stopmarginblock", "stopmarginrule", "stopnamemakeup", "stopnarrower", "stopopposite", "stopoverlay", "stopoverview", "stoppacked", "stopparagraph", "stoppositioning", "stoppostponing", "stopproduct", "stopprofile", "stopproject", "stopquotation", "stopraster", "stopsymbolset", "stopsynchronization", "stoptable", "stoptables", "stoptabulate", "stoptext", "stoptextrule", "stoptyping", "stopunpacked", "stopversion", "stretched", "sub", "subformulanumber", "subject", "subpagenumber", "subsection", "subsubject", "subsubsection", "subsubsubject", "switchtobodyfont", "switchtorawfont", "sym", "symbol", "symoffset", "synchronizationbar", "synchronize", "synonym", "tab", "testcolumn", "testpage", "tex", "textheight", "textreference", "textrule", "textvariable", "textwidth", "thinrule", "thinrules", "title", "tooltip", "topdistance", "topheight", "topspace", "totalnumberofpages", "translate", "txt", "typ", "type", "typebuffer", "typefile", "underbar", "underbars", "unitmeaning", "unknown", "useJSscripts", "useURL", "useXMLfilter", "useblocks", "usecommands", "usedirectory", "useencoding", "useexternaldocument", "useexternalfigure", "useexternalfile", "useexternalfiles", "useexternalsoundtrack", "usemodule", "usemodules", "usereferences", "usespecials", "usesymbols", "usetypescript", "usetypescriptfile", "useurl", "version", "vl", "weekday", "whitespace", "wordright", "writebetweenlist", "writetolist", "writetoreferencelist", "writetoregister" },
["fr"]={ "CAP", "Cap", "Caps", "Caractere", "Caracteres", "Chiffresromains", "JOURSEMAINE", "MOIS", "MOT", "MOTS", "Mot", "Mots", "Numeros", "a", "adaptedisposition", "affectenumero", "affectevariabletexte", "ajustechamp", "alaligne", "alapage", "aligneadroite", "aligneagauche", "aligneaumilieu", "appendix", "arg", "arriereplan", "atleftmargin", "atrightmargin", "baha", "barrecouleur", "barreinteraction", "barresynchronisation", "bas", "bouton", "boutonmenu", "boutonsinteraction", "but", "cacheblocs", "cap", "caractere", "caracteres", "champ", "changepolicebrute", "changepolicecorps", "chapter", "chem", "chiffresromains", "citation", "citer", "clip", "clonechamp", "colonne", "comment", "commentaire", "comparegroupecouleur", "comparepalette", "completecombinedlist", "completelistoffloats", "completelistofsorts", "completelistofsynonyms", "completenumeropage", "completeregistre", "composant", "composeenalinea", "concernant", "convertitnumero", "copitchamp", "corrigeespaceblanc", "couleur", "couleurgrise", "coupledocument", "coupledregister", "couplemarquage", "couplepapier", "coupleregistre", "crlf", "cutspace", "dactylographier", "dans", "dansautremarge", "dansborddroit", "dansbordgauche", "dansdroite", "dansgauche", "dansmarge", "dansmargedroite", "dansmargegauche", "date", "datecourante", "daterecommandation", "de", "decouplemarquage", "decrementenumero", "definebodyfontDEF", "definebodyfontREF", "definecombination", "definedfont", "definefontfeature", "definefonthandling", "defineframed", "defineframedtext", "defineindentedtext", "defineitemgroup", "definemathalignment", "defineplacement", "definetypeface", "definicaractere", "definit", "definitaccent", "definitbloc", "definitblocsection", "definitbuffer", "definitcalque", "definitchamp", "definitchampprincipal", "definitcommande", "definitconversion", "definitcouleur", "definitdactylo", "definitdansmarge", "definitdemarrestoppe", "definitdescription", "definitdisposition", "definitenumeration", "definitenvironnementpolicecorps", "definitetiquette", "definitflottant", "definitformatreference", "definitgroupecouleur", "definithbox", "definitjeucolonne", "definitliste", "definitlisteimbriquee", "definitlistereference", "definitlogo", "definitmakeup", "definitmarquage", "definitmenuinteraction", "definitnotepdp", "definitpalette", "definitparagraphes", "definitpilechamp", "definitpolice", "definitpolicebrute", "definitpolicecorps", "definitpositiontexte", "definitprofil", "definitprogramme", "definitreference", "definitregistre", "definitregle", "definitrevetement", "definitsautdecolonne", "definitsautdepage", "definitsection", "definitsortie", "definitsouschamp", "definitstyle", "definitstylepolice", "definitsymbole", "definitsymbolefigure", "definitsynonymepolice", "definitsynonymes", "definittabulation", "definittaillepapier", "definittete", "definittexte", "definittrametableau", "definittri", "definittype", "definitvariabletexte", "definitversion", "definitvide", "demarrealignement", "demarrearriereplan", "demarreblocmarge", "demarrecitation", "demarreciter", "demarrecodage", "demarrecolonnes", "demarrecombinaison", "demarrecompoetroite", "demarrecomposant", "demarrecorrectionligne", "demarrecouleur", "demarredegroupe", "demarredocument", "demarreenvironement", "demarrefigure", "demarreglobal", "demarregroupe", "demarrejeucolonne", "demarrejeusymboles", "demarreligne", "demarreligneregleetexte", "demarrelignes", "demarrelocal", "demarremakeup", "demarremargereglee", "demarrenotespdplocales", "demarrenumerotationligne", "demarreopposition", "demarrepositionnement", "demarreproduit", "demarreprofil", "demarreprojet", "demarreraster", "demarrerevetement", "demarresynchronisation", "demarretableau", "demarretableaux", "demarretexte", "demarreversion", "demarrevuedensemble", "deplaceformule", "deplacesurgrille", "description", "determinecaracteristiqueliste", "determinecaracteristiquesregistre", "determinenumerotete", "dimension", "distancebord", "distanceborddroit", "distancebordgauche", "distanceentete", "distanceinf", "distancemarge", "distancemargedroite", "distancemargegauche", "distancepdp", "distancesup", "domicile", "echelle", "ecran", "ecritdansliste", "ecritdanslistereference", "ecritentreliste", "ecritregistre", "el", "element", "elements", "emptylines", "enumeration", "environement", "espace", "espaceblanc", "espacefixe", "espaceinf", "espacesfixes", "espacesup", "etiquette", "etiquettes", "etire", "fait", "faitreference", "fichierdactylo", "figureexterne", "forceblocs", "fraction", "framed", "framedtext", "gardeblocs", "getnumber", "grille", "groupe", "haut", "hauteureditionpapier", "hauteurentete", "hauteurinf", "hauteurliste", "hauteurmakeup", "hauteurpapier", "hauteurpdp", "hauteursup", "hauteurtexte", "headsym", "hl", "immediatebetweenlist", "immediatetolist", "inconnu", "incrementenumero", "indentation", "inframed", "infull", "inhibemenuinteraction", "ininner", "inmframed", "inneredgedistance", "inneredgewidth", "innermargindistance", "innermarginwidth", "inouter", "installelangue", "joursemaine", "labeling", "labeltexte", "langue", "langueprincipale", "largeurbord", "largeurborddroit", "largeurbordgauche", "largeureditionpapier", "largeurligne", "largeurliste", "largeurmakeup", "largeurmarge", "largeurmargedroite", "largeurmargegauche", "largeurpapier", "largeurtexte", "leg", "ligneh", "lignenoire", "ligneregleetexte", "lignesnoires", "listesymbole", "llongueurliste", "loadsorts", "loadsynonyms", "logchamp", "mapfontsize", "mar", "margereglee", "marquage", "marquageversion", "marquepage", "mathematique", "mediaeval", "menuinteraction", "mframed", "mois", "montrecadre", "montrechamps", "montrecouleur", "montredisposition", "montreedition", "montreenvironnementpolicecorps", "montrefiguresexternes", "montregrille", "montregroupecouleur", "montrejeusymboles", "montremakeup", "montrepalette", "montrepolicecorps", "montrereglages", "montrestruts", "motdroit", "motmarge", "movesidefloat", "name", "navigating", "nextsection", "niveautete", "nocap", "nombredesouspages", "nombretotaldepages", "nommacro", "nop", "note", "notepdp", "numeroformule", "numeropage", "numeros", "numerosousformule", "numerotete", "numerotetecourant", "obtientmarquage", "oriente", "outeredgedistance", "outeredgewidth", "outermargindistance", "outermarginwidth", "overbar", "overbars", "overstrike", "overstrikes", "page", "pagedepth", "pagedouble", "pageoffset", "paragraph", "part", "pasplusdeblocs", "pasplusdefichiers", "periodes", "pilechamp", "placecoteacote", "placeflottant", "placeformule", "placelegende", "placelesunsaudessusdesautres", "placeliste", "placelisteinmbriquee", "placelistereference", "placelistoffloats", "placelistofsorts", "placelistofsynonyms", "placelogos", "placemarquespages", "placenotespdp", "placenotespdplocales", "placenumeropage", "placenumerotete", "placerawlist", "placeregistre", "placeregle", "placesousformule", "placesurgrille", "placetextetete", "placevariabletexte", "position", "positionnetexte", "prendbuffer", "produit", "programme", "projet", "publication", "qqpart", "ran", "raz", "razmarquage", "raznumero", "recommandation", "ref", "refait", "reference", "referencepage", "referencetexte", "reflete", "register", "reglages", "reglealignement", "reglearrangement", "reglearriereplan", "reglearriereplans", "reglebarreinteraction", "reglebarresynchronisation", "reglebloc", "regleblocmarge", "regleblocsection", "regleboutons", "reglebuffer", "reglecapitales", "reglechamp", "reglechamps", "regleclipping", "reglecolonnes", "reglecombinaisons", "reglecommentaire", "reglecommentairepage", "reglecompoetroite", "reglecomposeenalinea", "reglecouleur", "reglecouleurs", "regledactylo", "regledansmarge", "regledemarrestoppe", "regledescriptions", "regledisposition", "regleecraninteraction", "regleecrans", "regleelements", "regleencadre", "regleentete", "regleenumerations", "regleenvironnementpolicecorps", "regleepaisseurligne", "regleespaceblanc", "regleespacement", "regleespacementinterligne", "reglefiguresexternes", "regleflottant", "regleflottants", "regleformulaires", "regleformules", "reglegroupeselements", "regleinf", "regleinteraction", "regleintitule", "regleintitules", "reglejeucolonne", "reglejeusymboles", "reglelabeltexte", "reglelangue", "reglelegende", "reglelignes", "reglelignesnoires", "reglelignesreglestexte", "regleliste", "reglelisteimbriquee", "reglelistereference", "reglemakeup", "reglemargereglee", "reglemarquage", "reglemarquagehyphenation", "reglemenuinteraction", "reglenotepdp", "reglenumero", "reglenumeropage", "reglenumerotation", "reglenumerotationligne", "reglenumerotationpage", "reglenumerotationparagraphe", "reglenumerotete", "regleoriente", "reglepalette", "reglepapier", "regleparagraphes", "reglepdp", "regleplacementopposition", "reglepolicecorps", "reglepositionnement", "reglepositiontexte", "regleprofils", "regleprogrammes", "reglepublications", "reglereferencage", "regleregistre", "regleregle", "regleremplitligne", "regleremplitlignesreglees", "reglesection", "regleseparationflottant", "reglesortie", "reglesouslignage", "reglesousnumeropage", "reglestrut", "reglesup", "reglesynchronisation", "reglesynonymes", "reglesysteme", "regletab", "regletableaux", "regletabulation", "regletaillepapier", "regletete", "regletetes", "regletexte", "regletextesentete", "regletextesinf", "regletextespdp", "regletextessup", "regletextestexte", "regletextetete", "regletolerance", "regletraitsfins", "regletransitionspage", "regletri", "regletype", "regleurl", "reglevariabletexte", "regleversions", "remplitchamp", "remplitligne", "remplitlignesreglees", "remplittexte", "reservefloat", "resettextcontent", "retourarriere", "sansalinea", "sansdimension", "sansespace", "sansespaceblanc", "sanslignesenteteetpdp", "sanslignessupetinf", "sansliste", "sansmarquage", "sanstest", "sauteblocs", "section", "seeregister", "selectionneblocs", "selectionnepapier", "selectionneversion", "sensunite", "separeflottant", "settext", "setupanswerarea", "setupcolumnsetlines", "setupcolumnsetstart", "setupfonthandling", "setupfontsynonym", "setupframedtexts", "setupindentedtext", "setupinterlinespace2", "setupitemgroup", "setuplistalternative", "setupmathalignment", "setupplacement", "sort", "sousnumeropage", "startalignment", "startarriereplan", "startbuffer", "startcitation", "startcolumnmakeup", "startcolumns", "startcombination", "startcomment", "startcomposant", "startcouleur", "startdescription", "startdocument", "startenumeration", "startenvironement", "startfait", "startfigure", "startfloattext", "startformula", "startframedtext", "startgroupe", "starthiding", "startitemgroup", "startlegend", "startligneregleetexte", "startline", "startlinecorrection", "startlinenumbering", "startlines", "startlocal", "startlocalenvironment", "startlocalfootnotes", "startmakeup", "startmargereglee", "startmarginblock", "startmenuinteraction", "startnamemakeup", "startnarrower", "startopposite", "startoverlay", "startoverview", "startparagraph", "startpositioning", "startpostponing", "startproduit", "startprofile", "startprojet", "startregister", "startsymbolset", "startsynchronization", "starttable", "starttables", "starttabulate", "starttyping", "startunpacked", "startversion", "stopalignment", "stoparriereplan", "stopbuffer", "stopcitation", "stopcolumnmakeup", "stopcolumns", "stopcombination", "stopcomment", "stopcompoetroite", "stopcomposant", "stopcouleur", "stopdescription", "stopdocument", "stopenumeration", "stopenvironement", "stopfait", "stopfigure", "stopfloattext", "stopformula", "stopframedtext", "stopgroupe", "stophiding", "stopitemgroup", "stoplegend", "stopligneregleetexte", "stopline", "stoplinecorrection", "stoplinenumbering", "stoplines", "stoplocal", "stoplocalenvironment", "stoplocalfootnotes", "stopmakeup", "stopmargereglee", "stopmarginblock", "stopmenuinteraction", "stopnamemakeup", "stopnarrower", "stopopposite", "stopoverlay", "stopoverview", "stopparagraph", "stoppealignement", "stoppearriereplan", "stoppeblocmarge", "stoppecitation", "stoppecodage", "stoppecolonnes", "stoppecombinaison", "stoppecomposant", "stoppecorrectionligne", "stoppecouleur", "stoppedegroupe", "stoppedocument", "stoppeenvironement", "stoppeglobal", "stoppegroupe", "stoppejeucolonne", "stoppeligne", "stoppeligneregleetexte", "stoppelignes", "stoppelocal", "stoppemakeup", "stoppemargereglee", "stoppenotespdplocales", "stoppenumerotationligne", "stoppeopposition", "stoppepositionnement", "stoppeproduit", "stoppeprofil", "stoppeprojet", "stopperaster", "stopperevetement", "stoppesynchronisation", "stoppetableau", "stoppetableaux", "stoppetexte", "stoppeversion", "stoppevuedensemble", "stoppositioning", "stoppostponing", "stopproduit", "stopprofile", "stopprojet", "stopsymbolset", "stopsynchronization", "stoptable", "stoptables", "stoptabulate", "stoptyping", "stopunpacked", "stopversion", "sub", "subject", "subsection", "subsubject", "subsubsection", "subsubsubject", "suggestion", "suivantprofil", "suivantversion", "suivantversionprofil", "sym", "symbole", "synchronise", "synonym", "tab", "tapebuffer", "testcolumn", "testpage", "tete", "tex", "textemarge", "textenotepdp", "textetete", "title", "titremarge", "traduire", "traiteblocs", "traitepage", "traitfin", "traitsfins", "txt", "typ", "underbar", "underbars", "uneligne", "useXMLfilter", "usedirectory", "usetypescript", "usetypescriptfile", "utiliseJSscripts", "utiliseURL", "utiliseblocs", "utilisechemin", "utilisecommandes", "utilisedocumentexterne", "utiliseencodage", "utilisefichierexterne", "utilisefichiersexternes", "utilisefigureexterne", "utilisemodule", "utilisemodules", "utilisepsiteaudioexterne", "utilisereferences", "utilisespecialites", "utilisesymboles", "utiliseurl", "va", "vaalaboite", "vaalapage", "vaenbas", "valeurcouleur", "valeurgris", "variabletexte", "version", "vide", "vl" },
["it"]={ "CAP", "Cap", "Caps", "GIORNOSETTIMANA", "Lettera", "Lettere", "MESE", "Numeri", "Numeriromani", "PAROLA", "PAROLE", "Parola", "Parole", "accoppiacarta", "accoppiadocumento", "accoppiamarcatura", "accoppiapagina", "accoppiaregistro", "adattacampo", "adattalayout", "al", "allineacentro", "allineadestra", "allineasinistra", "altezzacarta", "altezzacartastampa", "altezzacima", "altezzaelenco", "altezzafondo", "altezzaintestazione", "altezzamakeup", "altezzapdp", "altezzatesto", "ambiente", "ampiezzabordo", "ampiezzabordodestro", "ampiezzabordosinistro", "ampiezzacarta", "ampiezzacartastampa", "ampiezzaelenco", "ampiezzamakeup", "ampiezzamargine", "ampiezzamarginedestro", "ampiezzamarginesinistro", "ampiezzatesto", "ap", "apagina", "appendix", "arg", "atleftmargin", "atrightmargin", "barracolori", "barrainterazione", "barrasincronizzazione", "bastablocchi", "bastafile", "cambiaafontdeltesto", "campi", "camporiempimento", "cap", "capello", "chapter", "chim", "circondato", "citazione", "clip", "clonacampo", "colonna", "colore", "coloregrigio", "comment", "commento", "completecombinedlist", "completelistoffloats", "completelistofsorts", "completelistofsynonyms", "completeregister", "componenet", "confrontagruppocolori", "confrontatavolozza", "convertinumero", "copiacampo", "correggispaziobianco", "coupledregister", "crlf", "cutspace", "da", "daqualcheparte", "data", "datadioggi", "datareferral", "decrementnumber", "definebodyfontDEF", "definebodyfontREF", "definecolumnbreak", "definecombination", "definedfont", "definefontfeature", "definefonthandling", "defineindentedtext", "defineinmargin", "defineitemgroup", "definelayer", "definemathalignment", "definepagebreak", "defineplacement", "definetypeface", "definisci", "definisciaccento", "definisciambientefontdeltesto", "definisciblocco", "definiscibloccosezione", "definiscibuffer", "definiscicampo", "definiscicampoprincipale", "definiscicapoversi", "definiscicarattere", "definiscicolore", "definiscicomando", "definisciconversione", "definiscidescrizione", "definiscidimensionicarta", "definiscielenco", "definiscielencocombinato", "definiscienumerazione", "definiscietichetta", "definiscifigurasimbolo", "definiscifont", "definiscifontdeltesto", "definiscifontgrezzo", "definisciformatoriferimento", "definiscigruppocolonne", "definiscigruppocolori", "definiscihbox", "definisciincorniciato", "definisciiniziatermina", "definiscilayout", "definiscilinea", "definiscilistariferimenti", "definiscilogo", "definiscimakeup", "definiscimarcatura", "definiscimenuinterazione", "definiscimodellotabella", "definiscioggettomobile", "definisciordinamento", "definiscioutput", "definisciposizionetesto", "definisciprofilo", "definisciprogramma", "definisciregistro", "definisciriferimento", "definiscirigovuoto", "definiscisezione", "definiscisimbolo", "definiscisinonimi", "definiscisinonimofont", "definiscisottocampo", "definiscisovrapposizione", "definiscistackcampi", "definiscistile", "definiscistilefont", "definiscitabulato", "definiscitavolozza", "definiscitesta", "definiscitesto", "definiscitestoincorniciato", "definiscitype", "definiscityping", "definiscivariabiletesto", "definisciversion", "description", "determinacaratteristicheregistro", "determinacarattersticheelenco", "determinanumerotesta", "dimensione", "disabilitamenuinterazione", "distanzabordo", "distanzabordodestro", "distanzabordosinistro", "distanzacima", "distanzafondo", "distanzaintestazione", "distanzamargine", "distanzamarginedestro", "distanzamarginesinistro", "distanzapdp", "domicilio", "el", "elaborablocchi", "elaborapagina", "elementi", "elemento", "emptylines", "enumeration", "etichetta", "etichette", "fatto", "figuraesterna", "fondo", "forzablocchi", "framedtext", "frazione", "getnumber", "giornosettimana", "griglia", "headsym", "hl", "ignoto", "immediatebetweenlist", "immediatetolist", "impaccato", "impostaallineamento", "impostaambientefontdeltesto", "impostaampiezzariga", "impostabarrainterazione", "impostabarrasincronizzazione", "impostablocchimargine", "impostablocco", "impostabloccosezione", "impostabuffer", "impostacampi", "impostacampo", "impostacapoversi", "impostacaption", "impostacaptions", "impostacima", "impostaclippling", "impostacolonne", "impostacolore", "impostacolori", "impostacombinazioni", "impostacommento", "impostacommentopagina", "impostadefinizionenotepdp", "impostadescrizioni", "impostadimensionicarta", "impostaelementi", "impostaelencazioni", "impostaelenco", "impostaelencocombinato", "impostaenumerazioni", "impostafigureesterne", "impostafondo", "impostafontdeltesto", "impostaforms", "impostaformule", "impostagruppocolonne", "impostaincorniciato", "impostainiziatermina", "impostainmargine", "impostainstestazione", "impostainterazione", "impostainterlinea", "impostalayout", "impostalegenda", "impostalinea", "impostalineemargine", "impostalineenere", "impostalineeriempimento", "impostalineesottili", "impostalineetesto", "impostalingua", "impostalistariferimenti", "impostamaiuscole", "impostamakeup", "impostamarcatura", "impostamenuinterazione", "impostamenzione", "impostanotepdp", "impostanumerazione", "impostanumerazionecapoversi", "impostanumerazionepagina", "impostanumerazionerighe", "impostanumeropagina", "impostanumerosottopagina", "impostanumerotesta", "impostaoggettimobili", "impostaoggettomobile", "impostaordinamento", "impostaoutput", "impostaparranging", "impostapdp", "impostapiustretto", "impostaposizionamento", "impostaposizionamentoopposti", "impostaposizionetesto", "impostaprofili", "impostaprogrammi", "impostapubblicazioni", "impostapulsanti", "impostaregistro", "impostarientro", "impostariferimento", "impostarighe", "impostarigheriempimento", "impostarigovuoto", "impostarotazione", "impostaschermi", "impostaschermointerazione", "impostasegnosillabazione", "impostasetsimboli", "impostasezione", "impostasfondi", "impostasfondo", "impostasincronizzazione", "impostasinonimi", "impostasistema", "impostasottolinea", "impostaspaziatura", "impostaspaziobianco", "impostaspezzamentooggettomobile", "impostastrut", "impostatab", "impostatabelle", "impostatabulato", "impostatavolozza", "impostatesta", "impostateste", "impostatesticima", "impostatestifondo", "impostatestiincorniciati", "impostatestiintestazioni", "impostatestipdp", "impostatesto", "impostatestoetichette", "impostatestointestazioni", "impostatestotesti", "impostatolleranza", "impostatransizionepagina", "impostatype", "impostatyping", "impostaurl", "impostavariabiletesto", "impostaversioni", "impostazioni", "in", "inaltromargine", "incorniciato", "incrementanumero", "indentation", "indestra", "ininner", "iniziaallineamento", "iniziaambiente", "iniziabloccomargine", "iniziacitazione", "iniziacodifica", "iniziacolonne", "iniziacolore", "iniziacombinazione", "iniziacomponente", "iniziacorrezioneriga", "iniziadocumento", "iniziafigura", "iniziaglobale", "iniziagruppocolonne", "iniziaimpaccato", "inizialineamargine", "inizialineatesto", "inizialocale", "iniziamakeup", "inizianotepdplocali", "inizianumerazionerighe", "iniziaopposto", "iniziaoverview", "iniziapiustretto", "iniziaposizionamento", "iniziaprodotto", "iniziaprofilo", "iniziaprogetto", "iniziaraster", "iniziariga", "iniziarighe", "iniziasetsimboli", "iniziasfondo", "iniziasincronizzazione", "iniziasovrapposizione", "iniziatabella", "iniziatabelle", "iniziatesto", "iniziaunpacked", "iniziaversione", "inlatodestro", "inlatosinistro", "inmaframed", "inmargine", "inmarginedestro", "inmarginesinistro", "inneredgedistance", "inneredgewidth", "innermargindistance", "innermarginwidth", "inouter", "inriga", "insinistra", "installalingua", "intorno", "labeling", "leg", "lettera", "lettere", "lineamargine", "lineanera", "lineasottile", "lineatesto", "lineenere", "lineeriempimento", "lineesottili", "lingua", "linguaprincipale", "listsymbol", "livellotesta", "loadsorts", "loadsynonyms", "logcampi", "lunghezzaelenco", "maframed", "mapfontsize", "mar", "marcatura", "marcaversione", "matematica", "mediaeval", "menuinterattivo", "menzione", "mese", "mettielenco", "mettielencocombinato", "mettifiancoafianco", "mettiformula", "mettiingriglia", "mettilegenda", "mettilinea", "mettiloghi", "mettinotepdp", "mettinotepdplocali", "mettinumeropagina", "mettiregistro", "mettisegnalibro", "mettisottoformula", "mettiunosullaltro", "mettivariabiletesto", "mostraambientefontdeltesto", "mostracampi", "mostracolore", "mostracornice", "mostrafiguresterne", "mostrafontdeltesto", "mostragriglia", "mostragruppocolori", "mostraimpostazioni", "mostralyout", "mostramakeup", "mostrasetsimboli", "mostrastampa", "mostrastruts", "mostratavolozza", "movesidefloat", "name", "nascondiblocchi", "navigating", "nextsection", "nientedimensioni", "nienteelenco", "nientelineecimafondo", "nientelineintestazionepdp", "nientemarcatura", "nienterientro", "nientespazio", "nientespaziobianco", "nocap", "nome", "nomeunita", "nop", "nota", "notapdp", "notest", "numberofsubpages", "numeri", "numeriromani", "numeroformula", "numeropagina", "numeropaginacompleto", "numerosottoformula", "numerotesta", "numerotestacorrente", "numerototaledipagine", "outeredgedistance", "outeredgewidth", "outermargindistance", "outermarginwidth", "overbar", "overbars", "overstrike", "overstrikes", "pagedepth", "pageoffset", "pagina", "paragraph", "paroladestra", "parolainmargine", "part", "passaafontgrezzo", "ped", "pedap", "perlungo", "placefloat", "placelistoffloats", "placelistofsorts", "placelistofsynonyms", "placerawlist", "placereferencelist", "posizionanumerotesta", "posizionatesto", "posizionatestotesta", "posizione", "prendibuffer", "prendimarcatura", "prodotto", "progetto", "programma", "pubblicazione", "pulsante", "pulsantemenu", "pulsantinterazione", "punti", "qualcheriga", "ran", "referral", "referring", "register", "reimposta", "reimpostamarcatura", "reservefloat", "resetnumber", "resettextcontent", "rientro", "rif", "rifai", "riferimento", "riferimentopagina", "riferimentotesto", "riflessione", "rigariempimento", "rigovuoto", "ruota", "saltablocchi", "scala", "schermo", "scrividentroelenco", "scriviinelenco", "scriviinlistariferimenti", "scriviinregistro", "section", "seeregister", "segnalibro", "seguiprofilo", "seguiversione", "seguiversioneprofilo", "selezionablocchi", "selezionacarta", "selezionaversione", "separamarcatura", "setnumber", "settext", "setupanswerarea", "setupcolumnsetlines", "setupcolumnsetstart", "setupfonthandling", "setupfontsynonym", "setupindentedtext", "setupinterlinespace2", "setupitemgroup", "setuplistalternative", "setupmathalignment", "setuppaper", "setupplacement", "setvariabiletesto", "sfondo", "sim", "simbolo", "sincronizza", "sort", "spazifissi", "spazio", "spaziobianco", "spaziocima", "spaziodietro", "spaziofisso", "spaziofondo", "spessoreriga", "spezzaoggettomobile", "spostaagriglia", "spostaformula", "stackcampi", "startalignment", "startambiente", "startbuffer", "startcitazione", "startcolore", "startcolumnmakeup", "startcolumns", "startcombination", "startcomment", "startcomponenet", "startdescription", "startdocument", "startenumeration", "startfatto", "startfigure", "startfloattext", "startformula", "startframedtext", "starthiding", "startimpaccato", "startitemgroup", "startlegend", "startline", "startlineamargine", "startlineatesto", "startlinecorrection", "startlinenumbering", "startlines", "startlocal", "startlocalenvironment", "startlocalfootnotes", "startmakeup", "startmarginblock", "startmenuinterattivo", "startnamemakeup", "startnarrower", "startopposite", "startoverlay", "startoverview", "startparagraph", "startpositioning", "startpostponing", "startprodotto", "startprofile", "startprogetto", "startregister", "startsfondo", "startsymbolset", "startsynchronization", "starttable", "starttables", "starttabulate", "starttyping", "startunpacked", "startversione", "stirato", "stopalignment", "stopambiente", "stopbuffer", "stopcitazione", "stopcolore", "stopcolumnmakeup", "stopcolumns", "stopcombination", "stopcomment", "stopcomponenet", "stopdescription", "stopdocument", "stopenumeration", "stopfatto", "stopfigure", "stopfloattext", "stopformula", "stopframedtext", "stophiding", "stopimpaccato", "stopitemgroup", "stoplegend", "stopline", "stoplineamargine", "stoplineatesto", "stoplinecorrection", "stoplinenumbering", "stoplines", "stoplocal", "stoplocalenvironment", "stoplocalfootnotes", "stopmakeup", "stopmarginblock", "stopmenuinterattivo", "stopnamemakeup", "stopnarrower", "stopopposite", "stopoverlay", "stopoverview", "stopparagraph", "stoppositioning", "stoppostponing", "stopprodotto", "stopprofile", "stopprogetto", "stopsfondo", "stopsymbolset", "stopsynchronization", "stoptable", "stoptables", "stoptabulate", "stoptyping", "stopunpacked", "stopversione", "sub", "subject", "subpagenumber", "subsection", "subsubject", "subsubsection", "subsubsubject", "synonym", "tab", "terminaallineamento", "terminaambiente", "terminabloccomargine", "terminacitazione", "terminacodifica", "terminacolonne", "terminacolore", "terminacombinazione", "terminacomponente", "terminacorrezioneriga", "terminadocumento", "terminaglobale", "terminagruppocolonne", "terminaimpaccato", "terminalineamargine", "terminalineatesto", "terminalocale", "terminamakeup", "terminanotepdplocali", "terminanumerazionerighe", "terminaopposto", "terminaoverview", "terminapiustretto", "terminaposizionamento", "terminaprodotto", "terminaprofili", "terminaprogetto", "terminaraster", "terminariga", "terminarighe", "terminasfondo", "terminasincronizzazione", "terminasovrapposizione", "terminatabella", "terminatabelle", "terminatesto", "terminaunpacked", "terminaversioni", "testa", "testcolumn", "testoetichetta", "testoinmargine", "testoinstestazioni", "testonotapdp", "testoriempimento", "testpage", "tex", "tieniblocchi", "title", "titoloinmargine", "tooltip", "traduci", "txt", "typ", "type", "typebuffer", "typefile", "underbar", "underbars", "usaJSscripts", "usaURL", "usablocco", "usacartella", "usacodifica", "usacolonnasonoraesterna", "usacomandi", "usadocumentoesterno", "usafiguraesterna", "usafileesterni", "usafileesterno", "usamoduli", "usamodulo", "usariferimenti", "usasimboli", "usaspecialita", "usaurl", "useXMLfilter", "usedirectory", "usetypescript", "usetypescriptfile", "vaia", "vaiabox", "vaiapagina", "vaigiu", "valorecolore", "valoregrigio", "variabiletesto", "versione", "vl" },
- ["nl"]={ "CAP", "Cap", "Caps", "Cijfers", "KAP", "Kap", "Kaps", "Letter", "Letters", "MAAND", "Romeins", "WEEKDAG", "WOORD", "WOORDEN", "Woord", "Woorden", "aantalsubpaginas", "about", "achtergrond", "appendix", "arg", "bepaalkopnummer", "bepaallijstkenmerken", "bepaalregisterkenmerken", "betekenis", "binnenmargeafstand", "binnenmargebreedte", "binnenrandafstand", "binnenrandbreedte", "blanko", "blokje", "blokjes", "blokkeerinteractiemenu", "bodemwit", "bookmark", "bovenafstand", "bovenhoogte", "breuk", "buitenmargeafstand", "buitenmargebreedte", "buitenrandafstand", "buitenrandbreedte", "but", "button", "cap", "chapter", "chem", "cijfers", "citaat", "citeer", "clip", "comment", "completecombinedlist", "completelistoffloats", "completelistofsorts", "completelistofsynonyms", "converteernummer", "copieerveld", "corrigeerwitruimte", "coupledregister", "crlf", "datum", "definebodyfontDEF", "definebodyfontREF", "definedfont", "definefontfeature", "definefonthandling", "definerawfont", "definetypeface", "definieer", "definieeraccent", "definieeralineas", "definieerbeeldmerk", "definieerblanko", "definieerblok", "definieerbuffer", "definieercombinatie", "definieercommando", "definieerconversie", "definieerfiguursymbool", "definieerfont", "definieerfontstijl", "definieerfontsynoniem", "definieerhbox", "definieerhoofdveld", "definieeringesprongentext", "definieerinmarge", "definieerinteractiemenu", "definieeritemgroep", "definieerkadertekst", "definieerkarakter", "definieerkleur", "definieerkleurgroep", "definieerkolomgroep", "definieerkolomovergang", "definieerkop", "definieerkorps", "definieerkorpsomgeving", "definieerlayer", "definieerlayout", "definieerletter", "definieerlijn", "definieerlijst", "definieermarkering", "definieeromlijnd", "definieeropmaak", "definieeroverlay", "definieerpaginaovergang", "definieerpalet", "definieerpapierformaat", "definieerplaats", "definieerplaatsblok", "definieerprofiel", "definieerprogramma", "definieerreferentie", "definieerreferentieformaat", "definieerreferentielijst", "definieerregister", "definieersamengesteldelijst", "definieersectie", "definieersectieblok", "definieersorteren", "definieerstartstop", "definieersubveld", "definieersymbool", "definieersynoniemen", "definieertabelvorm", "definieertabulatie", "definieertekst", "definieertekstpositie", "definieertekstvariabele", "definieertype", "definieertypen", "definieeruitvoer", "definieerveld", "definieerveldstapel", "definieerversie", "definieerwiskundeuitlijnen", "description", "dimensie", "directnaarlijst", "directtussenlijst", "doordefinieren", "doorlabelen", "doornummeren", "dunnelijn", "dunnelijnen", "eenregel", "enumeration", "ergens", "externfiguur", "forceerblokken", "formulenummer", "framedtext", "gebruikJSscripts", "gebruikURL", "gebruikXMLfilter", "gebruikblokken", "gebruikcommandos", "gebruikexterndocument", "gebruikexternefile", "gebruikexternefiles", "gebruikexternfiguur", "gebruikexterngeluidsfragment", "gebruikgebied", "gebruikmodule", "gebruikmodules", "gebruikreferenties", "gebruikspecials", "gebruiksymbolen", "gebruiktypescript", "gebruiktypescriptfile", "gebruikurl", "geenblokkenmeer", "geenbovenenonderregels", "geendimensie", "geenfilesmeer", "geenhoofdenvoetregels", "geenlijst", "geenmarkering", "geenspatie", "geentest", "geenwitruimte", "geg", "grijskleur", "grijswaarde", "haalbuffer", "haalmarkering", "haalnummer", "haarlijn", "handhaafblokken", "herhaal", "hl", "hoofdafstand", "hoofdhoogte", "hoofdtaal", "hoog", "huidigedatum", "huidigekopnummer", "in", "inanderemarge", "inbinnen", "inbuiten", "indentation", "inlijnd", "inlinker", "inlinkermarge", "inlinkerrand", "inmarge", "inrechter", "inrechtermarge", "inrechterrand", "inregel", "inspringen", "installeertaal", "instellingen", "interactiebalk", "interactiebuttons", "interactiemenu", "invullijnen", "invulregel", "invultekst", "invulveld", "inwilijnd", "items", "its", "kantlijn", "kap", "kenmerk", "kenmerkdatum", "kentekstvariabeletoe", "kleur", "kleurenbalk", "kleurwaarde", "kloonveld", "kolom", "kop", "kopniveau", "kopnummer", "koppeldocument", "koppelmarkering", "koppelpagina", "koppelpapier", "koppelregister", "kopsym", "koptekst", "kopwit", "laag", "label", "labeling", "labels", "labeltekst", "laho", "leg", "legeregels", "letter", "letters", "lijndikte", "lijstbreedte", "lijsthoogte", "lijstlengte", "lijstsymbool", "linkermargeafstand", "linkermargebreedte", "linkerrandafstand", "linkerrandbreedte", "loadsorts", "loadsynonyms", "maand", "mapfontsize", "mar", "margeafstand", "margebreedte", "margetekst", "margetitel", "margewoord", "markeer", "markeerversie", "mediaeval", "menubutton", "naam", "naar", "naarbox", "naarpagina", "name", "navigerend", "nextsection", "nietinspringen", "nocap", "nokap", "noot", "nop", "omgeving", "omlaag", "omlijnd", "onbekend", "onderafstand", "onderdeel", "onderhoogte", "ontkoppelmarkering", "op", "opelkaar", "oplinkermarge", "oppagina", "oprechtermarge", "overbar", "overbars", "overstrike", "overstrikes", "pagina", "paginadiepte", "paginanummer", "paginaoffset", "paginareferentie", "papierbreedte", "papierhoogte", "paragraph", "part", "paslayoutaan", "passeerblokken", "passendveld", "plaatsbeeldmerken", "plaatsbookmarks", "plaatsformule", "plaatskopnummer", "plaatskoptekst", "plaatslegenda", "plaatslijn", "plaatslijst", "plaatslokalevoetnoten", "plaatsnaastelkaar", "plaatsonderelkaar", "plaatsopgrid", "plaatspaginanummer", "plaatsplaatsblok", "plaatsreferentielijst", "plaatsregister", "plaatsruwelijst", "plaatssamengesteldelijst", "plaatssubformule", "plaatstekstvariabele", "plaatsvoetnoten", "placelistoffloats", "placelistofsorts", "placelistofsynonyms", "positioneer", "positioneertekst", "printpapierbreedte", "printpapierhoogte", "produkt", "programma", "projekt", "publicatie", "punten", "ran", "randafstand", "randbreedte", "rechtermargeafstand", "rechtermargebreedte", "rechterrandafstand", "rechterrandbreedte", "ref", "refereer", "referentie", "regellinks", "regelmidden", "regelrechts", "register", "registreervelden", "reservefloat", "reset", "resetmarkering", "resetnummer", "resettekstinhoud", "resettextcontent", "romeins", "rooster", "roteer", "rugwit", "schaal", "scherm", "schrijfnaarlijst", "schrijfnaarreferentielijst", "schrijfnaarregister", "schrijftussenlijst", "section", "seeregister", "selecteerblokken", "selecteerpapier", "selecteerversie", "setnummer", "setupfonthandling", "setupfontsynonym", "setupinterlinespace2", "setuplistalternative", "snijwit", "som", "sort", "spatie", "spiegel", "splitsplaatsblok", "startachtergrond", "startalignment", "startbuffer", "startcitaat", "startcodering", "startcolumns", "startcombinatie", "startcombination", "startcomment", "startdescription", "startdocument", "startenumeration", "startfigure", "startfiguur", "startfloattext", "startformula", "startframedtext", "startgeg", "startglobaal", "starthiding", "startinteractiemenu", "startitemgroup", "startkantlijn", "startkleur", "startkolomgroep", "startkolommen", "startkolomopmaak", "startlegend", "startline", "startlinecorrection", "startlinenumbering", "startlines", "startlocal", "startlocalenvironment", "startlocalfootnotes", "startlokaal", "startlokalevoetnoten", "startmakeup", "startmargeblok", "startmarginblock", "startnaast", "startnamemakeup", "startnarrower", "startomgeving", "startonderdeel", "startopelkaar", "startopmaak", "startopposite", "startoverlay", "startoverview", "startoverzicht", "startparagraph", "startpositioneren", "startpositioning", "startpostponing", "startprodukt", "startprofiel", "startprofile", "startprojekt", "startraster", "startregel", "startregelcorrectie", "startregelnummeren", "startregels", "startregister", "startsmaller", "startsymbolset", "startsymboolset", "startsynchronisatie", "startsynchronization", "starttabel", "starttabellen", "starttable", "starttables", "starttabulate", "starttekst", "starttekstlijn", "starttyping", "startuitlijnen", "startunpacked", "startvanelkaar", "startversie", "stelachtergrondenin", "stelachtergrondin", "stelalineasin", "stelantwoordgebiedin", "stelarrangerenin", "stelblankoin", "stelblokin", "stelblokjesin", "stelblokkopjein", "stelblokkopjesin", "stelbovenin", "stelboventekstenin", "stelbufferin", "stelbuttonsin", "stelciterenin", "stelclipin", "stelcombinatiesin", "stelcommentaarin", "steldoordefinierenin", "steldoornummerenin", "steldunnelijnenin", "stelexternefigurenin", "stelformulesin", "stelformulierenin", "stelhoofdin", "stelhoofdtekstenin", "stelingesprongentextin", "stelinmargein", "stelinspringenin", "stelinteractiebalkin", "stelinteractiein", "stelinteractiemenuin", "stelinteractieschermin", "stelinterliniein", "stelinvullijnenin", "stelinvulregelsin", "stelitemgroepin", "stelitemsin", "stelkadertekstenin", "stelkantlijnin", "stelkapitalenin", "stelkleurenin", "stelkleurin", "stelkolomgroepin", "stelkolomgroepregelsin", "stelkolomgroepstartin", "stelkolommenin", "stelkopin", "stelkopnummerin", "stelkoppeltekenin", "stelkoppenin", "stelkoptekstin", "stelkorpsin", "stelkorpsomgevingin", "stellabeltekstin", "stellayoutin", "stellegendain", "stellijndiktein", "stellijnin", "stellijstin", "stelmargeblokkenin", "stelmarkeringin", "stelnaastplaatsenin", "stelnummerenin", "stelnummerin", "stelomlijndin", "stelonderin", "stelonderstrepenin", "stelondertekstenin", "stelopmaakin", "stelopsommingenin", "stelpaginacommentaarin", "stelpaginanummerin", "stelpaginanummeringin", "stelpaginaovergangenin", "stelpaletin", "stelpapierformaatin", "stelpapierin", "stelparagraafnummerenin", "stelplaatsblokin", "stelplaatsblokkenin", "stelplaatsbloksplitsenin", "stelplaatsin", "stelpositionerenin", "stelprofielenin", "stelprogrammasin", "stelpublicatiesin", "stelrastersin", "stelreferentielijstin", "stelrefererenin", "stelregelnummerenin", "stelregelsin", "stelregisterin", "stelroterenin", "stelsamengesteldelijstin", "stelsectieblokin", "stelsectiein", "stelsmallerin", "stelsorterenin", "stelspatieringin", "stelstartstopin", "stelstrutin", "stelsubpaginanummerin", "stelsymboolsetin", "stelsynchronisatiebalkin", "stelsynchronisatiein", "stelsynoniemenin", "stelsysteemin", "steltaalin", "steltabellenin", "steltabin", "steltabulatiein", "steltekstin", "steltekstinhoudin", "steltekstlijnenin", "steltekstpositiein", "stelteksttekstenin", "steltekstvariabelein", "steltolerantiein", "steltypein", "steltypenin", "steluitlijnenin", "steluitvoerin", "stelurlin", "stelveldenin", "stelveldin", "stelversiesin", "stelvoetin", "stelvoetnootdefinitiein", "stelvoetnotenin", "stelvoettekstenin", "stelwiskundeuitlijnenin", "stelwitruimtein", "stopachtergrond", "stopalignment", "stopbuffer", "stopcitaat", "stopcodering", "stopcolumns", "stopcombinatie", "stopcombination", "stopcomment", "stopdescription", "stopdocument", "stopenumeration", "stopfigure", "stopfloattext", "stopformula", "stopframedtext", "stopgeg", "stopglobaal", "stophiding", "stopinteractiemenu", "stopitemgroup", "stopkantlijn", "stopkleur", "stopkolomgroep", "stopkolommen", "stopkolomopmaak", "stoplegend", "stopline", "stoplinecorrection", "stoplinenumbering", "stoplines", "stoplocal", "stoplocalenvironment", "stoplocalfootnotes", "stoplokaal", "stoplokalevoetnoten", "stopmakeup", "stopmargeblok", "stopmarginblock", "stopnaast", "stopnamemakeup", "stopnarrower", "stopomgeving", "stoponderdeel", "stopopelkaar", "stopopmaak", "stopopposite", "stopoverlay", "stopoverview", "stopoverzicht", "stopparagraph", "stoppositioneren", "stoppositioning", "stoppostponing", "stopprodukt", "stopprofiel", "stopprofile", "stopprojekt", "stopraster", "stopregel", "stopregelcorrectie", "stopregelnummeren", "stopregels", "stopsmaller", "stopsymbolset", "stopsynchronisatie", "stopsynchronization", "stoptabel", "stoptabellen", "stoptable", "stoptables", "stoptabulate", "stoptekst", "stoptekstlijn", "stoptyping", "stopuitlijnen", "stopunpacked", "stopvanelkaar", "stopversie", "sub", "subformulenummer", "subject", "subpaginanummer", "subsection", "subsubject", "subsubsection", "subsubsubject", "suggestie", "switchnaarkorps", "switchtorawfont", "sym", "symbool", "synchronisatiebalk", "synchroniseer", "synonym", "taal", "tab", "tekstbreedte", "teksthoogte", "tekstlijn", "tekstreferentie", "tekstvariabele", "testkolom", "testpagina", "tex", "title", "toelichting", "toonexternefiguren", "toongrid", "tooninstellingen", "toonkader", "toonkleur", "toonkleurgroep", "toonkorps", "toonkorpsomgeving", "toonlayout", "toonopmaak", "toonpalet", "toonprint", "toonstruts", "toonsymboolset", "toonvelden", "totaalaantalpaginas", "txt", "typ", "type", "typebuffer", "typefile", "uit", "uitgerekt", "underbar", "underbars", "usecodering", "usedirectory", "vastespatie", "vastespaties", "veld", "veldstapel", "verbergblokken", "vergelijkkleurgroep", "vergelijkpalet", "verhoognummer", "verlaagnummer", "verplaatsformule", "verplaatsopgrid", "verplaatszijblok", "versie", "vertaal", "verwerkblokken", "verwerkpagina", "vl", "voetafstand", "voethoogte", "voetnoot", "voetnoottekst", "volgprofiel", "volgprofielversie", "volgversie", "volledigepaginanummer", "volledigregister", "voluit", "weekdag", "wilijnd", "wiskunde", "witruimte", "woonplaats", "woordrechts", "zetbreedte", "zethoogte" },
+ ["nl"]={ "CAP", "Cap", "Caps", "Cijfers", "KAP", "Kap", "Kaps", "Letter", "Letters", "MAAND", "Romeins", "WEEKDAG", "WOORD", "WOORDEN", "Woord", "Woorden", "aantalsubpaginas", "about", "achtergrond", "appendix", "arg", "bepaalkopnummer", "bepaallijstkenmerken", "bepaalregisterkenmerken", "betekenis", "binnenmargeafstand", "binnenmargebreedte", "binnenrandafstand", "binnenrandbreedte", "blanko", "blokje", "blokjes", "blokkeerinteractiemenu", "bodemwit", "bookmark", "bovenafstand", "bovenhoogte", "breuk", "buitenmargeafstand", "buitenmargebreedte", "buitenrandafstand", "buitenrandbreedte", "but", "button", "cap", "chapter", "chem", "cijfers", "citaat", "citeer", "clip", "comment", "completecombinedlist", "completelistoffloats", "completelistofsorts", "completelistofsynonyms", "converteernummer", "copieerveld", "corrigeerwitruimte", "coupledregister", "crlf", "datum", "definebodyfontDEF", "definebodyfontREF", "definedfont", "definefontfeature", "definefonthandling", "definerawfont", "definetypeface", "definieer", "definieeraccent", "definieeralineas", "definieerbeeldmerk", "definieerblanko", "definieerblok", "definieerbuffer", "definieercombinatie", "definieercommando", "definieerconversie", "definieerfiguursymbool", "definieerfont", "definieerfontstijl", "definieerfontsynoniem", "definieerhbox", "definieerhoofdveld", "definieeringesprongentext", "definieerinmarge", "definieerinteractiemenu", "definieeritemgroep", "definieerkadertekst", "definieerkarakter", "definieerkleur", "definieerkleurgroep", "definieerkolomgroep", "definieerkolomovergang", "definieerkop", "definieerkorps", "definieerkorpsomgeving", "definieerlayer", "definieerlayout", "definieerletter", "definieerlijn", "definieerlijst", "definieermarkering", "definieeromlijnd", "definieeropmaak", "definieeroverlay", "definieerpaginaovergang", "definieerpalet", "definieerpapierformaat", "definieerplaats", "definieerplaatsblok", "definieerprofiel", "definieerprogramma", "definieerreferentie", "definieerreferentieformaat", "definieerreferentielijst", "definieerregister", "definieersamengesteldelijst", "definieersectie", "definieersectieblok", "definieersorteren", "definieerstartstop", "definieersubveld", "definieersymbool", "definieersynoniemen", "definieertabelvorm", "definieertabulatie", "definieertekst", "definieertekstpositie", "definieertekstvariabele", "definieertype", "definieertypen", "definieeruitvoer", "definieerveld", "definieerveldstapel", "definieerversie", "definieerwiskundeuitlijnen", "description", "dimensie", "directnaarlijst", "directtussenlijst", "doordefinieren", "doorlabelen", "doornummeren", "dunnelijn", "dunnelijnen", "eenregel", "enumeration", "ergens", "externfiguur", "forceerblokken", "formulenummer", "framedtext", "gebruikJSscripts", "gebruikURL", "gebruikXMLfilter", "gebruikblokken", "gebruikcommandos", "gebruikexterndocument", "gebruikexternefile", "gebruikexternefiles", "gebruikexternfiguur", "gebruikexterngeluidsfragment", "gebruikgebied", "gebruikmodule", "gebruikmodules", "gebruikreferenties", "gebruikspecials", "gebruiksymbolen", "gebruiktypescript", "gebruiktypescriptfile", "gebruikurl", "geenblokkenmeer", "geenbovenenonderregels", "geendimensie", "geenfilesmeer", "geenhoofdenvoetregels", "geenlijst", "geenmarkering", "geenspatie", "geentest", "geenwitruimte", "geg", "grijskleur", "grijswaarde", "haalbuffer", "haalmarkering", "haalnummer", "haarlijn", "handhaafblokken", "herhaal", "hl", "hoofdafstand", "hoofdhoogte", "hoofdtaal", "hoog", "huidigedatum", "huidigekopnummer", "in", "inanderemarge", "inbinnen", "inbuiten", "indentation", "inlijnd", "inlinker", "inlinkermarge", "inlinkerrand", "inmarge", "inrechter", "inrechtermarge", "inrechterrand", "inregel", "inspringen", "installeertaal", "instellingen", "interactiebalk", "interactiebuttons", "interactiemenu", "invullijnen", "invulregel", "invultekst", "invulveld", "inwilijnd", "items", "its", "kantlijn", "kap", "kenmerk", "kenmerkdatum", "kentekstvariabeletoe", "kleur", "kleurenbalk", "kleurwaarde", "kloonveld", "kolom", "kop", "kopniveau", "kopnummer", "koppeldocument", "koppelmarkering", "koppelpagina", "koppelpapier", "koppelregister", "kopsym", "koptekst", "kopwit", "laag", "label", "labeling", "labels", "labeltekst", "laho", "leg", "legeregels", "letter", "letters", "lijndikte", "lijstbreedte", "lijsthoogte", "lijstlengte", "lijstsymbool", "linkermargeafstand", "linkermargebreedte", "linkerrandafstand", "linkerrandbreedte", "loadsorts", "loadsynonyms", "maand", "mapfontsize", "mar", "margeafstand", "margebreedte", "margetekst", "margetitel", "margewoord", "markeer", "markeerversie", "mediaeval", "menubutton", "naam", "naar", "naarbox", "naarpagina", "name", "navigerend", "nextsection", "nietinspringen", "nocap", "nokap", "noot", "nop", "omgeving", "omlaag", "omlijnd", "onbekend", "onderafstand", "onderdeel", "onderhoogte", "ontkoppelmarkering", "op", "opelkaar", "oplinkermarge", "oppagina", "oprechtermarge", "overbar", "overbars", "overstrike", "overstrikes", "pagina", "paginadiepte", "paginanummer", "paginaoffset", "paginareferentie", "papierbreedte", "papierhoogte", "paragraph", "part", "paslayoutaan", "passeerblokken", "passendveld", "plaatsbeeldmerken", "plaatsbookmarks", "plaatsformule", "plaatskopnummer", "plaatskoptekst", "plaatslegenda", "plaatslijn", "plaatslijst", "plaatslokalevoetnoten", "plaatsnaastelkaar", "plaatsonderelkaar", "plaatsopgrid", "plaatspaginanummer", "plaatsplaatsblok", "plaatsreferentielijst", "plaatsregister", "plaatsruwelijst", "plaatssamengesteldelijst", "plaatssubformule", "plaatstekstvariabele", "plaatsvoetnoten", "placelistoffloats", "placelistofsorts", "placelistofsynonyms", "positioneer", "positioneertekst", "printpapierbreedte", "printpapierhoogte", "produkt", "programma", "projekt", "publicatie", "punten", "ran", "randafstand", "randbreedte", "rechtermargeafstand", "rechtermargebreedte", "rechterrandafstand", "rechterrandbreedte", "ref", "refereer", "referentie", "regellinks", "regelmidden", "regelrechts", "register", "registreervelden", "reservefloat", "reset", "resetmarkering", "resetnummer", "resettekstinhoud", "resettextcontent", "romeins", "rooster", "roteer", "rugwit", "schaal", "scherm", "schrijfnaarlijst", "schrijfnaarreferentielijst", "schrijfnaarregister", "schrijftussenlijst", "section", "seeregister", "selecteerblokken", "selecteerpapier", "selecteerversie", "setnummer", "setupfonthandling", "setupfontsynonym", "setupinterlinespace2", "setuplistalternative", "snijwit", "som", "sort", "spatie", "spiegel", "splitsplaatsblok", "startachtergrond", "startalignment", "startbuffer", "startcitaat", "startcodering", "startcolumns", "startcombinatie", "startcombination", "startcomment", "startdescription", "startdocument", "startenumeration", "startfigure", "startfiguur", "startfloattext", "startformula", "startframedtext", "startgeg", "startglobaal", "starthiding", "startinteractiemenu", "startitemgroup", "startkantlijn", "startkleur", "startkolomgroep", "startkolommen", "startkolomopmaak", "startlegend", "startline", "startlinecorrection", "startlinenumbering", "startlines", "startlocal", "startlocalenvironment", "startlocalfootnotes", "startlokaal", "startlokalevoetnoten", "startmakeup", "startmargeblok", "startmarginblock", "startnaast", "startnamemakeup", "startnarrower", "startomgeving", "startonderdeel", "startopelkaar", "startopmaak", "startopposite", "startoverlay", "startoverview", "startoverzicht", "startparagraph", "startpositioneren", "startpositioning", "startpostponing", "startprodukt", "startprofiel", "startprofile", "startprojekt", "startraster", "startregel", "startregelcorrectie", "startregelnummeren", "startregels", "startregister", "startsmaller", "startsymbolset", "startsymboolset", "startsynchronisatie", "startsynchronization", "starttabel", "starttabellen", "starttable", "starttables", "starttabulate", "starttekst", "starttekstlijn", "starttyping", "startuitlijnen", "startunpacked", "startvanelkaar", "startversie", "stelachtergrondenin", "stelachtergrondin", "stelalineasin", "stelantwoordgebiedin", "stelarrangerenin", "stelblankoin", "stelblokin", "stelblokjesin", "stelblokkopjein", "stelblokkopjesin", "stelbovenin", "stelboventekstenin", "stelbufferin", "stelbuttonsin", "stelciterenin", "stelclipin", "stelcombinatiesin", "stelcommentaarin", "steldoordefinierenin", "steldoornummerenin", "steldunnelijnenin", "stelexternefigurenin", "stelformulesin", "stelformulierenin", "stelhoofdin", "stelhoofdtekstenin", "stelingesprongentextin", "stelinmargein", "stelinspringenin", "stelinteractiebalkin", "stelinteractiein", "stelinteractiemenuin", "stelinteractieschermin", "stelinterliniein", "stelinvullijnenin", "stelinvulregelsin", "stelitemgroepin", "stelitemsin", "stelkadertekstenin", "stelkantlijnin", "stelkapitalenin", "stelkleurenin", "stelkleurin", "stelkolomgroepin", "stelkolomgroepregelsin", "stelkolomgroepstartin", "stelkolommenin", "stelkopin", "stelkopnummerin", "stelkoppeltekenin", "stelkoppenin", "stelkoptekstin", "stelkorpsin", "stelkorpsomgevingin", "stellabeltekstin", "stellayoutin", "stellegendain", "stellijndiktein", "stellijnin", "stellijstin", "stelmargeblokkenin", "stelmarkeringin", "stelnaastplaatsenin", "stelnummerenin", "stelnummerin", "stelomlijndin", "stelonderin", "stelonderstrepenin", "stelondertekstenin", "stelopmaakin", "stelopsommingenin", "stelpaginacommentaarin", "stelpaginanummerin", "stelpaginanummeringin", "stelpaginaovergangenin", "stelpaletin", "stelpapierformaatin", "stelpapierin", "stelparagraafnummerenin", "stelplaatsblokin", "stelplaatsblokkenin", "stelplaatsbloksplitsenin", "stelplaatsin", "stelpositionerenin", "stelprofielenin", "stelprogrammasin", "stelpublicatiesin", "stelrastersin", "stelreferentielijstin", "stelrefererenin", "stelregelnummerenin", "stelregelsin", "stelregisterin", "stelroterenin", "stelsamengesteldelijstin", "stelsectieblokin", "stelsectiein", "stelsmallerin", "stelsorterenin", "stelspatieringin", "stelstartstopin", "stelstrutin", "stelsubpaginanummerin", "stelsymboolsetin", "stelsynchronisatiebalkin", "stelsynchronisatiein", "stelsynoniemenin", "stelsysteemin", "steltaalin", "steltabellenin", "steltabin", "steltabulatiein", "steltekstin", "steltekstinhoudin", "steltekstlijnenin", "steltekstpositiein", "stelteksttekstenin", "steltekstvariabelein", "steltolerantiein", "steltypein", "steltypenin", "steluitlijnenin", "steluitvoerin", "stelurlin", "stelveldenin", "stelveldin", "stelversiesin", "stelvoetin", "stelvoetnootdefinitiein", "stelvoetnotenin", "stelvoettekstenin", "stelwiskundeuitlijnenin", "stelwitruimtein", "stopachtergrond", "stopalignment", "stopbuffer", "stopcitaat", "stopcodering", "stopcolumns", "stopcombinatie", "stopcombination", "stopcomment", "stopdescription", "stopdocument", "stopenumeration", "stopfigure", "stopfloattext", "stopformula", "stopframedtext", "stopgeg", "stopglobaal", "stophiding", "stopinteractiemenu", "stopitemgroup", "stopkantlijn", "stopkleur", "stopkolomgroep", "stopkolommen", "stopkolomopmaak", "stoplegend", "stopline", "stoplinecorrection", "stoplinenumbering", "stoplines", "stoplocal", "stoplocalenvironment", "stoplocalfootnotes", "stoplokaal", "stoplokalevoetnoten", "stopmakeup", "stopmargeblok", "stopmarginblock", "stopnaast", "stopnamemakeup", "stopnarrower", "stopomgeving", "stoponderdeel", "stopopelkaar", "stopopmaak", "stopopposite", "stopoverlay", "stopoverview", "stopoverzicht", "stopparagraph", "stoppositioneren", "stoppositioning", "stoppostponing", "stopprodukt", "stopprofiel", "stopprofile", "stopprojekt", "stopraster", "stopregel", "stopregelcorrectie", "stopregelnummeren", "stopregels", "stopsmaller", "stopsymbolset", "stopsynchronisatie", "stopsynchronization", "stoptabel", "stoptabellen", "stoptable", "stoptables", "stoptabulate", "stoptekst", "stoptekstlijn", "stoptyping", "stopuitlijnen", "stopunpacked", "stopvanelkaar", "stopversie", "sub", "subformulenummer", "subject", "subpaginanummer", "subsection", "subsubject", "subsubsection", "subsubsubject", "suggestie", "switchnaarkorps", "switchtorawfont", "sym", "symbool", "symoffset", "synchronisatiebalk", "synchroniseer", "synonym", "taal", "tab", "tekstbreedte", "teksthoogte", "tekstlijn", "tekstreferentie", "tekstvariabele", "testkolom", "testpagina", "tex", "title", "toelichting", "toonexternefiguren", "toongrid", "tooninstellingen", "toonkader", "toonkleur", "toonkleurgroep", "toonkorps", "toonkorpsomgeving", "toonlayout", "toonopmaak", "toonpalet", "toonprint", "toonstruts", "toonsymboolset", "toonvelden", "totaalaantalpaginas", "txt", "typ", "type", "typebuffer", "typefile", "uit", "uitgerekt", "underbar", "underbars", "usecodering", "usedirectory", "vastespatie", "vastespaties", "veld", "veldstapel", "verbergblokken", "vergelijkkleurgroep", "vergelijkpalet", "verhoognummer", "verlaagnummer", "verplaatsformule", "verplaatsopgrid", "verplaatszijblok", "versie", "vertaal", "verwerkblokken", "verwerkpagina", "vl", "voetafstand", "voethoogte", "voetnoot", "voetnoottekst", "volgprofiel", "volgprofielversie", "volgversie", "volledigepaginanummer", "volledigregister", "voluit", "weekdag", "wilijnd", "wiskunde", "witruimte", "woonplaats", "woordrechts", "zetbreedte", "zethoogte" },
["pe"]={ "CAP", "Cap", "Caps", "Character", "Characters", "MONTH", "Numbers", "Romannumerals", "WEEKDAY", "WORD", "WORDS", "Word", "Words", "appendix", "cap", "chapter", "chem", "comment", "completecombinedlist", "completelistoffloats", "completelistofsorts", "completelistofsynonyms", "coupledregister", "crlf", "definebodyfontDEF", "definebodyfontREF", "definedfont", "definefontfeature", "definefonthandling", "defineindentedtext", "definetypeface", "description", "enumeration", "framedtext", "indentation", "inmframed", "its", "labeling", "loadsorts", "loadsynonyms", "mapfontsize", "mediaeval", "mframed", "name", "nextsection", "nocap", "overbar", "overbars", "overstrike", "overstrikes", "paragraph", "part", "placelistoffloats", "placelistofsorts", "placelistofsynonyms", "ran", "register", "reservefloat", "resettextcontent", "section", "seeregister", "setupanswerarea", "setupcapitals", "setupfonthandling", "setupfontsynonym", "setupindentedtext", "setupinterlinespace2", "setuplistalternative", "setupurl", "sort", "startalignment", "startbuffer", "startcolumns", "startcombination", "startcomment", "startdescription", "startdocument", "startenumeration", "startfigure", "startfloattext", "startformula", "startframedtext", "starthiding", "startitemgroup", "startlegend", "startline", "startlinecorrection", "startlinenumbering", "startlines", "startlocal", "startlocalenvironment", "startlocalfootnotes", "startmakeup", "startmarginblock", "startnamemakeup", "startnarrower", "startopposite", "startoverlay", "startoverview", "startparagraph", "startpositioning", "startpostponing", "startprofile", "startraster", "startregister", "startsymbolset", "startsynchronization", "starttable", "starttables", "starttabulate", "starttyping", "startunpacked", "startتولید", "startحقیقت", "startخطحاشیه", "startخطمتن", "startرنگ", "startفشرده", "startمحیط", "startمنویپانل", "startمولفه", "startنسخه", "startنقلقول", "startپروژه", "startپسزمینه", "stopalignment", "stopbuffer", "stopcolumns", "stopcombination", "stopcomment", "stopdescription", "stopdocument", "stopenumeration", "stopfigure", "stopfloattext", "stopformula", "stopframedtext", "stophiding", "stopitemgroup", "stoplegend", "stopline", "stoplinecorrection", "stoplinenumbering", "stoplines", "stoplocal", "stoplocalenvironment", "stoplocalfootnotes", "stopmakeup", "stopmarginblock", "stopnamemakeup", "stopnarrower", "stopopposite", "stopoverlay", "stopoverview", "stopparagraph", "stoppositioning", "stoppostponing", "stopprofile", "stopraster", "stopsymbolset", "stopsynchronization", "stoptable", "stoptables", "stoptabulate", "stoptyping", "stopunpacked", "stopتولید", "stopحقیقت", "stopخطحاشیه", "stopخطمتن", "stopرنگ", "stopفشرده", "stopمحیط", "stopمنویپانل", "stopمولفه", "stopنسخه", "stopنقلقول", "stopپروژه", "stopپسزمینه", "sub", "subject", "subsection", "subsubject", "subsubsection", "subsubsubject", "synonym", "title", "tooltip", "txt", "typ", "underbar", "underbars", "useJSscripts", "useURL", "useXMLfilter", "usedirectory", "useurl", "آفستصفحه", "آیتم", "آیتمها", "آینه", "اجباربلوکها", "ارتفاعآرایش", "ارتفاعبالا", "ارتفاعبرگ", "ارتفاعتهبرگ", "ارتفاعخط", "ارتفاعسربرگ", "ارتفاعمتن", "ارتفاعپایین", "از", "ازکارانداختنمنویپانل", "استفادهبلوکها", "استفادهدستخطتایپ", "استفادهرمزینه", "استفادهشکلخارجی", "استفادهفرمانها", "استفادهقطعهموزیکخارجی", "استفادهمدول", "استفادهمدولها", "استفادهمرجعها", "استفادهمسیر", "استفادهنمادها", "استفادهنوشتارخارجی", "استفادهویژگیها", "استفادهپروندهخارجی", "استفادهپروندهدستخطتایپ", "استفادهپروندههایخارجی", "اعدادلاتین", "افزودن", "اما", "امتحاننکن", "انتخاببرگ", "انتخاببلوکها", "انتخابنسخه", "انتقالبهتوری", "انتقالفرمول", "انتقالکنارشناور", "انجامدوباره", "بارگذاریها", "بارگذاریآرایش", "بارگذاریآیتمها", "بارگذاریارجاع", "بارگذاریاندازهبرگ", "بارگذاریباریکتر", "بارگذاریبافر", "بارگذاریبالا", "بارگذاریبخش", "بارگذاریبردباری", "بارگذاریبرنامهها", "بارگذاریبرگ", "بارگذاریبست", "بارگذاریبلوک", "بارگذاریبلوکهایحاشیه", "بارگذاریبلوکبخش", "بارگذاریتایپ", "بارگذاریتایپکردن", "بارگذاریتب", "بارگذاریترتیب", "بارگذاریترکیبها", "بارگذاریتطابق", "بارگذاریتعریفپانوشت", "بارگذاریتنظیم", "بارگذاریتنظیمریاضی", "بارگذاریتهبرگ", "بارگذاریتورفتگی", "بارگذاریتوضیح", "بارگذاریتوضیحصفحه", "بارگذاریثبت", "بارگذاریجانشانی", "بارگذاریجدولها", "بارگذاریجدولبندی", "بارگذاریخالی", "بارگذاریخروجی", "بارگذاریخط", "بارگذاریخطها", "بارگذاریخطهایحاشیه", "بارگذاریخطهایسیاه", "بارگذاریخطهایمتن", "بارگذاریخطهایمجموعهستون", "بارگذاریخطهاینازک", "بارگذاریدرجدرخطها", "بارگذاریدرجمخالف", "بارگذاریدرونحاشیه", "بارگذاریدوران", "بارگذاریدکمهها", "بارگذاریراهنما", "بارگذاریرنگ", "بارگذاریرنگها", "بارگذاریزبان", "بارگذاریستونها", "بارگذاریسر", "بارگذاریسربرگ", "بارگذاریسرها", "بارگذاریسیستم", "بارگذاریشرح", "بارگذاریشرحها", "بارگذاریشروعمجموعهستون", "بارگذاریشروعپایان", "بارگذاریشماره", "بارگذاریشمارهزیرصفحه", "بارگذاریشمارهسر", "بارگذاریشمارهصفحه", "بارگذاریشمارهگذاری", "بارگذاریشمارهگذاریها", "بارگذاریشمارهگذاریصفحه", "بارگذاریشمارهگذاریپاراگراف", "بارگذاریشمارهگذاریخط", "بارگذاریشناور", "بارگذاریشناورها", "بارگذاریشکافتنشناورها", "بارگذاریشکلهایخارجی", "بارگذاریطرح", "بارگذاریطرحبندی", "بارگذاریعرضخط", "بارگذاریفاصلهبینخط", "بارگذاریفرمولها", "بارگذاریفضایسفید", "بارگذاریفضاگذاری", "بارگذاریقالبی", "بارگذاریقلممتن", "بارگذاریلوح", "بارگذاریلیست", "بارگذاریلیستترکیبی", "بارگذاریلیستمرجع", "بارگذاریمترادفها", "بارگذاریمتغیرمتن", "بارگذاریمتن", "بارگذاریمتنهایبالا", "بارگذاریمتنسر", "بارگذاریمتنسربرگ", "بارگذاریمتنقالبی", "بارگذاریمتنمتنها", "بارگذاریمتنپانوشت", "بارگذاریمتنپایین", "بارگذاریمجموعهستون", "بارگذاریمجموعهنماد", "بارگذاریمحیطقلممتن", "بارگذاریمنویپانل", "بارگذاریمکانمتن", "بارگذاریمکانگذاری", "بارگذاریمیدان", "بارگذاریمیدانها", "بارگذاریمیلهتطابق", "بارگذاریمیلهزیر", "بارگذاریمیلهپانل", "بارگذارینسخهها", "بارگذارینشانهشکستن", "بارگذارینشانهگذاری", "بارگذارینشرها", "بارگذارینقل", "بارگذاریپاراگرافها", "بارگذاریپانل", "بارگذاریپانوشتها", "بارگذاریپایین", "بارگذاریپردهها", "بارگذاریپردهپانل", "بارگذاریپروفایلها", "بارگذاریپرکردنخطها", "بارگذاریپسزمینه", "بارگذاریپسزمینهها", "بارگذاریچیدن", "بارگذاریگذارصفحه", "بارگذاریگروههایآیتم", "بارگذاریگروهآیتم", "بازنشانی", "بازنشانیشماره", "بازنشانیمتن", "بازنشانینشانهگذاری", "باگذاریمتنبرچسب", "بدونبعد", "بدونبلوکهایبیشتر", "بدونتورفتگی", "بدونخطبالاوپایین", "بدونخطسروتهبرگ", "بدونفایلهایبیشتر", "بدونفضا", "بدونفضایسفید", "بدونلیست", "بدوننشانهگذاری", "برنامه", "بروبه", "بروبهجعبه", "بروبهصفحه", "بروپایین", "برچسب", "برچسبها", "بعد", "بلند", "بلوکهایپردازش", "بلوکهاپنهان", "بنویسبینلیست", "بنویسدرثبت", "بنویسدرلیستمرجع", "بنویسدرلیست", "تاریخ", "تاریخجاری", "تاریخرجوع", "تایپ", "تایپبافر", "تایپپرونده", "تب", "ترجمه", "تطابق", "تعریف", "تعریفآرایش", "تعریفآرم", "تعریفالگویجدول", "تعریفاندازهبرگ", "تعریفبافر", "تعریفبخش", "تعریفبرنامه", "تعریفبرچسب", "تعریفبلوک", "تعریفبلوکبخش", "تعریفتایپ", "تعریفتایپکردن", "تعریفتبدیل", "تعریفترتیب", "تعریفترکیب", "تعریفتنظیمریاضی", "تعریفتودهمیدان", "تعریفثبت", "تعریفجانشانی", "تعریفجدولبندی", "تعریفجعبهافقی", "تعریفحرف", "تعریفخالی", "تعریفخروجی", "تعریفخطحائل", "تعریفدرونحاشیه", "تعریفرنگ", "تعریفزیرمیدان", "تعریفسبک", "تعریفسبکقلم", "تعریفسر", "تعریفشرح", "تعریفشروعپایان", "تعریفشمارهبندی", "تعریفشمایلمرجع", "تعریفشناور", "تعریفشکستنستون", "تعریفشکستصفحه", "تعریفطرحبندی", "تعریففرمان", "تعریفقالبی", "تعریفقلم", "تعریفقلمخام", "تعریفقلممتن", "تعریفلایه", "تعریفلهجه", "تعریفلوح", "تعریفلیست", "تعریفلیستترکیبی", "تعریفلیستمرجع", "تعریفمترادفها", "تعریفمترادفقلم", "تعریفمتغیرمتن", "تعریفمتن", "تعریفمتنقالبی", "تعریفمجموعهستون", "تعریفمحیطقلمبدنه", "تعریفمرجع", "تعریفمنویپانل", "تعریفمکانمتن", "تعریفمیدان", "تعریفمیداناصلی", "تعریفنسخه", "تعریفنشانهگذاری", "تعریفنماد", "تعریفنمادشکل", "تعریفپاراگرافها", "تعریفپروفایل", "تعریفپوشش", "تعریفگروهآیتم", "تعریفگروهرنگ", "تعیینشماره", "تعیینشمارهسر", "تعیینمتغیرمتن", "تعیینمحتوایمتن", "تعیینمشخصاتثبت", "تعیینمشخصاتلیست", "تغییربهقلمبدنه", "تغییربهقلمخام", "تنظیمراست", "تنظیمطرحبندی", "تنظیموسط", "توجه", "تورفتگی", "توری", "تولید", "تک", "ثبتزوج", "ثبتکامل", "جداسازینشانهگذاری", "حاش", "حرف", "حرفها", "حفظبلوکها", "حقیقت", "خالی", "خطهایسیاه", "خطهاینازک", "خطهاخالی", "خطحاشیه", "خطسیاه", "خطمتن", "خطمو", "خطنازک", "خا", "خع", "در", "درجآرمها", "درجثبت", "درجخط", "درجدرخط", "درجدرخطها", "درجدرمتن", "درجدرمیدان", "درجدربالاییکدیگر", "درجدرتوری", "درجراهنما", "درجزیرفرمول", "درجشمارهسر", "درجشمارهصفحه", "درجشناور", "درجفرمول", "درجلیست", "درجلیستخام", "درجلیستمختلط", "درجلیستمرجع", "درجمتغیرمتن", "درجمتنسر", "درجپانوشتها", "درجپانوشتهایموضعی", "درجچوبخط", "درجکناربهکنار", "درحاشیه", "درحاشیهدیگر", "درحاشیهراست", "درحاشیهچپ", "درخارجی", "درخط", "درداخلی", "درراست", "درصفحه", "درقالبی", "درلبهراست", "درلبهچپ", "درمورد", "درون", "درپر", "درچپ", "دریافتبافر", "دریافتشماره", "دریافتنشانه", "دوران", "دکمه", "دکمهمنو", "دکمهپانل", "رج", "رجوع", "رنگ", "رنگخاکستری", "روزهفته", "ریاضی", "زبان", "زباناصلی", "ستون", "ستونامتحان", "سر", "سرپوشکوچکنه", "شروعآرایش", "شروعآرایشستون", "شروعباریکتر", "شروعبازبینی", "شروعبلوکحاشیه", "شروعترکیب", "شروعتصحیحخط", "شروعتطابق", "شروعتنظیم", "شروعتولید", "شروعجدول", "شروعجدولها", "شروعخط", "شروعخطها", "شروعخطحاشیه", "شروعخطمتن", "شروعرنگ", "شروعستونها", "شروعسراسری", "شروعشمارهگذاریخط", "شروعشکل", "شروعغیرفشرده", "شروعفشرده", "شروعمتن", "شروعمجموعهستون", "شروعمجموعهنماد", "شروعمحیط", "شروعمخالف", "شروعموضعی", "شروعمولفه", "شروعمکانگذاری", "شروعنسخه", "شروعنقلقول", "شروعنوشتار", "شروعپانوشتهایموضعی", "شروعپروفایل", "شروعپروژه", "شروعپسزمینه", "شروعپوشش", "شروعکد", "شمارهافزایش", "شمارهزیرصفحه", "شمارهزیرفرمول", "شمارهسر", "شمارهسرجاری", "شمارهصفحه", "شمارهصفحهکامل", "شمارهفرمول", "شمارهمبدل", "شمارهها", "شمارهکاهش", "شمارهکلصفحهها", "شکافتنشناور", "شکلخارجی", "صفحه", "صفحهتست", "صفحهزوج", "صفحهپردازش", "طوللیست", "عبوربلوکها", "عرضآرایش", "عرضبرگ", "عرضحاشیه", "عرضحاشیهخارجی", "عرضحاشیهداخلی", "عرضحاشیهراست", "عرضحاشیهچپ", "عرضخط", "عرضلبه", "عرضلبهخارجی", "عرضلبهداخلی", "عرضلبهراست", "عرضلبهچپ", "عرضلیست", "عرضمتن", "عمقصفحه", "عنوانحاشیه", "فاصلهبالا", "فاصلهتهبرگ", "فاصلهحاشیه", "فاصلهحاشیهخارجی", "فاصلهحاشیهداخلی", "فاصلهحاشیهراست", "فاصلهحاشیهچپ", "فاصلهسربرگ", "فاصلهلبه", "فاصلهلبهخارجی", "فاصلهلبهداخلی", "فاصلهلبهراست", "فاصلهلبهچپ", "فاصلهپایین", "فاصلهپشت", "فشرده", "فضا", "فضاهایثابت", "فضایبالا", "فضایبرش", "فضایثابت", "فضایسفید", "فضایسفیدصحیح", "فضایپایین", "فوریبهلیست", "فوریبینلیست", "قالبی", "لوحمقایسه", "ماه", "متغیر متن", "متنبرچسب", "متنحاشیه", "متنسر", "متنپانوشت", "محیط", "مراجعه", "مرجع", "مرجعصفحه", "مرجعمتن", "مرحلهسر", "مسکن", "معنیواحد", "مقایسهگروهرنگ", "مقدارخاکستری", "مقداررنگ", "مقیاس", "منفی", "منویپانل", "مولفه", "مکان", "مکانمتن", "میدان", "میدانهایگزارش", "میدانشبیهسازی", "میدانپشته", "میدانکپی", "میلهتطابق", "میلهرنگ", "میلهپانل", "ناشناس", "نامماکرو", "نسخه", "نسخهنشانه", "نشانهگذاری", "نشانهگذاریزوج", "نشر", "نصبزبان", "نقطهها", "نقل", "نقلقول", "نم", "نماد", "نمادسر", "نمادلیست", "نمایشآرایش", "نمایشبارگذاریها", "نمایشبستها", "نمایشتوری", "نمایشرنگ", "نمایششکلهایخارجی", "نمایشطرحبندی", "نمایشقالب", "نمایشقلمبدنه", "نمایشلوح", "نمایشمجموعهعلامت", "نمایشمحیطقلمبدنه", "نمایشمیدانها", "نمایشچاپ", "نمایشگروهرنگ", "نوشتارزوج", "هدایت", "پا", "پابا", "پانوشت", "پایانآرایش", "پایانآرایشستون", "پایانبازبینی", "پایانبلوکحاشیه", "پایانترکیب", "پایانتصحیحخط", "پایانتطابق", "پایانتنظیم", "پایانتولید", "پایانجدول", "پایانجدولها", "پایانخط", "پایانخطها", "پایانخطحاشیه", "پایانخطمتن", "پایانرنگ", "پایانستونها", "پایانسراسری", "پایانشمارهگذاریخط", "پایانغیرفشرده", "پایانفشرده", "پایانمتن", "پایانمجموعهستون", "پایانمحیط", "پایانمخالف", "پایانموضعی", "پایانمولفه", "پایانمکانگذاری", "پایاننازکتر", "پایاننسخه", "پایاننقلقول", "پایاننوشتار", "پایانپانوشتهایموضعی", "پایانپروفایل", "پایانپروژه", "پایانپسزمینه", "پایانپوشش", "پایانکد", "پایین", "پرده", "پروژه", "پرکردنمیدان", "پسزمینه", "پیروینسخه", "پیروینسخهپروفایل", "پیرویپروفایل", "چاپارتفاعبرگ", "چاپعرضبرگ", "چوبخط", "چپچین", "کاغذزوج", "کسر", "کشیده", "کلمهحاشیه", "کلمهراست", "گیره", "یادداشت", "یکجا", "یکخط" },
["ro"]={ "CAP", "CUVANT", "CUVINTE", "Cap", "Caps", "Cuvant", "Cuvinte", "KAP", "Kap", "Kaps", "LUNA", "Litera", "Litere", "Numere", "Numereromane", "ZIDINSAPTAMANA", "adapteazaaspect", "adubuffer", "adumarcaje", "afiseazaaspect", "afiseazacampuri", "afiseazaculoare", "afiseazafiguriexterne", "afiseazafonttext", "afiseazagrid", "afiseazagrupculoare", "afiseazamakeup", "afiseazamediufonttext", "afiseazapaleta", "afiseazarama", "afiseazasetari", "afiseazasetsimboluri", "afiseazastruts", "afiseazatiparire", "aliniat", "aliniatcentru", "aliniatdreapta", "aliniatstanga", "appendix", "arg", "ascundeblocuri", "atleftmargin", "atrightmargin", "baraculoare", "barainteractiune", "barasincronizare", "blanc", "but", "butoaneinteractiune", "buton", "butonmeniu", "camp", "campumplere", "cap", "chapter", "chem", "citat", "clip", "cloneazacamp", "coloana", "comment", "comparagrupculoare", "comparapaleta", "completeazanumarpagina", "completecombinedlist", "completelistoffloats", "completelistofsorts", "completelistofsynonyms", "completeregister", "componenta", "convertestenumar", "copiazacamp", "corecteazaspatiualb", "coupledregister", "crlf", "culoare", "culoaregri", "cupleazadocument", "cupleazamarcaje", "cupleazaregistru", "cutspace", "cuvantdreapta", "cuvantmarginal", "data", "datacurenta", "datareferit", "decrementnumber", "decupleazamarcaje", "definebodyfontDEF", "definebodyfontREF", "definecolumnbreak", "definecolumnset", "definecombination", "definedfont", "definefontfeature", "definefonthandling", "defineindentedtext", "defineinmargin", "defineitemgroup", "definelayer", "definelayout", "definemathalignment", "definepagebreak", "defineplacement", "defineste", "definesteaccent", "definesteantet", "definesteblanc", "definestebloc", "definesteblocsectiune", "definestebuffer", "definestecamp", "definestecampprincipal", "definestecaracter", "definestecomanda", "definesteconversie", "definesteculoare", "definestedescriere", "definestedimensiunehartie", "definesteenumerare", "definesteeticheta", "definestefloat", "definestefont", "definestefontraw", "definestefonttext", "definesteformatreferinte", "definestegrupculori", "definestehbox", "definesteinconjurare", "definestelista", "definestelistacombinata", "definestelistareferinte", "definestelogo", "definestemakeup", "definestemarcaje", "definestemediulfonttext", "definestemeniuinteractiune", "definesteoutput", "definesteoverlay", "definestepaleta", "definesteparagraf", "definestepozitietext", "definesteprofil", "definesteprogram", "definestereferinte", "definesteregistru", "definesterigla", "definestesablontabel", "definestesectiune", "definestesimbol", "definestesimbolfigura", "definestesinonim", "definestesinonimfont", "definestesortare", "definestestartstop", "definestestil", "definestestilfont", "definestestivacampuri", "definestesubcamp", "definestetabulatori", "definestetext", "definestetexteinconjurate", "definestetextinconjurat", "definestetyping", "definestevariabilatext", "definesteversiune", "definetype", "definetypeface", "description", "despre", "determinacaracteristicilelistei", "determinacaracteristiciregistru", "determinanumartitlu", "dezactiveazameniuinteractiune", "dimensiune", "din", "distantaantet", "distantacolt", "distantacoltdreapta", "distantacoltstanga", "distantajos", "distantamargine", "distantamarginedreapta", "distantamarginestanga", "distantasubsol", "distantasus", "domiciliu", "dute", "dutebox", "dutepagina", "ecran", "el", "element", "emptylines", "enumeration", "eticheta", "etichete", "fact", "faraaliniat", "faradimensiune", "farafisiere", "faraliniiantetsisubsol", "faraliniisussijos", "faralista", "faramarcaje", "faraspatiu", "faraspatiualb", "figuraexterna", "firdepar", "folosesteURL", "folosestebloc", "folosestecodificarea", "folosestecomenzi", "folosestedirector", "folosestedocumentextern", "folosestefiguraexterna", "folosestefisiereexterne", "folosestefisierextern", "folosestemodul", "folosestemodule", "folosestemuzicaexterna", "folosestereferinte", "folosestescriptJS", "folosestesimboluri", "folosestespeciale", "folosesteurl", "footnotetext", "forteazablocuri", "fractie", "framed", "framedtext", "fundal", "gatablocuri", "getnumber", "grid", "grosimelinie", "hartiedubla", "headsym", "hl", "immediatebetweenlist", "immediatetolist", "impachetat", "impartefloat", "in", "inalt", "inaltamargine", "inaltimeantet", "inaltimehartie", "inaltimehartieimprimanta", "inaltimejos", "inaltimelista", "inaltimemakeup", "inaltimesubsol", "inaltimesus", "inaltimetext", "indentation", "indreapta", "inframed", "ininner", "injos", "inlinie", "inmaframed", "inmargineadreapta", "inmargineastanga", "inneredgedistance", "inneredgewidth", "innermargindistance", "innermarginwidth", "inouter", "inparteadreapta", "inparteastanga", "instalarelimba", "instanga", "intins", "jos", "jossus", "kap", "la", "labeling", "lapagina", "latimecoltdreapta", "latimecoltstanga", "latimecolturi", "latimehartie", "latimehartieimprimanta", "latimelista", "latimemakeup", "latimemargine", "latimemarginedreapta", "latimemarginestanga", "latimetext", "leg", "limba", "limbaprincipala", "liniemargine", "linieneagra", "liniesubtire", "linieumplere", "liniinegre", "liniisubtiri", "listsymbol", "litera", "litere", "loadsorts", "loadsynonyms", "logcampuri", "luna", "lungimelista", "maframed", "mapfontsize", "mar", "marcaje", "marcheazaversiune", "marginal", "matematica", "mediaeval", "mediu", "meniuinteractiune", "minicitat", "moveformula", "movesidefloat", "mutapegrid", "name", "navigating", "necunoscut", "nextsection", "niveltitlu", "nocap", "nokap", "nop", "nota", "notasubsol", "numarformula", "numarincrement", "numarpagina", "numarsubformula", "numartitlu", "numartitlucurent", "numartotalpagini", "numberofsubpages", "nume", "numere", "numereromane", "numeunitate", "nutesta", "olinie", "outeredgedistance", "outeredgewidth", "outermargindistance", "outermarginwidth", "overbar", "overbars", "overstrike", "overstrikes", "pagedepth", "pageoffset", "pagina", "paginadubla", "paragraph", "part", "pastreazablocuri", "pelung", "placefloat", "placeheadnumber", "placeheadtext", "placelistoffloats", "placelistofsorts", "placelistofsynonyms", "placerawlist", "placereferencelist", "plaseazapegrid", "plaseazasemnecarte", "potrivestecamp", "pozitie", "pozitietext", "proceseazabloc", "proceseazapagina", "produs", "program", "proiect", "publicatie", "puncte", "punedeasuprafiecareia", "punefatainfata", "puneformula", "punelegenda", "punelista", "punelistacombinata", "punelogouri", "punenotesubsol", "punenotesubsollocale", "punenumarpagina", "puneregistru", "punerigla", "punesubformula", "punevariabilatext", "ran", "ref", "refa", "referinta", "referintapagina", "referintatext", "referit", "referring", "reflexie", "register", "remarca", "reservefloat", "reset", "reseteazamarcaje", "resetnumber", "resettextcontent", "riglatext", "rigleumplere", "roteste", "saripesteblocuri", "scala", "scriebuffer", "scrieinlista", "scrieinlistareferinte", "scrieinregistru", "scrieintreliste", "section", "seeregister", "selecteazablocuri", "selecteazahartie", "selecteazaversiune", "semncarte", "setarebarasincronizare", "setareitemization", "setarelimba", "setareoutput", "setarepozitie", "setaresincronizare", "setari", "seteazaaliniat", "seteazaalinierea", "seteazaantet", "seteazaaranjareapag", "seteazaaspect", "seteazabarainteractiune", "seteazablanc", "seteazabloc", "seteazablocsectiune", "seteazablocurimarginale", "seteazabuffer", "seteazabutoane", "seteazacamp", "seteazacampuri", "seteazaclipping", "seteazacoloane", "seteazacombinari", "seteazacomentariu", "seteazacomentariupagina", "seteazaculoare", "seteazaculori", "seteazadefinireanotasubsol", "seteazadescriere", "seteazadimensiunihartie", "seteazaecrane", "seteazaecraninteractiune", "seteazaelemente", "seteazaenumerare", "seteazafiguriexterne", "seteazafloat", "seteazafloats", "seteazafonttext", "seteazaformulare", "seteazaformule", "seteazafundal", "seteazafundaluri", "seteazagrosimelinie", "seteazaimpartireafloat", "seteazainconjurat", "seteazaingust", "seteazainteractiunea", "seteazajos", "seteazalegenda", "seteazalegendele", "seteazaliniesilabe", "seteazaliniesubtire", "seteazalinii", "seteazaliniimargine", "seteazaliniinegre", "seteazaliniiumplere", "seteazalista", "seteazalistacombinata", "seteazalistareferinte", "seteazamajuscule", "seteazamakeup", "seteazamarcaje", "seteazamarginal", "seteazamediulfonttext", "seteazameniuinteractiune", "seteazaminicitat", "seteazanotasubsol", "seteazanumarpagina", "seteazanumarsubpagina", "seteazanumartitlu", "seteazanumerotare", "seteazanumerotarelinii", "seteazanumerotarepagina", "seteazanumerotareparagrafe", "seteazapaleta", "seteazaparagrafe", "seteazaplasareaopozita", "seteazapozitietext", "seteazaprofile", "seteazaprograme", "seteazapublicatii", "seteazareferinte", "seteazaregistru", "seteazarigla", "seteazarigletext", "seteazarigleumplere", "seteazarotare", "seteazasectiune", "seteazasimbol", "seteazasinonime", "seteazasistem", "seteazasortare", "seteazaspatiu", "seteazaspatiualb", "seteazaspatiuinterliniar", "seteazastrut", "seteazasublinie", "seteazasubsol", "seteazasus", "seteazatab", "seteazatabele", "seteazatabulatori", "seteazatext", "seteazatexteantet", "seteazatextejos", "seteazatextesubsol", "seteazatextesus", "seteazatextetext", "seteazatexteticheta", "seteazatexttitlu", "seteazatitlu", "seteazatitluri", "seteazatoleranta", "seteazatranzitiepagina", "seteazatype", "seteazatyping", "seteazaurl", "seteazavariabilatext", "seteazaversiuni", "setnumber", "settextcontent", "setupanswerarea", "setupcolumnset", "setupcolumnsetlines", "setupcolumnsetstart", "setupfonthandling", "setupfontsynonym", "setupindentedtext", "setupinterlinespace2", "setupitemgroup", "setuplistalternative", "setupmathalignment", "setupnumber", "setuppaper", "setupplacement", "setupstartstop", "setvariabilatext", "sim", "simbol", "sincronizeaza", "sort", "spatiifixate", "spatiu", "spatiualb", "spatiufixat", "spatiujos", "spatiuspate", "spatiusus", "startalignment", "startaliniere", "startblocmarginal", "startbuffer", "startcitat", "startcodificare", "startcoloane", "startcolumnmakeup", "startcolumns", "startcolumnset", "startcombinare", "startcombination", "startcomment", "startcomponenta", "startcorectielinie", "startculoare", "startdescription", "startdocument", "startenumeration", "startfact", "startfigura", "startfigure", "startfloattext", "startformula", "startframedtext", "startfundal", "startglobal", "starthiding", "startimpachetat", "startingust", "startitemgroup", "startlegend", "startline", "startlinecorrection", "startlinenumbering", "startlines", "startlinie", "startliniemargine", "startlinii", "startlocal", "startlocalenvironment", "startlocalfootnotes", "startmakeup", "startmarginblock", "startmediu", "startmeniuinteractiune", "startnamemakeup", "startnarrower", "startneimpachetat", "startnotesubsollocale", "startnumerotarelinii", "startopozit", "startopposite", "startoverlay", "startoverview", "startparagraph", "startpositioning", "startpostponing", "startpozitionare", "startprodus", "startprofil", "startprofile", "startproiect", "startraster", "startregister", "startriglatext", "startsetsimboluri", "startsincronizare", "startsymbolset", "startsynchronization", "starttabel", "starttabele", "starttable", "starttables", "starttabulate", "starttext", "starttyping", "startunpacked", "startversiune", "stivacampuri", "stopalignment", "stopaliniere", "stopblobal", "stopblocmarginal", "stopbuffer", "stopcitat", "stopcodificare", "stopcoloane", "stopcolumnmakeup", "stopcolumns", "stopcolumnset", "stopcombinare", "stopcombination", "stopcomment", "stopcomponenta", "stopcorectielinie", "stopculoare", "stopdescription", "stopdocument", "stopenumeration", "stopfact", "stopfigure", "stopfloattext", "stopformula", "stopframedtext", "stopfundal", "stophiding", "stopimpachetat", "stopingust", "stopitemgroup", "stoplegend", "stopline", "stoplinecorrection", "stoplinenumbering", "stoplines", "stoplinie", "stopliniemargine", "stoplinii", "stoplocal", "stoplocalenvironment", "stoplocalfootnotes", "stopmakeup", "stopmarginblock", "stopmediu", "stopmeniuinteractiune", "stopnamemakeup", "stopnarrower", "stopneimpachetat", "stopnotesubsollocale", "stopnumerotarelinii", "stopopozit", "stopopposite", "stopoverlay", "stopoverview", "stopparagraph", "stoppositioning", "stoppostponing", "stoppozitionare", "stopprodus", "stopprofil", "stopprofile", "stopproiect", "stopraster", "stopriglatext", "stopsincronizare", "stopsymbolset", "stopsynchronization", "stoptabel", "stoptabele", "stoptable", "stoptables", "stoptabulate", "stoptext", "stoptyping", "stopunpacked", "stopversiune", "sub", "subject", "subpagenumber", "subsection", "subsubject", "subsubsection", "subsubsubject", "synonym", "tab", "testcolumn", "testpage", "tex", "texteticheta", "textmarginal", "texttitlu", "textumplere", "title", "titlu", "titlumarginal", "tooltip", "traduce", "trecilafontraw", "trecilafonttext", "txt", "typ", "type", "typefile", "underbar", "underbars", "undeva", "urmeazaprofil", "urmeazaversiune", "urmeazaversiuneprofil", "useXMLfilter", "usedirectory", "usetypescript", "usetypescriptfile", "valoareculoare", "valoaregri", "variabilatext", "versiune", "vl", "zidinsaptamana" },
}
\ No newline at end of file
diff --git a/Master/texmf-dist/context/data/scite/lexers/data/scite-context-data-metafun.lua b/Master/texmf-dist/context/data/scite/lexers/data/scite-context-data-metafun.lua
index 749be7663c1..524a1ca494f 100644
--- a/Master/texmf-dist/context/data/scite/lexers/data/scite-context-data-metafun.lua
+++ b/Master/texmf-dist/context/data/scite/lexers/data/scite-context-data-metafun.lua
@@ -1,4 +1,4 @@
return {
- ["commands"]={ "sqr", "log", "ln", "exp", "inv", "pow", "pi", "radian", "tand", "cotd", "sin", "cos", "tan", "cot", "atan", "asin", "acos", "invsin", "invcos", "acosh", "asinh", "sinh", "cosh", "paired", "tripled", "unitcircle", "fulldiamond", "unitdiamond", "fullsquare", "llcircle", "lrcircle", "urcircle", "ulcircle", "tcircle", "bcircle", "lcircle", "rcircle", "lltriangle", "lrtriangle", "urtriangle", "ultriangle", "smoothed", "cornered", "superellipsed", "randomized", "squeezed", "enlonged", "shortened", "punked", "curved", "unspiked", "simplified", "blownup", "stretched", "enlarged", "leftenlarged", "topenlarged", "rightenlarged", "bottomenlarged", "crossed", "laddered", "randomshifted", "interpolated", "paralleled", "cutends", "peepholed", "llenlarged", "lrenlarged", "urenlarged", "ulenlarged", "llmoved", "lrmoved", "urmoved", "ulmoved", "rightarrow", "leftarrow", "centerarrow", "boundingbox", "innerboundingbox", "outerboundingbox", "pushboundingbox", "popboundingbox", "bottomboundary", "leftboundary", "topboundary", "rightboundary", "xsized", "ysized", "xysized", "sized", "xyscaled", "intersection_point", "intersection_found", "penpoint", "bbwidth", "bbheight", "withshade", "withlinearshading", "withcircularshading", "withfromshadecolor", "withtoshadecolor", "withshading", "shadedinto", "withcircularshade", "withlinearshade", "cmyk", "spotcolor", "multitonecolor", "namedcolor", "drawfill", "undrawfill", "inverted", "uncolored", "softened", "grayed", "greyed", "onlayer", "along", "graphictext", "loadfigure", "externalfigure", "withmask", "figure", "register", "bitmapimage", "colordecimals", "ddecimal", "dddecimal", "ddddecimal", "textext", "thetextext", "rawtextext", "textextoffset", "verbatim", "thelabel", "label", "transparent", "withtransparency", "asgroup", "infont", "set_linear_vector", "linear_shade", "define_linear_shade", "define_circular_linear_shade", "define_sampled_linear_shade", "set_circular_vector", "circular_shade", "define_circular_shade", "define_circular_linear_shade", "define_sampled_circular_shade", "space", "CRLF", "grayscale", "greyscale", "withgray", "withgrey", "colorpart", "readfile", "clearxy", "unitvector", "center", "epsed", "anchored", "originpath", "infinite", "break", "xstretched", "ystretched", "snapped", "pathconnectors", "function", "constructedpath", "constructedpairs", "punkedfunction", "curvedfunction", "tightfunction", "punkedpath", "curvedpath", "tightpath", "punkedpairs", "curvedpairs", "tightpairs", "evenly", "oddly", "condition", "pushcurrentpicture", "popcurrentpicture", "arrowpath", "tensecircle", "roundedsquare", "colortype", "whitecolor", "blackcolor", "normalfill", "normaldraw", "visualizepaths", "naturalizepaths", "drawboundary", "drawwholepath", "visualizeddraw", "visualizedfill", "draworigin", "drawboundingbox", "drawpath", "drawpoint", "drawpoints", "drawcontrolpoints", "drawcontrollines", "drawpointlabels", "drawlineoptions", "drawpointoptions", "drawcontroloptions", "drawlabeloptions", "draworiginoptions", "drawboundoptions", "drawpathoptions", "resetdrawoptions" },
- ["internals"]={ "nocolormodel", "greycolormodel", "graycolormodel", "rgbcolormodel", "cmykcolormodel", "shadefactor", "textextoffset", "normaltransparent", "multiplytransparent", "screentransparent", "overlaytransparent", "softlighttransparent", "hardlighttransparent", "colordodgetransparent", "colorburntransparent", "darkentransparent", "lightentransparent", "differencetransparent", "exclusiontransparent", "huetransparent", "saturationtransparent", "colortransparent", "luminositytransparent" },
+ ["commands"]={ "sqr", "log", "ln", "exp", "inv", "pow", "pi", "radian", "tand", "cotd", "sin", "cos", "tan", "cot", "atan", "asin", "acos", "invsin", "invcos", "acosh", "asinh", "sinh", "cosh", "paired", "tripled", "unitcircle", "fulldiamond", "unitdiamond", "fullsquare", "llcircle", "lrcircle", "urcircle", "ulcircle", "tcircle", "bcircle", "lcircle", "rcircle", "lltriangle", "lrtriangle", "urtriangle", "ultriangle", "smoothed", "cornered", "superellipsed", "randomized", "squeezed", "enlonged", "shortened", "punked", "curved", "unspiked", "simplified", "blownup", "stretched", "enlarged", "leftenlarged", "topenlarged", "rightenlarged", "bottomenlarged", "crossed", "laddered", "randomshifted", "interpolated", "paralleled", "cutends", "peepholed", "llenlarged", "lrenlarged", "urenlarged", "ulenlarged", "llmoved", "lrmoved", "urmoved", "ulmoved", "rightarrow", "leftarrow", "centerarrow", "boundingbox", "innerboundingbox", "outerboundingbox", "pushboundingbox", "popboundingbox", "bottomboundary", "leftboundary", "topboundary", "rightboundary", "xsized", "ysized", "xysized", "sized", "xyscaled", "intersection_point", "intersection_found", "penpoint", "bbwidth", "bbheight", "withshade", "withlinearshading", "withcircularshading", "withfromshadecolor", "withtoshadecolor", "withshading", "shadedinto", "withcircularshade", "withlinearshade", "cmyk", "spotcolor", "multitonecolor", "namedcolor", "drawfill", "undrawfill", "inverted", "uncolored", "softened", "grayed", "greyed", "onlayer", "along", "graphictext", "loadfigure", "externalfigure", "withmask", "figure", "register", "bitmapimage", "colordecimals", "ddecimal", "dddecimal", "ddddecimal", "textext", "thetextext", "rawtextext", "textextoffset", "verbatim", "thelabel", "label", "autoalign", "transparent", "withtransparency", "property", "properties", "withproperties", "asgroup", "infont", "set_linear_vector", "linear_shade", "define_linear_shade", "define_circular_linear_shade", "define_sampled_linear_shade", "set_circular_vector", "circular_shade", "define_circular_shade", "define_circular_linear_shade", "define_sampled_circular_shade", "space", "CRLF", "grayscale", "greyscale", "withgray", "withgrey", "colorpart", "readfile", "clearxy", "unitvector", "center", "epsed", "anchored", "originpath", "infinite", "break", "xstretched", "ystretched", "snapped", "pathconnectors", "function", "constructedpath", "constructedpairs", "punkedfunction", "curvedfunction", "tightfunction", "punkedpath", "curvedpath", "tightpath", "punkedpairs", "curvedpairs", "tightpairs", "evenly", "oddly", "condition", "pushcurrentpicture", "popcurrentpicture", "arrowpath", "tensecircle", "roundedsquare", "colortype", "whitecolor", "blackcolor", "normalfill", "normaldraw", "visualizepaths", "naturalizepaths", "drawboundary", "drawwholepath", "visualizeddraw", "visualizedfill", "draworigin", "drawboundingbox", "drawpath", "drawpoint", "drawpoints", "drawcontrolpoints", "drawcontrollines", "drawpointlabels", "drawlineoptions", "drawpointoptions", "drawcontroloptions", "drawlabeloptions", "draworiginoptions", "drawboundoptions", "drawpathoptions", "resetdrawoptions", "decorated", "redecorated", "undecorated" },
+ ["internals"]={ "nocolormodel", "greycolormodel", "graycolormodel", "rgbcolormodel", "cmykcolormodel", "shadefactor", "textextoffset", "normaltransparent", "multiplytransparent", "screentransparent", "overlaytransparent", "softlighttransparent", "hardlighttransparent", "colordodgetransparent", "colorburntransparent", "darkentransparent", "lightentransparent", "differencetransparent", "exclusiontransparent", "huetransparent", "saturationtransparent", "colortransparent", "luminositytransparent", "metapostversion", "maxdimensions" },
}
\ No newline at end of file
diff --git a/Master/texmf-dist/context/data/scite/lexers/data/scite-context-data-metapost.lua b/Master/texmf-dist/context/data/scite/lexers/data/scite-context-data-metapost.lua
index d3c19908956..df97c0a268a 100644
--- a/Master/texmf-dist/context/data/scite/lexers/data/scite-context-data-metapost.lua
+++ b/Master/texmf-dist/context/data/scite/lexers/data/scite-context-data-metapost.lua
@@ -1,7 +1,7 @@
return {
["commands"]={ "beginfig", "endfig", "rotatedaround", "reflectedabout", "arrowhead", "currentpen", "currentpicture", "cuttings", "defaultfont", "extra_beginfig", "extra_endfig", "ditto", "EOF", "down", "evenly", "fullcircle", "halfcircle", "identity", "in", "left", "origin", "pensquare", "quartercircle", "right", "unitsquare", "up", "withdots", "abs", "bbox", "ceiling", "center", "cutafter", "cutbefore", "dir", "directionpoint", "div", "dotprod", "intersectionpoint", "inverse", "mod", "round", "unitvector", "whatever", "cutdraw", "draw", "drawarrow", "drawdblarrow", "fill", "filldraw", "drawdot", "loggingall", "interact", "tracingall", "tracingnone", "pickup", "undraw", "unfill", "unfilldraw", "buildcycle", "dashpattern", "decr", "dotlabel", "dotlabels", "drawoptions", "incr", "label", "labels", "max", "min", "thelabel", "z", "beginchar", "blacker", "capsule_end", "change_width", "define_blacker_pixels", "define_corrected_pixels", "define_good_x_pixels", "define_good_y_pixels", "define_horizontal_corrected_pixels", "define_pixels", "define_whole_blacker_pixels", "define_whole_pixels", "define_whole_vertical_blacker_pixels", "define_whole_vertical_pixels", "endchar", "extra_beginchar", "extra_endchar", "extra_setup", "font_coding_scheme", "clearxy", "clearit", "clearpen", "shipit", "font_extra_space", "exitunless", "relax", "hide", "gobble", "gobbled", "stop", "blankpicture", "counterclockwise", "tensepath", "takepower", "direction", "softjoin", "makelabel", "rotatedabout", "flex", "superellipse", "erase", "image", "nullpen", "savepen", "clearpen", "penpos", "penlabels", "range", "numtok", "thru", "z", "laboff", "bye", "red", "green", "blue", "cyan", "magenta", "yellow", "black", "white", "background", "graypart", "graycolor", "mm", "pt", "dd", "bp", "cm", "pc", "cc", "in" },
["internals"]={ "mitered", "rounded", "beveled", "butt", "squared", "eps", "epsilon", "infinity", "bboxmargin", "ahlength", "ahangle", "labeloffset", "dotlabeldiam", "defaultpen", "defaultscale", "join_radius", "pen_lft", "pen_rt", "pen_top", "pen_bot" },
- ["primitives"]={ "charcode", "day", "linecap", "linejoin", "miterlimit", "month", "pausing", "prologues", "showstopping", "time", "tracingcapsules", "tracingchoices", "mpprocset", "tracingcommands", "tracingequations", "tracinglostchars", "tracingmacros", "tracingonline", "tracingoutput", "tracingrestores", "tracingspecs", "tracingstats", "tracingtitles", "truecorners", "warningcheck", "year", "false", "nullpicture", "pencircle", "true", "and", "angle", "arclength", "arctime", "ASCII", "boolean", "bot", "char", "color", "cosd", "cycle", "decimal", "directiontime", "floor", "fontsize", "hex", "infont", "intersectiontimes", "known", "length", "llcorner", "lrcorner", "makepath", "makepen", "mexp", "mlog", "normaldeviate", "not", "numeric", "oct", "odd", "or", "path", "pair", "pen", "penoffset", "picture", "point", "postcontrol", "precontrol", "reverse", "rotated", "scaled", "shifted", "sind", "slanted", "sqrt", "str", "string", "subpath", "substring", "transform", "transformed", "ulcorner", "uniformdeviate", "unknown", "urcorner", "xpart", "xscaled", "xxpart", "xypart", "ypart", "yscaled", "yxpart", "yypart", "zscaled", "addto", "clip", "input", "interim", "let", "newinternal", "save", "setbounds", "shipout", "show", "showdependencies", "showtoken", "showvariable", "special", "begingroup", "endgroup", "of", "curl", "tension", "and", "controls", "interpath", "on", "off", "def", "vardef", "enddef", "expr", "suffix", "text", "primary", "secondary", "tertiary", "primarydef", "secondarydef", "tertiarydef", "randomseed", "also", "contour", "doublepath", "withcolor", "withpen", "dashed", "if", "else", "elseif", "fi", "for", "endfor", "forever", "exitif", "forsuffixes", "downto", "upto", "step", "until", "charlist", "extensible", "fontdimen", "headerbyte", "kern", "ligtable", "boundarychar", "chardp", "charext", "charht", "charic", "charwd", "designsize", "fontmaking", "charexists", "cullit", "currenttransform", "gfcorners", "grayfont", "hround", "imagerules", "lowres_fix", "nodisplays", "notransforms", "openit", "displaying", "currentwindow", "screen_rows", "screen_cols", "pixels_per_inch", "cull", "display", "openwindow", "numspecial", "totalweight", "autorounding", "fillin", "proofing", "tracingpens", "xoffset", "chardx", "granularity", "smoothing", "turningcheck", "yoffset", "chardy", "hppp", "tracingedges", "vppp", "extra_beginfig", "extra_endfig", "mpxbreak", "endinput", "message", "delimiters", "turningnumber", "errmessage", "readstring", "scantokens", "end", "outer", "inner", "write", "to", "readfrom", "withprescript", "withpostscript", "top", "bot", "lft", "rt", "ulft", "urt", "llft", "lrt", "redpart", "greenpart", "bluepart", "cyanpart", "magentapart", "yellowpart", "blackpart", "greypart", "rgbcolor", "cmykcolor", "greycolor", "graycolor", "colormodel", "graypart", "expandafter" },
+ ["primitives"]={ "charcode", "day", "linecap", "linejoin", "miterlimit", "month", "pausing", "prologues", "showstopping", "time", "tracingcapsules", "tracingchoices", "mpprocset", "tracingcommands", "tracingequations", "tracinglostchars", "tracingmacros", "tracingonline", "tracingoutput", "tracingrestores", "tracingspecs", "tracingstats", "tracingtitles", "truecorners", "warningcheck", "year", "false", "nullpicture", "pencircle", "true", "and", "angle", "arclength", "arctime", "ASCII", "boolean", "bot", "char", "color", "cosd", "cycle", "decimal", "directiontime", "floor", "fontsize", "hex", "infont", "intersectiontimes", "known", "length", "llcorner", "lrcorner", "makepath", "makepen", "mexp", "mlog", "normaldeviate", "not", "numeric", "oct", "odd", "or", "path", "pair", "pen", "penoffset", "picture", "point", "postcontrol", "precontrol", "reverse", "rotated", "scaled", "shifted", "sind", "slanted", "sqrt", "str", "string", "subpath", "substring", "transform", "transformed", "ulcorner", "uniformdeviate", "unknown", "urcorner", "xpart", "xscaled", "xxpart", "xypart", "ypart", "yscaled", "yxpart", "yypart", "zscaled", "addto", "clip", "input", "interim", "let", "newinternal", "save", "setbounds", "shipout", "show", "showdependencies", "showtoken", "showvariable", "special", "begingroup", "endgroup", "of", "curl", "tension", "and", "controls", "interpath", "on", "off", "def", "vardef", "enddef", "expr", "suffix", "text", "primary", "secondary", "tertiary", "primarydef", "secondarydef", "tertiarydef", "randomseed", "also", "contour", "doublepath", "withcolor", "withpen", "dashed", "if", "else", "elseif", "fi", "for", "endfor", "forever", "exitif", "within", "forsuffixes", "downto", "upto", "step", "until", "charlist", "extensible", "fontdimen", "headerbyte", "kern", "ligtable", "boundarychar", "chardp", "charext", "charht", "charic", "charwd", "designsize", "fontmaking", "charexists", "cullit", "currenttransform", "gfcorners", "grayfont", "hround", "imagerules", "lowres_fix", "nodisplays", "notransforms", "openit", "displaying", "currentwindow", "screen_rows", "screen_cols", "pixels_per_inch", "cull", "display", "openwindow", "numspecial", "totalweight", "autorounding", "fillin", "proofing", "tracingpens", "xoffset", "chardx", "granularity", "smoothing", "turningcheck", "yoffset", "chardy", "hppp", "tracingedges", "vppp", "extra_beginfig", "extra_endfig", "mpxbreak", "endinput", "message", "delimiters", "turningnumber", "errmessage", "readstring", "scantokens", "end", "outer", "inner", "write", "to", "readfrom", "withprescript", "withpostscript", "top", "bot", "lft", "rt", "ulft", "urt", "llft", "lrt", "redpart", "greenpart", "bluepart", "cyanpart", "magentapart", "yellowpart", "blackpart", "greypart", "rgbcolor", "cmykcolor", "greycolor", "graycolor", "colormodel", "graypart", "dashpart", "penpart", "stroked", "filled", "textual", "clipped", "bounded", "expandafter" },
["shortcuts"]={ "..", "...", "--", "---", "&" },
["tex"]={ "btex", "etex", "verbatimtex" },
}
\ No newline at end of file
diff --git a/Master/texmf-dist/context/data/scite/lexers/data/scite-context-data-tex.lua b/Master/texmf-dist/context/data/scite/lexers/data/scite-context-data-tex.lua
index 0dd0e1764b0..7d710740c29 100644
--- a/Master/texmf-dist/context/data/scite/lexers/data/scite-context-data-tex.lua
+++ b/Master/texmf-dist/context/data/scite/lexers/data/scite-context-data-tex.lua
@@ -1,9 +1,9 @@
return {
["aleph"]={ "AlephVersion", "Alephminorversion", "Alephrevision", "Alephversion", "Omegaminorversion", "Omegarevision", "Omegaversion", "boxdir", "pagebottomoffset", "pagerightoffset" },
["etex"]={ "botmarks", "clubpenalties", "currentgrouplevel", "currentgrouptype", "currentifbranch", "currentiflevel", "currentiftype", "detokenize", "dimexpr", "displaywidowpenalties", "eTeXVersion", "eTeXminorversion", "eTeXrevision", "eTeXversion", "everyeof", "firstmarks", "fontchardp", "fontcharht", "fontcharic", "fontcharwd", "glueexpr", "glueshrink", "glueshrinkorder", "gluestretch", "gluestretchorder", "gluetomu", "ifcsname", "ifdefined", "iffontchar", "interactionmode", "interlinepenalties", "lastlinefit", "lastnodetype", "marks", "muexpr", "mutoglue", "numexpr", "pagediscards", "parshapedimen", "parshapeindent", "parshapelength", "predisplaydirection", "protected", "readline", "savinghyphcodes", "savingvdiscards", "scantokens", "showgroups", "showifs", "showtokens", "splitbotmarks", "splitdiscards", "splitfirstmarks", "topmarks", "tracingassigns", "tracinggroups", "tracingifs", "tracingnesting", "tracingscantokens", "unexpanded", "unless", "widowpenalties" },
- ["luatex"]={ "Udelcode", "Udelcodenum", "Udelimiter", "Udelimiterover", "Udelimiterunder", "Umathaccent", "Umathaccents", "Umathaxis", "Umathbinbinspacing", "Umathbinclosespacing", "Umathbininnerspacing", "Umathbinopenspacing", "Umathbinopspacing", "Umathbinordspacing", "Umathbinpunctspacing", "Umathbinrelspacing", "Umathbotaccent", "Umathchar", "Umathchardef", "Umathcharnum", "Umathclosebinspacing", "Umathcloseclosespacing", "Umathcloseinnerspacing", "Umathcloseopenspacing", "Umathcloseopspacing", "Umathcloseordspacing", "Umathclosepunctspacing", "Umathcloserelspacing", "Umathcode", "Umathcodenum", "Umathconnectoroverlapmin", "Umathfractiondelsize", "Umathfractiondenomdown", "Umathfractiondenomvgap", "Umathfractionnumup", "Umathfractionnumvgap", "Umathfractionrule", "Umathinnerbinspacing", "Umathinnerclosespacing", "Umathinnerinnerspacing", "Umathinneropenspacing", "Umathinneropspacing", "Umathinnerordspacing", "Umathinnerpunctspacing", "Umathinnerrelspacing", "Umathlimitabovebgap", "Umathlimitabovekern", "Umathlimitabovevgap", "Umathlimitbelowbgap", "Umathlimitbelowkern", "Umathlimitbelowvgap", "Umathopbinspacing", "Umathopclosespacing", "Umathopenbinspacing", "Umathopenclosespacing", "Umathopeninnerspacing", "Umathopenopenspacing", "Umathopenopspacing", "Umathopenordspacing", "Umathopenpunctspacing", "Umathopenrelspacing", "Umathoperatorsize", "Umathopinnerspacing", "Umathopopenspacing", "Umathopopspacing", "Umathopordspacing", "Umathoppunctspacing", "Umathoprelspacing", "Umathordbinspacing", "Umathordclosespacing", "Umathordinnerspacing", "Umathordopenspacing", "Umathordopspacing", "Umathordordspacing", "Umathordpunctspacing", "Umathordrelspacing", "Umathoverbarkern", "Umathoverbarrule", "Umathoverbarvgap", "Umathoverdelimiterbgap", "Umathoverdelimitervgap", "Umathpunctbinspacing", "Umathpunctclosespacing", "Umathpunctinnerspacing", "Umathpunctopenspacing", "Umathpunctopspacing", "Umathpunctordspacing", "Umathpunctpunctspacing", "Umathpunctrelspacing", "Umathquad", "Umathradicaldegreeafter", "Umathradicaldegreebefore", "Umathradicaldegreeraise", "Umathradicalkern", "Umathradicalrule", "Umathradicalvgap", "Umathrelbinspacing", "Umathrelclosespacing", "Umathrelinnerspacing", "Umathrelopenspacing", "Umathrelopspacing", "Umathrelordspacing", "Umathrelpunctspacing", "Umathrelrelspacing", "Umathspaceafterscript", "Umathstackdenomdown", "Umathstacknumup", "Umathstackvgap", "Umathsubshiftdown", "Umathsubshiftdrop", "Umathsubsupshiftdown", "Umathsubsupvgap", "Umathsubtopmax", "Umathsupbottommin", "Umathsupshiftdrop", "Umathsupshiftup", "Umathsupsubbottommax", "Umathunderbarkern", "Umathunderbarrule", "Umathunderbarvgap", "Umathunderdelimiterbgap", "Umathunderdelimitervgap", "Uoverdelimiter", "Uradical", "Uroot", "Ustack", "Ustartdisplaymath", "Ustartmath", "Ustopdisplaymath", "Ustopmath", "Usubscript", "Usuperscript", "Uunderdelimiter", "alignmark", "aligntab", "attribute", "attributedef", "catcodetable", "clearmarks", "crampeddisplaystyle", "crampedscriptscriptstyle", "crampedscriptstyle", "crampedtextstyle", "fontid", "formatname", "gleaders", "ifabsdim", "ifabsnum", "ifprimitive", "initcatcodetable", "latelua", "luaescapestring", "luastartup", "luatexdatestamp", "luatexrevision", "luatexversion", "mathstyle", "nokerns", "noligs", "outputbox", "pageleftoffset", "pagetopoffset", "postexhyphenchar", "posthyphenchar", "preexhyphenchar", "prehyphenchar", "primitive", "savecatcodetable", "scantextokens", "suppressfontnotfounderror", "suppressifcsnameerror", "suppresslongerror", "suppressoutererror", "synctex" },
+ ["luatex"]={ "Uchar", "Udelcode", "Udelcodenum", "Udelimiter", "Udelimiterover", "Udelimiterunder", "Umathaccent", "Umathaxis", "Umathbinbinspacing", "Umathbinclosespacing", "Umathbininnerspacing", "Umathbinopenspacing", "Umathbinopspacing", "Umathbinordspacing", "Umathbinpunctspacing", "Umathbinrelspacing", "Umathchar", "Umathchardef", "Umathcharnum", "Umathclosebinspacing", "Umathcloseclosespacing", "Umathcloseinnerspacing", "Umathcloseopenspacing", "Umathcloseopspacing", "Umathcloseordspacing", "Umathclosepunctspacing", "Umathcloserelspacing", "Umathcode", "Umathcodenum", "Umathconnectoroverlapmin", "Umathfractiondelsize", "Umathfractiondenomdown", "Umathfractiondenomvgap", "Umathfractionnumup", "Umathfractionnumvgap", "Umathfractionrule", "Umathinnerbinspacing", "Umathinnerclosespacing", "Umathinnerinnerspacing", "Umathinneropenspacing", "Umathinneropspacing", "Umathinnerordspacing", "Umathinnerpunctspacing", "Umathinnerrelspacing", "Umathlimitabovebgap", "Umathlimitabovekern", "Umathlimitabovevgap", "Umathlimitbelowbgap", "Umathlimitbelowkern", "Umathlimitbelowvgap", "Umathopbinspacing", "Umathopclosespacing", "Umathopenbinspacing", "Umathopenclosespacing", "Umathopeninnerspacing", "Umathopenopenspacing", "Umathopenopspacing", "Umathopenordspacing", "Umathopenpunctspacing", "Umathopenrelspacing", "Umathoperatorsize", "Umathopinnerspacing", "Umathopopenspacing", "Umathopopspacing", "Umathopordspacing", "Umathoppunctspacing", "Umathoprelspacing", "Umathordbinspacing", "Umathordclosespacing", "Umathordinnerspacing", "Umathordopenspacing", "Umathordopspacing", "Umathordordspacing", "Umathordpunctspacing", "Umathordrelspacing", "Umathoverbarkern", "Umathoverbarrule", "Umathoverbarvgap", "Umathoverdelimiterbgap", "Umathoverdelimitervgap", "Umathpunctbinspacing", "Umathpunctclosespacing", "Umathpunctinnerspacing", "Umathpunctopenspacing", "Umathpunctopspacing", "Umathpunctordspacing", "Umathpunctpunctspacing", "Umathpunctrelspacing", "Umathquad", "Umathradicaldegreeafter", "Umathradicaldegreebefore", "Umathradicaldegreeraise", "Umathradicalkern", "Umathradicalrule", "Umathradicalvgap", "Umathrelbinspacing", "Umathrelclosespacing", "Umathrelinnerspacing", "Umathrelopenspacing", "Umathrelopspacing", "Umathrelordspacing", "Umathrelpunctspacing", "Umathrelrelspacing", "Umathspaceafterscript", "Umathstackdenomdown", "Umathstacknumup", "Umathstackvgap", "Umathsubshiftdown", "Umathsubshiftdrop", "Umathsubsupshiftdown", "Umathsubsupvgap", "Umathsubtopmax", "Umathsupbottommin", "Umathsupshiftdrop", "Umathsupshiftup", "Umathsupsubbottommax", "Umathunderbarkern", "Umathunderbarrule", "Umathunderbarvgap", "Umathunderdelimiterbgap", "Umathunderdelimitervgap", "Uoverdelimiter", "Uradical", "Uroot", "Ustack", "Ustartdisplaymath", "Ustartmath", "Ustopdisplaymath", "Ustopmath", "Usubscript", "Usuperscript", "Uunderdelimiter", "alignmark", "aligntab", "attribute", "attributedef", "catcodetable", "clearmarks", "crampeddisplaystyle", "crampedscriptscriptstyle", "crampedscriptstyle", "crampedtextstyle", "fontid", "formatname", "gleaders", "ifabsdim", "ifabsnum", "ifprimitive", "initcatcodetable", "latelua", "luaescapestring", "luastartup", "luatexdatestamp", "luatexrevision", "luatexversion", "mathstyle", "nokerns", "noligs", "outputbox", "pageleftoffset", "pagetopoffset", "postexhyphenchar", "posthyphenchar", "preexhyphenchar", "prehyphenchar", "primitive", "savecatcodetable", "scantextokens", "suppressfontnotfounderror", "suppressifcsnameerror", "suppresslongerror", "suppressoutererror", "synctex" },
["omega"]={ "OmegaVersion", "bodydir", "chardp", "charht", "charit", "charwd", "leftghost", "localbrokenpenalty", "localinterlinepenalty", "localleftbox", "localrightbox", "mathdir", "odelcode", "odelimiter", "omathaccent", "omathchar", "omathchardef", "omathcode", "oradical", "pagedir", "pageheight", "pagewidth", "pardir", "rightghost", "textdir" },
["pdftex"]={ "efcode", "expanded", "ifincsname", "ifpdfabsdim", "ifpdfabsnum", "ifpdfprimitive", "leftmarginkern", "letterspacefont", "lpcode", "pdfadjustspacing", "pdfannot", "pdfcatalog", "pdfcolorstack", "pdfcolorstackinit", "pdfcompresslevel", "pdfcopyfont", "pdfcreationdate", "pdfdecimaldigits", "pdfdest", "pdfdestmargin", "pdfdraftmode", "pdfeachlinedepth", "pdfeachlineheight", "pdfendlink", "pdfendthread", "pdffirstlineheight", "pdffontattr", "pdffontexpand", "pdffontname", "pdffontobjnum", "pdffontsize", "pdfgamma", "pdfgentounicode", "pdfglyphtounicode", "pdfhorigin", "pdfignoreddimen", "pdfimageapplygamma", "pdfimagegamma", "pdfimagehicolor", "pdfimageresolution", "pdfincludechars", "pdfinclusioncopyfonts", "pdfinclusionerrorlevel", "pdfinfo", "pdfinsertht", "pdflastannot", "pdflastlinedepth", "pdflastlink", "pdflastobj", "pdflastxform", "pdflastximage", "pdflastximagecolordepth", "pdflastximagepages", "pdflastxpos", "pdflastypos", "pdflinkmargin", "pdfliteral", "pdfmapfile", "pdfmapline", "pdfminorversion", "pdfnames", "pdfnoligatures", "pdfnormaldeviate", "pdfobj", "pdfobjcompresslevel", "pdfoptionpdfminorversion", "pdfoutline", "pdfoutput", "pdfpageattr", "pdfpagebox", "pdfpageheight", "pdfpageref", "pdfpageresources", "pdfpagesattr", "pdfpagewidth", "pdfpkmode", "pdfpkresolution", "pdfprimitive", "pdfprotrudechars", "pdfpxdimen", "pdfrandomseed", "pdfrefobj", "pdfrefxform", "pdfrefximage", "pdfreplacefont", "pdfrestore", "pdfretval", "pdfsave", "pdfsavepos", "pdfsetmatrix", "pdfsetrandomseed", "pdfstartlink", "pdfstartthread", "pdftexbanner", "pdftexrevision", "pdftexversion", "pdfthread", "pdfthreadmargin", "pdftracingfonts", "pdftrailer", "pdfuniformdeviate", "pdfuniqueresname", "pdfvorigin", "pdfxform", "pdfxformattr", "pdfxformname", "pdfxformresources", "pdfximage", "pdfximagebbox", "quitvmode", "rightmarginkern", "rpcode", "tagcode" },
- ["tex"]={ "-", "/", "AlephVersion", "Alephminorversion", "Alephrevision", "Alephversion", "OmegaVersion", "Omegaminorversion", "Omegarevision", "Omegaversion", "Udelcode", "Udelcodenum", "Udelimiter", "Udelimiterover", "Udelimiterunder", "Umathaccent", "Umathaccents", "Umathaxis", "Umathbinbinspacing", "Umathbinclosespacing", "Umathbininnerspacing", "Umathbinopenspacing", "Umathbinopspacing", "Umathbinordspacing", "Umathbinpunctspacing", "Umathbinrelspacing", "Umathbotaccent", "Umathchar", "Umathchardef", "Umathcharnum", "Umathclosebinspacing", "Umathcloseclosespacing", "Umathcloseinnerspacing", "Umathcloseopenspacing", "Umathcloseopspacing", "Umathcloseordspacing", "Umathclosepunctspacing", "Umathcloserelspacing", "Umathcode", "Umathcodenum", "Umathconnectoroverlapmin", "Umathfractiondelsize", "Umathfractiondenomdown", "Umathfractiondenomvgap", "Umathfractionnumup", "Umathfractionnumvgap", "Umathfractionrule", "Umathinnerbinspacing", "Umathinnerclosespacing", "Umathinnerinnerspacing", "Umathinneropenspacing", "Umathinneropspacing", "Umathinnerordspacing", "Umathinnerpunctspacing", "Umathinnerrelspacing", "Umathlimitabovebgap", "Umathlimitabovekern", "Umathlimitabovevgap", "Umathlimitbelowbgap", "Umathlimitbelowkern", "Umathlimitbelowvgap", "Umathopbinspacing", "Umathopclosespacing", "Umathopenbinspacing", "Umathopenclosespacing", "Umathopeninnerspacing", "Umathopenopenspacing", "Umathopenopspacing", "Umathopenordspacing", "Umathopenpunctspacing", "Umathopenrelspacing", "Umathoperatorsize", "Umathopinnerspacing", "Umathopopenspacing", "Umathopopspacing", "Umathopordspacing", "Umathoppunctspacing", "Umathoprelspacing", "Umathordbinspacing", "Umathordclosespacing", "Umathordinnerspacing", "Umathordopenspacing", "Umathordopspacing", "Umathordordspacing", "Umathordpunctspacing", "Umathordrelspacing", "Umathoverbarkern", "Umathoverbarrule", "Umathoverbarvgap", "Umathoverdelimiterbgap", "Umathoverdelimitervgap", "Umathpunctbinspacing", "Umathpunctclosespacing", "Umathpunctinnerspacing", "Umathpunctopenspacing", "Umathpunctopspacing", "Umathpunctordspacing", "Umathpunctpunctspacing", "Umathpunctrelspacing", "Umathquad", "Umathradicaldegreeafter", "Umathradicaldegreebefore", "Umathradicaldegreeraise", "Umathradicalkern", "Umathradicalrule", "Umathradicalvgap", "Umathrelbinspacing", "Umathrelclosespacing", "Umathrelinnerspacing", "Umathrelopenspacing", "Umathrelopspacing", "Umathrelordspacing", "Umathrelpunctspacing", "Umathrelrelspacing", "Umathspaceafterscript", "Umathstackdenomdown", "Umathstacknumup", "Umathstackvgap", "Umathsubshiftdown", "Umathsubshiftdrop", "Umathsubsupshiftdown", "Umathsubsupvgap", "Umathsubtopmax", "Umathsupbottommin", "Umathsupshiftdrop", "Umathsupshiftup", "Umathsupsubbottommax", "Umathunderbarkern", "Umathunderbarrule", "Umathunderbarvgap", "Umathunderdelimiterbgap", "Umathunderdelimitervgap", "Uoverdelimiter", "Uradical", "Uroot", "Ustack", "Ustartdisplaymath", "Ustartmath", "Ustopdisplaymath", "Ustopmath", "Usubscript", "Usuperscript", "Uunderdelimiter", "above", "abovedisplayshortskip", "abovedisplayskip", "abovewithdelims", "accent", "adjdemerits", "advance", "afterassignment", "aftergroup", "alignmark", "aligntab", "atop", "atopwithdelims", "attribute", "attributedef", "badness", "baselineskip", "batchmode", "begingroup", "belowdisplayshortskip", "belowdisplayskip", "binoppenalty", "bodydir", "botmark", "botmarks", "box", "boxdir", "boxmaxdepth", "brokenpenalty", "catcode", "catcodetable", "char", "chardef", "chardp", "charht", "charit", "charwd", "cleaders", "clearmarks", "closein", "closeout", "clubpenalties", "clubpenalty", "copy", "count", "countdef", "cr", "crampeddisplaystyle", "crampedscriptscriptstyle", "crampedscriptstyle", "crampedtextstyle", "crcr", "csname", "currentgrouplevel", "currentgrouptype", "currentifbranch", "currentiflevel", "currentiftype", "day", "deadcycles", "def", "defaulthyphenchar", "defaultskewchar", "delcode", "delimiter", "delimiterfactor", "delimitershortfall", "detokenize", "dimen", "dimendef", "dimexpr", "directlua", "discretionary", "displayindent", "displaylimits", "displaystyle", "displaywidowpenalties", "displaywidowpenalty", "displaywidth", "divide", "doublehyphendemerits", "dp", "dump", "eTeXVersion", "eTeXminorversion", "eTeXrevision", "eTeXversion", "edef", "efcode", "else", "emergencystretch", "end", "endcsname", "endgroup", "endinput", "endlinechar", "eqno", "errhelp", "errmessage", "errorcontextlines", "errorstopmode", "escapechar", "everycr", "everydisplay", "everyeof", "everyhbox", "everyjob", "everymath", "everypar", "everyvbox", "exhyphenchar", "exhyphenpenalty", "expandafter", "expanded", "fam", "fi", "finalhyphendemerits", "firstmark", "firstmarks", "floatingpenalty", "font", "fontchardp", "fontcharht", "fontcharic", "fontcharwd", "fontdimen", "fontid", "fontname", "formatname", "futurelet", "gdef", "gleaders", "global", "globaldefs", "glueexpr", "glueshrink", "glueshrinkorder", "gluestretch", "gluestretchorder", "gluetomu", "halign", "hangafter", "hangindent", "hbadness", "hbox", "hfil", "hfill", "hfilneg", "hfuzz", "hoffset", "holdinginserts", "hrule", "hsize", "hskip", "hss", "ht", "hyphenation", "hyphenchar", "hyphenpenalty", "if", "ifabsdim", "ifabsnum", "ifcase", "ifcat", "ifcsname", "ifdefined", "ifdim", "ifeof", "iffalse", "iffontchar", "ifhbox", "ifhmode", "ifincsname", "ifinner", "ifmmode", "ifnum", "ifodd", "ifpdfabsdim", "ifpdfabsnum", "ifpdfprimitive", "ifprimitive", "iftrue", "ifvbox", "ifvmode", "ifvoid", "ifx", "ignorespaces", "immediate", "indent", "initcatcodetable", "input", "inputlineno", "insert", "insertpenalties", "interactionmode", "interlinepenalties", "interlinepenalty", "jobname", "kern", "language", "lastbox", "lastkern", "lastlinefit", "lastnodetype", "lastpenalty", "lastskip", "latelua", "lccode", "leaders", "left", "leftghost", "lefthyphenmin", "leftmarginkern", "leftskip", "leqno", "let", "letterspacefont", "limits", "linepenalty", "lineskip", "lineskiplimit", "localbrokenpenalty", "localinterlinepenalty", "localleftbox", "localrightbox", "long", "looseness", "lower", "lowercase", "lpcode", "luaescapestring", "luastartup", "luatexdatestamp", "luatexrevision", "luatexversion", "mag", "mark", "marks", "mathaccent", "mathbin", "mathchar", "mathchardef", "mathchoice", "mathclose", "mathcode", "mathdir", "mathinner", "mathop", "mathopen", "mathord", "mathpunct", "mathrel", "mathstyle", "mathsurround", "maxdeadcycles", "maxdepth", "meaning", "medmuskip", "message", "middle", "mkern", "month", "moveleft", "moveright", "mskip", "muexpr", "multiply", "muskip", "muskipdef", "mutoglue", "newlinechar", "noalign", "noboundary", "noexpand", "noindent", "nokerns", "noligs", "nolimits", "nolocaldirs", "nolocalwhatsits", "nonscript", "nonstopmode", "nulldelimiterspace", "nullfont", "number", "numexpr", "odelcode", "odelimiter", "omathaccent", "omathchar", "omathchardef", "omathcode", "omit", "openin", "openout", "or", "oradical", "outer", "output", "outputbox", "outputpenalty", "over", "overfullrule", "overline", "overwithdelims", "pagebottomoffset", "pagedepth", "pagedir", "pagediscards", "pagefilllstretch", "pagefillstretch", "pagefilstretch", "pagegoal", "pageheight", "pageleftoffset", "pagerightoffset", "pageshrink", "pagestretch", "pagetopoffset", "pagetotal", "pagewidth", "par", "pardir", "parfillskip", "parindent", "parshape", "parshapedimen", "parshapeindent", "parshapelength", "parskip", "patterns", "pausing", "pdfadjustspacing", "pdfannot", "pdfcatalog", "pdfcolorstack", "pdfcolorstackinit", "pdfcompresslevel", "pdfcopyfont", "pdfcreationdate", "pdfdecimaldigits", "pdfdest", "pdfdestmargin", "pdfdraftmode", "pdfeachlinedepth", "pdfeachlineheight", "pdfendlink", "pdfendthread", "pdffirstlineheight", "pdffontattr", "pdffontexpand", "pdffontname", "pdffontobjnum", "pdffontsize", "pdfgamma", "pdfgentounicode", "pdfglyphtounicode", "pdfhorigin", "pdfignoreddimen", "pdfimageapplygamma", "pdfimagegamma", "pdfimagehicolor", "pdfimageresolution", "pdfincludechars", "pdfinclusioncopyfonts", "pdfinclusionerrorlevel", "pdfinfo", "pdfinsertht", "pdflastannot", "pdflastlinedepth", "pdflastlink", "pdflastobj", "pdflastxform", "pdflastximage", "pdflastximagecolordepth", "pdflastximagepages", "pdflastxpos", "pdflastypos", "pdflinkmargin", "pdfliteral", "pdfmapfile", "pdfmapline", "pdfminorversion", "pdfnames", "pdfnoligatures", "pdfnormaldeviate", "pdfobj", "pdfobjcompresslevel", "pdfoptionpdfminorversion", "pdfoutline", "pdfoutput", "pdfpageattr", "pdfpagebox", "pdfpageheight", "pdfpageref", "pdfpageresources", "pdfpagesattr", "pdfpagewidth", "pdfpkmode", "pdfpkresolution", "pdfprimitive", "pdfprotrudechars", "pdfpxdimen", "pdfrandomseed", "pdfrefobj", "pdfrefxform", "pdfrefximage", "pdfreplacefont", "pdfrestore", "pdfretval", "pdfsave", "pdfsavepos", "pdfsetmatrix", "pdfsetrandomseed", "pdfstartlink", "pdfstartthread", "pdftexbanner", "pdftexrevision", "pdftexversion", "pdfthread", "pdfthreadmargin", "pdftracingfonts", "pdftrailer", "pdfuniformdeviate", "pdfuniqueresname", "pdfvorigin", "pdfxform", "pdfxformattr", "pdfxformname", "pdfxformresources", "pdfximage", "pdfximagebbox", "penalty", "postdisplaypenalty", "postexhyphenchar", "posthyphenchar", "predisplaydirection", "predisplaypenalty", "predisplaysize", "preexhyphenchar", "prehyphenchar", "pretolerance", "prevdepth", "prevgraf", "primitive", "protected", "quitvmode", "radical", "raise", "read", "readline", "relax", "relpenalty", "right", "rightghost", "righthyphenmin", "rightmarginkern", "rightskip", "romannumeral", "rpcode", "savecatcodetable", "savinghyphcodes", "savingvdiscards", "scantextokens", "scantokens", "scriptfont", "scriptscriptfont", "scriptscriptstyle", "scriptspace", "scriptstyle", "scrollmode", "setbox", "setlanguage", "sfcode", "shipout", "show", "showbox", "showboxbreadth", "showboxdepth", "showgroups", "showifs", "showlists", "showthe", "showtokens", "skewchar", "skip", "skipdef", "spacefactor", "spaceskip", "span", "special", "splitbotmark", "splitbotmarks", "splitdiscards", "splitfirstmark", "splitfirstmarks", "splitmaxdepth", "splittopskip", "string", "suppressfontnotfounderror", "suppressifcsnameerror", "suppresslongerror", "suppressoutererror", "synctex", "tabskip", "tagcode", "textdir", "textfont", "textstyle", "the", "thickmuskip", "thinmuskip", "time", "toks", "toksdef", "tolerance", "topmark", "topmarks", "topskip", "tracingassigns", "tracingcommands", "tracinggroups", "tracingifs", "tracinglostchars", "tracingmacros", "tracingnesting", "tracingonline", "tracingoutput", "tracingpages", "tracingparagraphs", "tracingrestores", "tracingscantokens", "tracingstats", "uccode", "uchyph", "underline", "unexpanded", "unhbox", "unhcopy", "unkern", "unless", "unpenalty", "unskip", "unvbox", "unvcopy", "uppercase", "vadjust", "valign", "vbadness", "vbox", "vcenter", "vfil", "vfill", "vfilneg", "vfuzz", "voffset", "vrule", "vsize", "vskip", "vsplit", "vss", "vtop", "wd", "widowpenalties", "widowpenalty", "write", "xdef", "xleaders", "xspaceskip", "year" },
+ ["tex"]={ "-", "/", "AlephVersion", "Alephminorversion", "Alephrevision", "Alephversion", "OmegaVersion", "Omegaminorversion", "Omegarevision", "Omegaversion", "Udelcode", "Udelcodenum", "Udelimiter", "Udelimiterover", "Udelimiterunder", "Umathaccent", "Umathaxis", "Umathbinbinspacing", "Umathbinclosespacing", "Umathbininnerspacing", "Umathbinopenspacing", "Umathbinopspacing", "Umathbinordspacing", "Umathbinpunctspacing", "Umathbinrelspacing", "Umathchar", "Umathchardef", "Umathcharnum", "Umathclosebinspacing", "Umathcloseclosespacing", "Umathcloseinnerspacing", "Umathcloseopenspacing", "Umathcloseopspacing", "Umathcloseordspacing", "Umathclosepunctspacing", "Umathcloserelspacing", "Umathcode", "Umathcodenum", "Umathconnectoroverlapmin", "Umathfractiondelsize", "Umathfractiondenomdown", "Umathfractiondenomvgap", "Umathfractionnumup", "Umathfractionnumvgap", "Umathfractionrule", "Umathinnerbinspacing", "Umathinnerclosespacing", "Umathinnerinnerspacing", "Umathinneropenspacing", "Umathinneropspacing", "Umathinnerordspacing", "Umathinnerpunctspacing", "Umathinnerrelspacing", "Umathlimitabovebgap", "Umathlimitabovekern", "Umathlimitabovevgap", "Umathlimitbelowbgap", "Umathlimitbelowkern", "Umathlimitbelowvgap", "Umathopbinspacing", "Umathopclosespacing", "Umathopenbinspacing", "Umathopenclosespacing", "Umathopeninnerspacing", "Umathopenopenspacing", "Umathopenopspacing", "Umathopenordspacing", "Umathopenpunctspacing", "Umathopenrelspacing", "Umathoperatorsize", "Umathopinnerspacing", "Umathopopenspacing", "Umathopopspacing", "Umathopordspacing", "Umathoppunctspacing", "Umathoprelspacing", "Umathordbinspacing", "Umathordclosespacing", "Umathordinnerspacing", "Umathordopenspacing", "Umathordopspacing", "Umathordordspacing", "Umathordpunctspacing", "Umathordrelspacing", "Umathoverbarkern", "Umathoverbarrule", "Umathoverbarvgap", "Umathoverdelimiterbgap", "Umathoverdelimitervgap", "Umathpunctbinspacing", "Umathpunctclosespacing", "Umathpunctinnerspacing", "Umathpunctopenspacing", "Umathpunctopspacing", "Umathpunctordspacing", "Umathpunctpunctspacing", "Umathpunctrelspacing", "Umathquad", "Umathradicaldegreeafter", "Umathradicaldegreebefore", "Umathradicaldegreeraise", "Umathradicalkern", "Umathradicalrule", "Umathradicalvgap", "Umathrelbinspacing", "Umathrelclosespacing", "Umathrelinnerspacing", "Umathrelopenspacing", "Umathrelopspacing", "Umathrelordspacing", "Umathrelpunctspacing", "Umathrelrelspacing", "Umathspaceafterscript", "Umathstackdenomdown", "Umathstacknumup", "Umathstackvgap", "Umathsubshiftdown", "Umathsubshiftdrop", "Umathsubsupshiftdown", "Umathsubsupvgap", "Umathsubtopmax", "Umathsupbottommin", "Umathsupshiftdrop", "Umathsupshiftup", "Umathsupsubbottommax", "Umathunderbarkern", "Umathunderbarrule", "Umathunderbarvgap", "Umathunderdelimiterbgap", "Umathunderdelimitervgap", "Uoverdelimiter", "Uradical", "Uroot", "Ustack", "Ustartdisplaymath", "Ustartmath", "Ustopdisplaymath", "Ustopmath", "Usubscript", "Usuperscript", "Uunderdelimiter", "above", "abovedisplayshortskip", "abovedisplayskip", "abovewithdelims", "accent", "adjdemerits", "advance", "afterassignment", "aftergroup", "alignmark", "aligntab", "atop", "atopwithdelims", "attribute", "attributedef", "badness", "baselineskip", "batchmode", "begingroup", "belowdisplayshortskip", "belowdisplayskip", "binoppenalty", "bodydir", "botmark", "botmarks", "box", "boxdir", "boxmaxdepth", "brokenpenalty", "catcode", "catcodetable", "char", "chardef", "chardp", "charht", "charit", "charwd", "cleaders", "clearmarks", "closein", "closeout", "clubpenalties", "clubpenalty", "copy", "count", "countdef", "cr", "crampeddisplaystyle", "crampedscriptscriptstyle", "crampedscriptstyle", "crampedtextstyle", "crcr", "csname", "currentgrouplevel", "currentgrouptype", "currentifbranch", "currentiflevel", "currentiftype", "day", "deadcycles", "def", "defaulthyphenchar", "defaultskewchar", "delcode", "delimiter", "delimiterfactor", "delimitershortfall", "detokenize", "dimen", "dimendef", "dimexpr", "directlua", "discretionary", "displayindent", "displaylimits", "displaystyle", "displaywidowpenalties", "displaywidowpenalty", "displaywidth", "divide", "doublehyphendemerits", "dp", "dump", "eTeXVersion", "eTeXminorversion", "eTeXrevision", "eTeXversion", "edef", "efcode", "else", "emergencystretch", "end", "endcsname", "endgroup", "endinput", "endlinechar", "eqno", "errhelp", "errmessage", "errorcontextlines", "errorstopmode", "escapechar", "everycr", "everydisplay", "everyeof", "everyhbox", "everyjob", "everymath", "everypar", "everyvbox", "exhyphenchar", "exhyphenpenalty", "expandafter", "expanded", "fam", "fi", "finalhyphendemerits", "firstmark", "firstmarks", "floatingpenalty", "font", "fontchardp", "fontcharht", "fontcharic", "fontcharwd", "fontdimen", "fontid", "fontname", "formatname", "futurelet", "gdef", "gleaders", "global", "globaldefs", "glueexpr", "glueshrink", "glueshrinkorder", "gluestretch", "gluestretchorder", "gluetomu", "halign", "hangafter", "hangindent", "hbadness", "hbox", "hfil", "hfill", "hfilneg", "hfuzz", "hoffset", "holdinginserts", "hrule", "hsize", "hskip", "hss", "ht", "hyphenation", "hyphenchar", "hyphenpenalty", "if", "ifabsdim", "ifabsnum", "ifcase", "ifcat", "ifcsname", "ifdefined", "ifdim", "ifeof", "iffalse", "iffontchar", "ifhbox", "ifhmode", "ifincsname", "ifinner", "ifmmode", "ifnum", "ifodd", "ifpdfabsdim", "ifpdfabsnum", "ifpdfprimitive", "ifprimitive", "iftrue", "ifvbox", "ifvmode", "ifvoid", "ifx", "ignorespaces", "immediate", "indent", "initcatcodetable", "input", "inputlineno", "insert", "insertpenalties", "interactionmode", "interlinepenalties", "interlinepenalty", "jobname", "kern", "language", "lastbox", "lastkern", "lastlinefit", "lastnodetype", "lastpenalty", "lastskip", "latelua", "lccode", "leaders", "left", "leftghost", "lefthyphenmin", "leftmarginkern", "leftskip", "leqno", "let", "letterspacefont", "limits", "linepenalty", "lineskip", "lineskiplimit", "localbrokenpenalty", "localinterlinepenalty", "localleftbox", "localrightbox", "long", "looseness", "lower", "lowercase", "lpcode", "luaescapestring", "luastartup", "luatexdatestamp", "luatexrevision", "luatexversion", "mag", "mark", "marks", "mathaccent", "mathbin", "mathchar", "mathchardef", "mathchoice", "mathclose", "mathcode", "mathdir", "mathinner", "mathop", "mathopen", "mathord", "mathpunct", "mathrel", "mathstyle", "mathsurround", "maxdeadcycles", "maxdepth", "meaning", "medmuskip", "message", "middle", "mkern", "month", "moveleft", "moveright", "mskip", "muexpr", "multiply", "muskip", "muskipdef", "mutoglue", "newlinechar", "noalign", "noboundary", "noexpand", "noindent", "nokerns", "noligs", "nolimits", "nolocaldirs", "nolocalwhatsits", "nonscript", "nonstopmode", "nulldelimiterspace", "nullfont", "number", "numexpr", "odelcode", "odelimiter", "omathaccent", "omathchar", "omathchardef", "omathcode", "omit", "openin", "openout", "or", "oradical", "outer", "output", "outputbox", "outputpenalty", "over", "overfullrule", "overline", "overwithdelims", "pagebottomoffset", "pagedepth", "pagedir", "pagediscards", "pagefilllstretch", "pagefillstretch", "pagefilstretch", "pagegoal", "pageheight", "pageleftoffset", "pagerightoffset", "pageshrink", "pagestretch", "pagetopoffset", "pagetotal", "pagewidth", "par", "pardir", "parfillskip", "parindent", "parshape", "parshapedimen", "parshapeindent", "parshapelength", "parskip", "patterns", "pausing", "pdfadjustspacing", "pdfannot", "pdfcatalog", "pdfcolorstack", "pdfcolorstackinit", "pdfcompresslevel", "pdfcopyfont", "pdfcreationdate", "pdfdecimaldigits", "pdfdest", "pdfdestmargin", "pdfdraftmode", "pdfeachlinedepth", "pdfeachlineheight", "pdfendlink", "pdfendthread", "pdffirstlineheight", "pdffontattr", "pdffontexpand", "pdffontname", "pdffontobjnum", "pdffontsize", "pdfgamma", "pdfgentounicode", "pdfglyphtounicode", "pdfhorigin", "pdfignoreddimen", "pdfimageapplygamma", "pdfimagegamma", "pdfimagehicolor", "pdfimageresolution", "pdfincludechars", "pdfinclusioncopyfonts", "pdfinclusionerrorlevel", "pdfinfo", "pdfinsertht", "pdflastannot", "pdflastlinedepth", "pdflastlink", "pdflastobj", "pdflastxform", "pdflastximage", "pdflastximagecolordepth", "pdflastximagepages", "pdflastxpos", "pdflastypos", "pdflinkmargin", "pdfliteral", "pdfmapfile", "pdfmapline", "pdfminorversion", "pdfnames", "pdfnoligatures", "pdfnormaldeviate", "pdfobj", "pdfobjcompresslevel", "pdfoptionpdfminorversion", "pdfoutline", "pdfoutput", "pdfpageattr", "pdfpagebox", "pdfpageheight", "pdfpageref", "pdfpageresources", "pdfpagesattr", "pdfpagewidth", "pdfpkmode", "pdfpkresolution", "pdfprimitive", "pdfprotrudechars", "pdfpxdimen", "pdfrandomseed", "pdfrefobj", "pdfrefxform", "pdfrefximage", "pdfreplacefont", "pdfrestore", "pdfretval", "pdfsave", "pdfsavepos", "pdfsetmatrix", "pdfsetrandomseed", "pdfstartlink", "pdfstartthread", "pdftexbanner", "pdftexrevision", "pdftexversion", "pdfthread", "pdfthreadmargin", "pdftracingfonts", "pdftrailer", "pdfuniformdeviate", "pdfuniqueresname", "pdfvorigin", "pdfxform", "pdfxformattr", "pdfxformname", "pdfxformresources", "pdfximage", "pdfximagebbox", "penalty", "postdisplaypenalty", "postexhyphenchar", "posthyphenchar", "predisplaydirection", "predisplaypenalty", "predisplaysize", "preexhyphenchar", "prehyphenchar", "pretolerance", "prevdepth", "prevgraf", "primitive", "protected", "quitvmode", "radical", "raise", "read", "readline", "relax", "relpenalty", "right", "rightghost", "righthyphenmin", "rightmarginkern", "rightskip", "romannumeral", "rpcode", "savecatcodetable", "savinghyphcodes", "savingvdiscards", "scantextokens", "scantokens", "scriptfont", "scriptscriptfont", "scriptscriptstyle", "scriptspace", "scriptstyle", "scrollmode", "setbox", "setlanguage", "sfcode", "shipout", "show", "showbox", "showboxbreadth", "showboxdepth", "showgroups", "showifs", "showlists", "showthe", "showtokens", "skewchar", "skip", "skipdef", "spacefactor", "spaceskip", "span", "special", "splitbotmark", "splitbotmarks", "splitdiscards", "splitfirstmark", "splitfirstmarks", "splitmaxdepth", "splittopskip", "string", "suppressfontnotfounderror", "suppressifcsnameerror", "suppresslongerror", "suppressoutererror", "synctex", "tabskip", "tagcode", "textdir", "textfont", "textstyle", "the", "thickmuskip", "thinmuskip", "time", "toks", "toksdef", "tolerance", "topmark", "topmarks", "topskip", "tracingassigns", "tracingcommands", "tracinggroups", "tracingifs", "tracinglostchars", "tracingmacros", "tracingnesting", "tracingonline", "tracingoutput", "tracingpages", "tracingparagraphs", "tracingrestores", "tracingscantokens", "tracingstats", "uccode", "uchyph", "underline", "unexpanded", "unhbox", "unhcopy", "unkern", "unless", "unpenalty", "unskip", "unvbox", "unvcopy", "uppercase", "vadjust", "valign", "vbadness", "vbox", "vcenter", "vfil", "vfill", "vfilneg", "vfuzz", "voffset", "vrule", "vsize", "vskip", "vsplit", "vss", "vtop", "wd", "widowpenalties", "widowpenalty", "write", "xdef", "xleaders", "xspaceskip", "year" },
["xetex"]={ "XeTeXversion" },
}
\ No newline at end of file
diff --git a/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-cld.lua b/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-cld.lua
index 4aa2901d232..1e30c18a287 100644
--- a/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-cld.lua
+++ b/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-cld.lua
@@ -7,7 +7,6 @@ local info = {
}
local lexer = lexer
-local token = lexer.token
local cldlexer = { _NAME = "cld", _FILENAME = "scite-context-lexer-cld" }
local whitespace = lexer.WHITESPACE -- maybe we need to fix this
diff --git a/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-lua-longstring.lua b/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-lua-longstring.lua
index 26bdb8dbccb..fdec301bef2 100644
--- a/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-lua-longstring.lua
+++ b/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-lua-longstring.lua
@@ -1,3 +1,11 @@
+local info = {
+ version = 1.002,
+ comment = "scintilla lpeg lexer for lua",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+}
+
local lexer = lexer
local token = lexer.token
local P = lpeg.P
diff --git a/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-lua.lua b/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-lua.lua
index 0ace7afc6ff..9672e110e4f 100644
--- a/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-lua.lua
+++ b/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-lua.lua
@@ -6,6 +6,8 @@ local info = {
license = "see context related readme files",
}
+-- todo: _G.print (keep _G colored)
+
if not lexer._CONTEXTEXTENSIONS then require("scite-context-lexer") end
local lexer = lexer
@@ -34,18 +36,32 @@ local keywords = {
}
local functions = {
- 'assert', 'collectgarbage', 'dofile', 'error', 'getfenv', 'getmetatable',
- 'ipairs', 'load', 'loadfile', 'loadstring', 'module', 'next', 'pairs',
- 'pcall', 'print', 'rawequal', 'rawget', 'rawset', 'require', 'setfenv',
- 'setmetatable', 'tonumber', 'tostring', 'type', 'unpack', 'xpcall', "select",
+ 'assert', 'collectgarbage', 'dofile', 'error', 'getmetatable',
+ 'ipairs', 'load', 'loadfile', 'module', 'next', 'pairs',
+ 'pcall', 'print', 'rawequal', 'rawget', 'rawset', 'require',
+ 'setmetatable', 'tonumber', 'tostring', 'type', 'unpack', 'xpcall', 'select',
+
+ "string", "table", "coroutine", "debug", "file", "io", "lpeg", "math", "os", "package", "bit32",
}
local constants = {
- '_G', '_VERSION', '_M', "...",
+ '_G', '_VERSION', '_M', '...', '_ENV',
+ -- here too
+ '__add', '__call', '__concat', '__div', '__eq', '__gc', '__index',
+ '__le', '__lt', '__metatable', '__mode', '__mul', '__newindex',
+ '__pow', '__sub', '__tostring', '__unm',
+}
+
+local internals = { -- __
+ 'add', 'call', 'concat', 'div', 'eq', 'gc', 'index',
+ 'le', 'lt', 'metatable', 'mode', 'mul', 'newindex',
+ 'pow', 'sub', 'tostring', 'unm',
}
local depricated = {
"arg", "arg.n",
+ "loadstring", "setfenv", "getfenv",
+ "pack",
}
local csnames = { -- todo: option
@@ -147,7 +163,7 @@ local operator = token("special", S('+-*/%^#=<>;:,{}[]().') + P('~=') ) --
local structure = token("special", S('{}[]()'))
local optionalspace = spacing^0
-local hasargument = #S("{(")
+local hasargument = #S("{([")
local gotokeyword = token("keyword", P("goto"))
* spacing
@@ -156,14 +172,28 @@ local gotolabel = token("keyword", P("::"))
* token("grouping",validword)
* token("keyword", P("::"))
-local keyword = token("keyword", exact_match(keywords ))
-local builtin = token("plain", exact_match(functions))
-local constant = token("data", exact_match(constants))
-local csname = token("user", exact_match(csnames ))
+local p_keywords = exact_match(keywords)
+local p_functions = exact_match(functions)
+local p_constants = exact_match(constants)
+local p_internals = P("__")
+ * exact_match(internals)
+local p_csnames = exact_match(csnames)
+
+local keyword = token("keyword", p_keywords)
+local builtin = token("plain", p_functions)
+local constant = token("data", p_constants)
+local internal = token("data", p_internals)
+local csname = token("user", p_csnames)
* (
optionalspace * hasargument
- + ( optionalspace * token("special", P(".")) * optionalspace * token("user", validword) )^1
+ + ( optionalspace * token("special", S(".:")) * optionalspace * token("user", validword) )^1
)
+local identifier = token("default", validword)
+ * ( optionalspace * token("special", S(".:")) * optionalspace * (
+ token("warning", p_keywords) +
+ token("data", p_internals) +
+ token("default", validword )
+ ) )^0
lualexer._rules = {
{ 'whitespace', spacing },
@@ -178,36 +208,83 @@ lualexer._rules = {
{ 'number', number },
{ 'longcomment', longcomment },
{ 'shortcomment', shortcomment },
--- { 'number', number },
{ 'label', gotolabel },
{ 'operator', operator },
{ 'rest', rest },
}
+-- -- experiment
+--
+-- local idtoken = R("az","AZ","__")
+--
+-- function context.one_of_match(specification)
+-- local pattern = idtoken -- the concat catches _ etc
+-- local list = { }
+-- for i=1,#specification do
+-- local style = specification[i][1]
+-- local words = specification[i][2]
+-- pattern = pattern + S(table.concat(words))
+-- for i=1,#words do
+-- list[words[i]] = style
+-- end
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- local style = list[s]
+-- if style then
+-- return true, { style, i } -- and i or nil
+-- else
+-- -- fail
+-- end
+-- end)
+-- end
+--
+-- local whatever = context.one_of_match {
+-- { "keyword", keywords }, -- keyword
+-- { "plain", functions }, -- builtin
+-- { "data", constants }, -- constant
+-- }
+--
+-- lualexer._rules = {
+-- { 'whitespace', spacing },
+-- { 'whatever', whatever },
+-- { 'csname', csname },
+-- { 'goto', gotokeyword },
+-- { 'identifier', identifier },
+-- { 'string', string },
+-- { 'number', number },
+-- { 'longcomment', longcomment },
+-- { 'shortcomment', shortcomment },
+-- { 'label', gotolabel },
+-- { 'operator', operator },
+-- { 'rest', rest },
+-- }
+
lualexer._tokenstyles = context.styleset
+-- lualexer._foldpattern = R("az")^2 + S("{}[]") -- separate entry else interference
+
+lualexer._foldpattern = (P("end") + P("if") + P("do") + P("function") + P("repeat") + P("until")) * P(#(1 - R("az")))
+ + S("{}[]")
+
lualexer._foldsymbols = {
_patterns = {
- -- '%l+', -- costly
- -- '%l%l+',
'[a-z][a-z]+',
- -- '[%({%)}%[%]]',
'[{}%[%]]',
},
['keyword'] = { -- challenge: if=0 then=1 else=-1 elseif=-1
- ['if'] = 1,
- ['end'] = -1,
- ['do'] = 1,
- ['function'] = 1,
- ['repeat'] = 1,
+ ['if'] = 1, -- if .. [then|else] .. end
+ ['do'] = 1, -- [while] do .. end
+ ['function'] = 1, -- function .. end
+ ['repeat'] = 1, -- repeat .. until
['until'] = -1,
+ ['end'] = -1,
},
['comment'] = {
['['] = 1, [']'] = -1,
},
- ['quote'] = { -- to be tested
- ['['] = 1, [']'] = -1,
- },
+ -- ['quote'] = { -- confusing
+ -- ['['] = 1, [']'] = -1,
+ -- },
['special'] = {
-- ['('] = 1, [')'] = -1,
['{'] = 1, ['}'] = -1,
diff --git a/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-mps.lua b/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-mps.lua
index 1a2a2571d4c..96c5e9c3cb9 100644
--- a/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-mps.lua
+++ b/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-mps.lua
@@ -70,6 +70,9 @@ local any = lexer.any
local dquote = P('"')
local cstoken = R("az","AZ") + P("_")
+local mptoken = R("az","AZ")
+local leftbrace = P("{")
+local rightbrace = P("}")
local number = context.patterns.real
local cstokentex = R("az","AZ","\127\255") + S("@!?_")
@@ -97,6 +100,14 @@ local special = token('special', S("#()[]{}<>=:\"")) -- or else := <> etc s
local texlike = token('warning', P("\\") * cstokentex^1)
local extra = token('extra', S("`~%^&_-+*/\'|\\"))
+local nested = P { leftbrace * (V(1) + (1-rightbrace))^0 * rightbrace }
+local texlike = token('embedded', P("\\") * (P("MP") + P("mp")) * mptoken^1)
+ * spacing^0
+ * token('grouping', leftbrace)
+ * token('rest', (nested + (1-rightbrace))^0 )
+ * token('grouping', rightbrace)
+ + token('warning', P("\\") * cstokentex^1)
+
metafunlexer._rules = {
{ 'whitespace', spacing },
{ 'comment', comment },
@@ -118,9 +129,11 @@ metafunlexer._rules = {
metafunlexer._tokenstyles = context.styleset
+metafunlexer._foldpattern = R("az")^2 -- separate entry else interference
+
metafunlexer._foldsymbols = {
_patterns = {
- "%l+",
+ '[a-z][a-z]+',
},
["primitive"] = {
["beginfig"] = 1,
diff --git a/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-tex.lua b/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-tex.lua
index 1ff68750fb2..e39ca2baaf2 100644
--- a/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-tex.lua
+++ b/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-tex.lua
@@ -59,6 +59,8 @@ local constants = { }
do -- todo: only once, store in global
+ -- commands helpers primitives
+
local definitions = context.loaddefinitions("scite-context-data-interfaces")
if definitions then
@@ -80,10 +82,17 @@ do -- todo: only once, store in global
end
local definitions = context.loaddefinitions("scite-context-data-context")
+ local overloaded = { }
if definitions then
helpers = definitions.helpers or { }
constants = definitions.constants or { }
+ for i=1,#helpers do
+ overloaded[helpers[i]] = true
+ end
+ for i=1,#constants do
+ overloaded[constants[i]] = true
+ end
end
local definitions = context.loaddefinitions("scite-context-data-tex")
@@ -92,20 +101,25 @@ do -- todo: only once, store in global
local function add(data,normal)
for k, v in next, data do
if v ~= "/" and v ~= "-" then
- primitives[#primitives+1] = v
+ if not overloaded[v] then
+ primitives[#primitives+1] = v
+ end
if normal then
- primitives[#primitives+1] = "normal" .. v
+ v = "normal" .. v
+ if not overloaded[v] then
+ primitives[#primitives+1] = v
+ end
end
end
end
end
add(definitions.tex,true)
- add(definitions.etex)
- add(definitions.pdftex)
- add(definitions.aleph)
- add(definitions.omega)
- add(definitions.luatex)
- add(definitions.xetex)
+ add(definitions.etex,true)
+ add(definitions.pdftex,true)
+ add(definitions.aleph,true)
+ add(definitions.omega,true)
+ add(definitions.luatex,true)
+ add(definitions.xetex,true)
end
end
@@ -128,12 +142,13 @@ local checkedword = context.checkedword
local styleofword = context.styleofword
local setwordlist = context.setwordlist
local validwords = false
+local validminimum = 3
-- % language=uk
local knownpreamble = Cmt(#P("% "), function(input,i,_) -- todo : utfbomb
if i < 10 then
- validwords = false
+ validwords, validminimum = false, 3
local s, e, word = find(input,'^(.+)[\n\r]',i) -- combine with match
if word then
local interface = match(word,"interface=([a-z]+)")
@@ -141,7 +156,7 @@ local knownpreamble = Cmt(#P("% "), function(input,i,_) -- todo : utfbomb
currentcommands = commands[interface] or commands.en or { }
end
local language = match(word,"language=([a-z]+)")
- validwords = language and setwordlist(language)
+ validwords, validminimum = setwordlist(language)
end
end
return false
@@ -224,15 +239,17 @@ local p_unit = P("pt") + P("bp") + P("sp") + P("mm") + P("cm") +
--
-- local p_word = Cmt(iwordpattern, function(_,i,s)
-- if validwords then
--- return checkedword(validwords,s,i)
+-- return checkedword(validwords,validminimum,s,i)
-- else
--- return true, { "text", i }
+-- -- return true, { "text", i }
+-- return true, "text", i
-- end
-- end)
--
-- So we use this one instead:
-local p_word = Ct( iwordpattern / function(s) return styleofword(validwords,s) end * Cp() ) -- the function can be inlined
+----- p_word = Ct( iwordpattern / function(s) return styleofword(validwords,validminimum,s) end * Cp() ) -- the function can be inlined
+local p_word = iwordpattern / function(s) return styleofword(validwords,validminimum,s) end * Cp() -- the function can be inlined
----- p_text = (1 - p_grouping - p_special - p_extra - backslash - space + hspace)^1
@@ -343,7 +360,7 @@ local function stopinlinelua_b(_,i,s) -- {
if luastatus == "display" then
return false
elseif luastatus == "inline" then
- lualevel = lualevel + 1
+ lualevel = lualevel + 1 -- ?
return false
else
return true
@@ -372,15 +389,17 @@ contextlexer._reset_parser = function()
lualevel = 0
end
-local luaenvironment = P("luacode")
+local luaenvironment = P("lua") * (P("setups") + P("code") + P(true))
local inlinelua = P("\\") * (
P("ctx") * ( P("lua") + P("command") + P("late") * (P("lua") + P("command")) )
+ P("cld") * ( P("command") + P("context") )
+ + P("luaexpr")
+ + (P("direct") + P("late")) * P("lua")
)
local startlua = P("\\start") * Cmt(luaenvironment,startdisplaylua)
- + inlinelua * space^0 * Cmt(P("{"),startinlinelua)
+ + inlinelua * space^0 * ( Cmt(P("{"),startinlinelua) )
local stoplua = P("\\stop") * Cmt(luaenvironment,stopdisplaylua)
+ Cmt(P("{"),stopinlinelua_b)
@@ -389,7 +408,8 @@ local stoplua = P("\\stop") * Cmt(luaenvironment,stopdisplaylua)
local startluacode = token("embedded", startlua)
local stopluacode = #stoplua * token("embedded", stoplua)
-local metafuncall = ( P("reusable") + P("usable") + P("unique") + P("use") ) * ("MPgraphic")
+local metafuncall = ( P("reusable") + P("usable") + P("unique") + P("use") + P("reuse") ) * ("MPgraphic")
+ + P("uniqueMPpagegraphic")
local metafunenvironment = metafuncall -- ( P("use") + P("reusable") + P("unique") ) * ("MPgraphic")
+ P("MP") * ( P("code")+ P("page") + P("inclusions") + P("initializations") + P("definitions") + P("extensions") + P("graphic") )
@@ -443,22 +463,33 @@ contextlexer._tokenstyles = context.styleset
-- contextlexer._tokenstyles[#contextlexer._tokenstyles + 1] = { cldlexer._NAME..'_whitespace', lexer.style_whitespace }
-- contextlexer._tokenstyles[#contextlexer._tokenstyles + 1] = { mpslexer._NAME..'_whitespace', lexer.style_whitespace }
+local environment = {
+ ["\\start"] = 1, ["\\stop"] = -1,
+ -- ["\\begin"] = 1, ["\\end" ] = -1,
+}
+
+-- local block = {
+-- ["\\begin"] = 1, ["\\end" ] = -1,
+-- }
-local folds = {
- ["\\start"] = 1, ["\\stop" ] = -1,
- ["\\begin"] = 1, ["\\end" ] = -1,
+local group = {
+ ["{"] = 1, ["}"] = -1,
}
-contextlexer._foldsymbols = {
+contextlexer._foldpattern = P("\\" ) * (P("start") + P("stop")) + S("{}") -- separate entry else interference
+
+contextlexer._foldsymbols = { -- these need to be style references
_patterns = {
"\\start", "\\stop", -- regular environments
- "\\begin", "\\end", -- (moveable) blocks
+ -- "\\begin", "\\end", -- (moveable) blocks
+ "[{}]",
},
- ["helper"] = folds,
- ["data"] = folds,
- ["command"] = folds,
- ["user"] = folds, -- csname
- ["grouping"] = folds,
+ ["command"] = environment,
+ ["constant"] = environment,
+ ["data"] = environment,
+ ["user"] = environment,
+ ["embedded"] = environment,
+ ["grouping"] = group,
}
return contextlexer
diff --git a/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-txt.lua b/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-txt.lua
index 012167aeb4c..fe062fb94e5 100644
--- a/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-txt.lua
+++ b/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-txt.lua
@@ -13,19 +13,20 @@ local token = lexer.token
local P, S, Cmt, Cp, Ct = lpeg.P, lpeg.S, lpeg.Cmt, lpeg.Cp, lpeg.Ct
local find, match = string.find, string.match
-local textlexer = { _NAME = "txt", _FILENAME = "scite-context-lexer-txt" }
-local whitespace = lexer.WHITESPACE
-local context = lexer.context
+local textlexer = { _NAME = "txt", _FILENAME = "scite-context-lexer-txt" }
+local whitespace = lexer.WHITESPACE
+local context = lexer.context
-local space = lexer.space
-local any = lexer.any
+local space = lexer.space
+local any = lexer.any
-local wordtoken = context.patterns.wordtoken
-local wordpattern = context.patterns.wordpattern
-local checkedword = context.checkedword
-local styleofword = context.styleofword
-local setwordlist = context.setwordlist
-local validwords = false
+local wordtoken = context.patterns.wordtoken
+local wordpattern = context.patterns.wordpattern
+local checkedword = context.checkedword
+local styleofword = context.styleofword
+local setwordlist = context.setwordlist
+local validwords = false
+local validminimum = 3
-- local styleset = context.newstyleset {
-- "default",
@@ -37,12 +38,12 @@ local validwords = false
local p_preamble = Cmt(#(S("#!-%") * P(" ")), function(input,i,_) -- todo: utf bomb
if i == 1 then -- < 10 then
- validwords = false
+ validwords, validminimum = false, 3
local s, e, line = find(input,'^[#!%-%%](.+)[\n\r]',i)
if line then
local language = match(line,"language=([a-z]+)")
if language then
- validwords = setwordlist(language)
+ validwords, validminimum = setwordlist(language)
end
end
end
@@ -52,17 +53,9 @@ end)
local t_preamble =
token("preamble", p_preamble)
--- local t_word =
--- Cmt(wordpattern, function(_,i,s)
--- if validwords then
--- return checkedword(validwords,s,i)
--- else
--- return true, { "text", i }
--- end
--- end)
-
local t_word =
- Ct( wordpattern / function(s) return styleofword(validwords,s) end * Cp() ) -- the function can be inlined
+-- Ct( wordpattern / function(s) return styleofword(validwords,validminimum,s) end * Cp() ) -- the function can be inlined
+ wordpattern / function(s) return styleofword(validwords,validminimum,s) end * Cp() -- the function can be inlined
local t_text =
token("default", wordtoken^1)
@@ -81,6 +74,7 @@ textlexer._rules = {
{ "rest", t_rest },
}
+textlexer._LEXBYLINE = true -- new (needs testing, not yet as the system changed in 3.24)
textlexer._tokenstyles = context.styleset
return textlexer
diff --git a/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-web.lua b/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-web.lua
new file mode 100644
index 00000000000..f59a3205dd8
--- /dev/null
+++ b/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-web.lua
@@ -0,0 +1,155 @@
+local info = {
+ version = 1.002,
+ comment = "scintilla lpeg lexer for w",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+}
+
+-- this will be extended
+
+if not lexer._CONTEXTEXTENSIONS then require("scite-context-lexer") end
+
+local lexer = lexer
+local token, style, colors, exact_match, no_style = lexer.token, lexer.style, lexer.colors, lexer.exact_match, lexer.style_nothing
+local P, R, S, C, Cg, Cb, Cs, Cmt, lpegmatch = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Cg, lpeg.Cb, lpeg.Cs, lpeg.Cmt, lpeg.match
+local setmetatable = setmetatable
+
+local weblexer = { _NAME = "web", _FILENAME = "scite-context-lexer-web" }
+local whitespace = lexer.WHITESPACE
+local context = lexer.context
+
+local keywords = { -- copied from cpp.lua
+ -- c
+ 'asm', 'auto', 'break', 'case', 'const', 'continue', 'default', 'do', 'else',
+ 'extern', 'false', 'for', 'goto', 'if', 'inline', 'register', 'return',
+ 'sizeof', 'static', 'switch', 'true', 'typedef', 'volatile', 'while',
+ 'restrict',
+ -- hm
+ '_Bool', '_Complex', '_Pragma', '_Imaginary',
+ -- c++.
+ 'catch', 'class', 'const_cast', 'delete', 'dynamic_cast', 'explicit',
+ 'export', 'friend', 'mutable', 'namespace', 'new', 'operator', 'private',
+ 'protected', 'public', 'signals', 'slots', 'reinterpret_cast',
+ 'static_assert', 'static_cast', 'template', 'this', 'throw', 'try', 'typeid',
+ 'typename', 'using', 'virtual'
+}
+
+local datatypes = { -- copied from cpp.lua
+ 'bool', 'char', 'double', 'enum', 'float', 'int', 'long', 'short', 'signed',
+ 'struct', 'union', 'unsigned', 'void'
+}
+
+local macros = { -- copied from cpp.lua
+ 'define', 'elif', 'else', 'endif', 'error', 'if', 'ifdef', 'ifndef', 'import',
+ 'include', 'line', 'pragma', 'undef', 'using', 'warning'
+}
+
+local space = lexer.space -- S(" \n\r\t\f\v")
+local any = lexer.any
+local patterns = context.patterns
+local restofline = patterns.restofline
+local startofline = patterns.startofline
+
+local squote = P("'")
+local dquote = P('"')
+local escaped = P("\\") * P(1)
+local slashes = P('//')
+local begincomment = P("/*")
+local endcomment = P("*/")
+local percent = P("%")
+
+local spacing = token(whitespace, space^1)
+local rest = token("default", any)
+
+local shortcomment = token("comment", slashes * restofline^0)
+local longcomment = token("comment", begincomment * (1-endcomment)^0 * endcomment^-1)
+local texcomment = token("comment", percent * restofline^0)
+
+local shortstring = token("quote", dquote) -- can be shared
+ * token("string", (escaped + (1-dquote))^0)
+ * token("quote", dquote)
+ + token("quote", squote)
+ * token("string", (escaped + (1-squote))^0)
+ * token("quote", squote)
+
+local integer = P("-")^-1 * (lexer.hex_num + lexer.dec_num)
+local number = token("number", lexer.float + integer)
+
+local validword = R("AZ","az","__") * R("AZ","az","__","09")^0
+
+local identifier = token("default",validword)
+
+local operator = token("special", S('+-*/%^!=<>;:{}[]().&|?~'))
+
+----- optionalspace = spacing^0
+
+local p_keywords = exact_match(keywords )
+local p_datatypes = exact_match(datatypes)
+local p_macros = exact_match(macros)
+
+local keyword = token("keyword", p_keywords)
+local datatype = token("keyword", p_datatypes)
+local identifier = token("default", validword)
+
+local macro = token("data", #P('#') * startofline * P('#') * S('\t ')^0 * p_macros)
+
+local beginweb = P("@")
+local endweb = P("@c")
+
+local webcomment = token("comment", #beginweb * startofline * beginweb * (1-endweb)^0 * endweb)
+
+local texlexer = lexer.load('scite-context-lexer-tex')
+
+lexer.embed_lexer(weblexer, texlexer, #beginweb * startofline * token("comment",beginweb), token("comment",endweb))
+
+weblexer._rules = {
+ { 'whitespace', spacing },
+ { 'keyword', keyword },
+ { 'type', datatype },
+ { 'identifier', identifier },
+ { 'string', shortstring },
+ -- { 'webcomment', webcomment },
+ { 'texcomment', texcomment },
+ { 'longcomment', longcomment },
+ { 'shortcomment', shortcomment },
+ { 'number', number },
+ { 'macro', macro },
+ { 'operator', operator },
+ { 'rest', rest },
+}
+
+weblexer._tokenstyles = context.styleset
+
+weblexer._foldpattern = P("/*") + P("*/") + S("{}") -- separate entry else interference
+
+weblexer._foldsymbols = {
+ _patterns = {
+ '[{}]',
+ '/%*',
+ '%*/',
+ },
+ -- ["data"] = { -- macro
+ -- ['region'] = 1,
+ -- ['endregion'] = -1,
+ -- ['if'] = 1,
+ -- ['ifdef'] = 1,
+ -- ['ifndef'] = 1,
+ -- ['endif'] = -1,
+ -- },
+ ["special"] = { -- operator
+ ['{'] = 1,
+ ['}'] = -1,
+ },
+ ["comment"] = {
+ ['/*'] = 1,
+ ['*/'] = -1,
+ }
+}
+
+-- -- by indentation:
+--
+weblexer._foldpatterns = nil
+weblexer._foldsymbols = nil
+
+return weblexer
diff --git a/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-xml-comment.lua b/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-xml-comment.lua
index eab3b2a61c8..104310f9417 100644
--- a/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-xml-comment.lua
+++ b/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-xml-comment.lua
@@ -27,12 +27,15 @@ xmlcommentlexer._rules = {
xmlcommentlexer._tokenstyles = context.styleset
+xmlcommentlexer._foldpattern = P("")
+
xmlcommentlexer._foldsymbols = {
_patterns = {
"<%!%-%-", "%-%->", -- comments
},
["comment"] = {
- ["" ] = -1,
+ ["" ] = -1,
}
}
diff --git a/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-xml-script.lua b/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-xml-script.lua
new file mode 100644
index 00000000000..fd1aae7f70c
--- /dev/null
+++ b/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-xml-script.lua
@@ -0,0 +1,30 @@
+local info = {
+ version = 1.002,
+ comment = "scintilla lpeg lexer for xml cdata",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+}
+
+local lexer = lexer
+local token = lexer.token
+local P = lpeg.P
+
+local xmlscriptlexer = { _NAME = "xml-script", _FILENAME = "scite-context-lexer-xml-script" }
+local whitespace = lexer.WHITESPACE -- triggers states
+local context = lexer.context
+
+local space = lexer.space
+local nospace = 1 - space - (P("") * P("script") + P("SCRIPT")) * P(">")
+
+local p_spaces = token(whitespace, space ^1)
+local p_cdata = token("default", nospace^1)
+
+xmlscriptlexer._rules = {
+ { "whitespace", p_spaces },
+ { "script", p_cdata },
+}
+
+xmlscriptlexer._tokenstyles = context.styleset
+
+return xmlscriptlexer
diff --git a/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-xml.lua b/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-xml.lua
index 34636127fc7..241e2259123 100644
--- a/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-xml.lua
+++ b/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-xml.lua
@@ -1,6 +1,6 @@
local info = {
version = 1.002,
- comment = "scintilla lpeg lexer for metafun",
+ comment = "scintilla lpeg lexer for xml",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
copyright = "PRAGMA ADE / ConTeXt Development Team",
license = "see context related readme files",
@@ -27,6 +27,8 @@ local context = lexer.context
local xmlcommentlexer = lexer.load("scite-context-lexer-xml-comment") -- indirect (some issue with the lexer framework)
local xmlcdatalexer = lexer.load("scite-context-lexer-xml-cdata") -- indirect (some issue with the lexer framework)
+local xmlscriptlexer = lexer.load("scite-context-lexer-xml-script") -- indirect (some issue with the lexer framework)
+local lualexer = lexer.load("scite-context-lexer-lua") --
local space = lexer.space -- S(" \t\n\r\v\f")
local any = lexer.any -- P(1)
@@ -51,6 +53,11 @@ local opencdata = P("")
local opendoctype = P("") + P(">")
+local openscript = openbegin * (P("script") + P("SCRIPT")) * (1-closeend)^0 * closeend -- begin
+local closescript = openend * (P("script") + P("SCRIPT")) * closeend
+
+local openlua = ""
--
--
@@ -71,7 +78,7 @@ local checkedword = context.checkedword
local styleofword = context.styleofword
local setwordlist = context.setwordlist
local validwords = false
-
+local validminimum = 3
--
--
@@ -79,29 +86,21 @@ local validwords = false
local p_preamble = Cmt(#P("]*%?>%s*<%?context%-directive%s+editor%s+language%s+(..)%s+%?>")
-- if not language then
-- language = match(input,'^<%?xml[^>]*language=[\"\'](..)[\"\'][^>]*%?>',i)
-- end
if language then
- validwords = setwordlist(language)
+ validwords, validminimum = setwordlist(language)
end
end
return false
end)
--- local p_word =
--- Cmt(iwordpattern, function(_,i,s)
--- if validwords then
--- return checkedword(validwords,s,i)
--- else
--- return true, { "text", i } -- or default
--- end
--- end)
-
local p_word =
- Ct( iwordpattern / function(s) return styleofword(validwords,s) end * Cp() ) -- the function can be inlined
+-- Ct( iwordpattern / function(s) return styleofword(validwords,validminimum,s) end * Cp() ) -- the function can be inlined
+ iwordpattern / function(s) return styleofword(validwords,validminimum,s) end * Cp() -- the function can be inlined
local p_rest =
token("default", any)
@@ -227,8 +226,10 @@ local p_doctype = token("command",P(""))
-lexer.embed_lexer(xmllexer, xmlcommentlexer, token("command",opencomment), token("command",closecomment))
-lexer.embed_lexer(xmllexer, xmlcdatalexer, token("command",opencdata), token("command",closecdata))
+lexer.embed_lexer(xmllexer, lualexer, token("command", openlua), token("command", closelua))
+lexer.embed_lexer(xmllexer, xmlcommentlexer, token("command", opencomment), token("command", closecomment))
+lexer.embed_lexer(xmllexer, xmlcdatalexer, token("command", opencdata), token("command", closecdata))
+lexer.embed_lexer(xmllexer, xmlscriptlexer, token("command", openscript), token("command", closescript))
-- local p_name =
-- token("plain",name)
@@ -308,9 +309,9 @@ xmllexer._rules = {
{ "whitespace", p_spacing },
{ "preamble", p_preamble },
{ "word", p_word },
--- { "text", p_text },
--- { "comment", p_comment },
--- { "cdata", p_cdata },
+ -- { "text", p_text },
+ -- { "comment", p_comment },
+ -- { "cdata", p_cdata },
{ "doctype", p_doctype },
{ "instruction", p_instruction },
{ "close", p_close },
@@ -322,12 +323,18 @@ xmllexer._rules = {
xmllexer._tokenstyles = context.styleset
+xmllexer._foldpattern = P("") + P("<") + P("/>") -- separate entry else interference
+
xmllexer._foldsymbols = { -- somehow doesn't work yet
_patterns = {
- "[<>]",
+ "",
+ "/>",
+ "<",
},
["keyword"] = {
- ["<"] = 1, [">"] = -1,
+ [""] = -1,
+ ["/>"] = -1,
+ ["<"] = 1,
},
}
diff --git a/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer.lua b/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer.lua
index 2db37e26b41..7883177b41e 100644
--- a/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer.lua
+++ b/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer.lua
@@ -1,5 +1,5 @@
local info = {
- version = 1.002,
+ version = 1.324,
comment = "basics for scintilla lpeg lexer for context/metafun",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
copyright = "PRAGMA ADE / ConTeXt Development Team",
@@ -8,9 +8,26 @@ local info = {
}
+-- todo: move all code here
+-- todo: explore adapted dll ... properties + init
+
-- The fold and lex functions are copied and patched from original code by Mitchell (see
-- lexer.lua). All errors are mine.
--
+-- Starting with SciTE version 3.20 there is an issue with coloring. As we still lack
+-- a connection with scite itself (properties as well as printing to the log pane) we
+-- cannot trace this (on windows). As far as I can see, there are no fundamental
+-- changes in lexer.lua or LexLPeg.cxx so it must be in scintilla itself. So for the
+-- moment I stick to 3.10. Indicators are: no lexing of 'next' and 'goto ' in the
+-- Lua lexer and no brace highlighting either. Interesting is that it does work ok in
+-- the cld lexer (so the Lua code is okay). Also the fact that char-def.lua lexes fast
+-- is a signal that the lexer quits somewhere halfway.
+--
+-- After checking 3.24 and adapting to the new lexer tables things are okay again. So,
+-- this version assumes 3.24 or higher. In 3.24 we have a different token result, i.e. no
+-- longer a { tag, pattern } but just two return values. I didn't check other changes but
+-- will do that when I run into issues.
+--
-- I've considered making a whole copy and patch the other functions too as we need
-- an extra nesting model. However, I don't want to maintain too much. An unfortunate
-- change in 3.03 is that no longer a script can be specified. This means that instead
@@ -29,7 +46,8 @@ local info = {
-- and the cursor is at the last line of a 200K line file. Optimizing the fold function
-- brought down loading of char-def.lua from 14 sec => 8 sec. Replacing the word_match
-- function and optimizing the lex function gained another 2+ seconds. A 6 second load
--- is quite ok for me.
+-- is quite ok for me. The changed lexer table structure (no subtables) brings loading
+-- down to a few seconds.
--
-- When the lexer path is copied to the textadept lexer path, and the theme definition to
-- theme path (as lexer.lua), the lexer works there as well. When I have time and motive
@@ -52,7 +70,7 @@ local info = {
--
-- Eventually it might be safer to copy the other methods from lexer.lua here as well so
-- that we have no dependencies, apart from the c library (for which at some point the api
--- will be stable I guess).
+-- will be stable I hope).
--
-- It's a pitty that there is no scintillua library for the OSX version of scite. Even
-- better would be to have the scintillua library as integral part of scite as that way I
@@ -64,7 +82,7 @@ local info = {
local lpeg = require 'lpeg'
-local R, P, S, C, V, Cp, Cs, Ct, Cmt, Cc, Cf, Cg = lpeg.R, lpeg.P, lpeg.S, lpeg.C, lpeg.V, lpeg.Cp, lpeg.Cs, lpeg.Ct, lpeg.Cmt, lpeg.Cc, lpeg.Cf, lpeg.Cg
+local R, P, S, C, V, Cp, Cs, Ct, Cmt, Cc, Cf, Cg, Carg = lpeg.R, lpeg.P, lpeg.S, lpeg.C, lpeg.V, lpeg.Cp, lpeg.Cs, lpeg.Ct, lpeg.Cmt, lpeg.Cc, lpeg.Cf, lpeg.Cg, lpeg.Carg
local lpegmatch = lpeg.match
local find, gmatch, match, lower, upper, gsub = string.find, string.gmatch, string.match, string.lower, string.upper, string.gsub
local concat = table.concat
@@ -173,6 +191,12 @@ patterns.spacing = space^1
patterns.nospacing = (1-space)^1
patterns.anything = P(1)
+local endof = S("\n\r\f")
+
+patterns.startofline = P(function(input,index)
+ return (index == 1 or lpegmatch(endof,input,index-1)) and index
+end)
+
function context.exact_match(words,word_chars,case_insensitive)
local characters = concat(words)
local pattern -- the concat catches _ etc
@@ -210,8 +234,11 @@ function context.exact_match(words,word_chars,case_insensitive)
end
-- spell checking (we can only load lua files)
-
+--
-- return {
+-- min = 3,
+-- max = 40,
+-- n = 12345,
-- words = {
-- ["someword"] = "someword",
-- ["anotherword"] = "Anotherword",
@@ -220,66 +247,81 @@ end
local lists = { }
-local splitter = (Cf(Ct("") * (Cg(C((1-S(" \t\n\r"))^1 * Cc(true))) + P(1))^1,rawset) )^0
-local splitter = (Cf(Ct("") * (Cg(C(R("az","AZ","\127\255")^1) * Cc(true)) + P(1))^1,rawset) )^0
-
-local function splitwords(words)
- return lpegmatch(splitter,words)
-end
-
function context.setwordlist(tag,limit) -- returns hash (lowercase keys and original values)
if not tag or tag == "" then
- return false
- elseif lists[tag] ~= nil then
- return lists[tag]
- else
- local list = context.loaddefinitions("spell-" .. tag)
+ return false, 3
+ end
+ local list = lists[tag]
+ if not list then
+ list = context.loaddefinitions("spell-" .. tag)
if not list or type(list) ~= "table" then
- lists[tag] = false
- return false
- elseif type(list.words) == "string" then
- list = splitwords(list.words) or false
- lists[tag] = list
- return list
+ list = { words = false, min = 3 }
else
- list = list.words or false
- lists[tag] = list
- return list
+ list.words = list.words or false
+ list.min = list.min or 3
end
+ lists[tag] = list
end
+ return list.words, list.min
end
patterns.wordtoken = R("az","AZ","\127\255")
patterns.wordpattern = patterns.wordtoken^3 -- todo: if limit and #s < limit then
-function context.checkedword(validwords,s,i) -- ,limit
- if not validwords then
- return true, { "text", i }
--- return true, { "default", i }
+-- -- pre 3.24:
+--
+-- function context.checkedword(validwords,validminimum,s,i) -- ,limit
+-- if not validwords then -- or #s < validminimum then
+-- return true, { "text", i } -- { "default", i }
+-- else
+-- -- keys are lower
+-- local word = validwords[s]
+-- if word == s then
+-- return true, { "okay", i } -- exact match
+-- elseif word then
+-- return true, { "warning", i } -- case issue
+-- else
+-- local word = validwords[lower(s)]
+-- if word == s then
+-- return true, { "okay", i } -- exact match
+-- elseif word then
+-- return true, { "warning", i } -- case issue
+-- elseif upper(s) == s then
+-- return true, { "warning", i } -- probably a logo or acronym
+-- else
+-- return true, { "error", i }
+-- end
+-- end
+-- end
+-- end
+
+function context.checkedword(validwords,validminimum,s,i) -- ,limit
+ if not validwords then -- or #s < validminimum then
+ return true, "text", i -- { "default", i }
else
-- keys are lower
local word = validwords[s]
if word == s then
- return true, { "okay", i } -- exact match
+ return true, "okay", i -- exact match
elseif word then
- return true, { "warning", i } -- case issue
+ return true, "warning", i -- case issue
else
local word = validwords[lower(s)]
if word == s then
- return true, { "okay", i } -- exact match
+ return true, "okay", i -- exact match
elseif word then
- return true, { "warning", i } -- case issue
+ return true, "warning", i -- case issue
elseif upper(s) == s then
- return true, { "warning", i } -- probably a logo or acronym
+ return true, "warning", i -- probably a logo or acronym
else
- return true, { "error", i }
+ return true, "error", i
end
end
end
end
-function context.styleofword(validwords,s) -- ,limit
- if not validwords then
+function context.styleofword(validwords,validminimum,s) -- ,limit
+ if not validwords or #s < validminimum then
return "text"
else
-- keys are lower
@@ -319,29 +361,57 @@ setmetatable(h_table, { __index = function(t,level) local v = { level, FOLD_HEAD
setmetatable(b_table, { __index = function(t,level) local v = { level, FOLD_BLANK } t[level] = v return v end })
setmetatable(n_table, { __index = function(t,level) local v = { level } t[level] = v return v end })
--- local newline = P("\r\n") + S("\r\n")
--- local splitlines = Ct( ( Ct ( (Cp() * Cs((1-newline)^1) * newline^-1) + (Cp() * Cc("") * newline) ) )^0)
+-- -- todo: move the local functions outside (see below) .. old variant < 3.24
--
--- local lines = lpegmatch(splitlines,text) -- iterating over lines is faster
--- for i=1, #lines do
--- local li = lines[i]
--- local line = li[2]
--- if line ~= "" then
--- local pos = li[1]
+-- local newline = P("\r\n") + S("\r\n")
+-- local p_yes = Cp() * Cs((1-newline)^1) * newline^-1
+-- local p_nop = newline
+--
+-- local function fold_by_parsing(text,start_pos,start_line,start_level,lexer)
+-- local foldsymbols = lexer._foldsymbols
+-- if not foldsymbols then
+-- return { }
+-- end
+-- local patterns = foldsymbols._patterns
+-- if not patterns then
+-- return { }
+-- end
+-- local nofpatterns = #patterns
+-- if nofpatterns == 0 then
+-- return { }
+-- end
+-- local folds = { }
+-- local line_num = start_line
+-- local prev_level = start_level
+-- local current_level = prev_level
+-- local validmatches = foldsymbols._validmatches
+-- if not validmatches then
+-- validmatches = { }
+-- for symbol, matches in next, foldsymbols do -- whatever = { start = 1, stop = -1 }
+-- if not find(symbol,"^_") then -- brrr
+-- for s, _ in next, matches do
+-- validmatches[s] = true
+-- end
+-- end
+-- end
+-- foldsymbols._validmatches = validmatches
+-- end
+-- -- of course we could instead build a nice lpeg checker .. something for
+-- -- a rainy day with a stack of new cd's at hand
+-- local function action_y(pos,line)
-- for i=1,nofpatterns do
-- for s, m in gmatch(line,patterns[i]) do
--- if hash[m] then
--- local symbols = fold_symbols[get_style_at(start_pos + pos + s - 1)]
+-- if validmatches[m] then
+-- local symbols = foldsymbols[get_style_at(start_pos + pos + s - 1)]
-- if symbols then
--- local l = symbols[m]
--- if l then
--- local t = type(l)
--- if t == 'number' then
--- current_level = current_level + l
--- elseif t == 'function' then
--- current_level = current_level + l(text, pos, line, s, match)
+-- local action = symbols[m]
+-- if action then
+-- if type(action) == 'number' then -- we could store this in validmatches if there was only one symbol category
+-- current_level = current_level + action
+-- else
+-- current_level = current_level + action(text,pos,line,s,m)
-- end
--- if current_level < FOLD_BASE then -- integrate in previous
+-- if current_level < FOLD_BASE then
-- current_level = FOLD_BASE
-- end
-- end
@@ -355,128 +425,298 @@ setmetatable(n_table, { __index = function(t,level) local v = { level
-- folds[line_num] = n_table[prev_level] -- { prev_level }
-- end
-- prev_level = current_level
--- else
+-- line_num = line_num + 1
+-- end
+-- local function action_n()
-- folds[line_num] = b_table[prev_level] -- { prev_level, FOLD_BLANK }
+-- line_num = line_num + 1
-- end
--- line_num = line_num + 1
+-- if lexer._reset_parser then
+-- lexer._reset_parser()
+-- end
+-- local lpegpattern = (p_yes/action_y + p_nop/action_n)^0 -- not too efficient but indirect function calls are neither but
+-- lpegmatch(lpegpattern,text) -- keys are not pressed that fast ... large files are slow anyway
+-- return folds
-- end
+-- The 3.24 variant; no longer subtable optimization is needed:
+
local newline = P("\r\n") + S("\r\n")
local p_yes = Cp() * Cs((1-newline)^1) * newline^-1
local p_nop = newline
+local folders = { }
+
local function fold_by_parsing(text,start_pos,start_line,start_level,lexer)
- local foldsymbols = lexer._foldsymbols
- if not foldsymbols then
- return { }
- end
- local patterns = foldsymbols._patterns
- if not patterns then
- return { }
- end
- local nofpatterns = #patterns
- if nofpatterns == 0 then
- return { }
- end
- local folds = { }
- local line_num = start_line
- local prev_level = start_level
- local current_level = prev_level
- local validmatches = foldsymbols._validmatches
- if not validmatches then
- validmatches = { }
- for symbol, matches in next, foldsymbols do -- whatever = { start = 1, stop = -1 }
- if not find(symbol,"^_") then -- brrr
- for s, _ in next, matches do
- validmatches[s] = true
+ local folder = folders[lexer]
+ if not folder then
+ --
+ local pattern, folds, text, start_pos, line_num, prev_level, current_level
+ --
+ local fold_symbols = lexer._foldsymbols
+ local fold_pattern = lexer._foldpattern -- use lpeg instead (context extension)
+ --
+ if fold_pattern then
+ -- if no functions are found then we could have a faster one
+
+ -- fold_pattern = Cp() * C(fold_pattern) * Carg(1) / function(s,match,pos)
+ -- local symbols = fold_symbols[get_style_at(start_pos + pos + s - 1)]
+ -- local l = symbols and symbols[match]
+ -- if l then
+ -- local t = type(l)
+ -- if t == 'number' then
+ -- current_level = current_level + l
+ -- elseif t == 'function' then
+ -- current_level = current_level + l(text, pos, line, s, match)
+ -- end
+ -- end
+ -- end
+ -- fold_pattern = (fold_pattern + P(1))^0
+ -- local action_y = function(pos,line)
+ -- lpegmatch(fold_pattern,line,1,pos)
+ -- folds[line_num] = prev_level
+ -- if current_level > prev_level then
+ -- folds[line_num] = prev_level + FOLD_HEADER
+ -- end
+ -- if current_level < FOLD_BASE then
+ -- current_level = FOLD_BASE
+ -- end
+ -- prev_level = current_level
+ -- line_num = line_num + 1
+ -- end
+ -- local action_n = function()
+ -- folds[line_num] = prev_level + FOLD_BLANK
+ -- line_num = line_num + 1
+ -- end
+ -- pattern = (p_yes/action_y + p_nop/action_n)^0
+
+ fold_pattern = Cp() * C(fold_pattern) / function(s,match)
+ local symbols = fold_symbols[get_style_at(start_pos + s)]
+ if symbols then
+ local l = symbols[match]
+ if l then
+ current_level = current_level + l
+ end
end
end
- end
- foldsymbols._validmatches = validmatches
- end
- local function action_y(pos,line) -- we can consider moving the local functions outside (drawback: folds is kept)
- for i=1,nofpatterns do
- for s, m in gmatch(line,patterns[i]) do
- if validmatches[m] then
- local symbols = foldsymbols[get_style_at(start_pos + pos + s - 1)]
- if symbols then
- local action = symbols[m]
- if action then
- if type(action) == 'number' then -- we could store this in validmatches if there was only one symbol category
- current_level = current_level + action
- else
- current_level = current_level + action(text,pos,line,s,m)
- end
- if current_level < FOLD_BASE then
- current_level = FOLD_BASE
- end
+ local action_y = function()
+ folds[line_num] = prev_level
+ if current_level > prev_level then
+ folds[line_num] = prev_level + FOLD_HEADER
+ end
+ if current_level < FOLD_BASE then
+ current_level = FOLD_BASE
+ end
+ prev_level = current_level
+ line_num = line_num + 1
+ end
+ local action_n = function()
+ folds[line_num] = prev_level + FOLD_BLANK
+ line_num = line_num + 1
+ end
+ pattern = ((fold_pattern + (1-newline))^1 * newline / action_y + newline/action_n)^0
+
+ else
+ -- the traditional one but a bit optimized
+ local fold_symbols_patterns = fold_symbols._patterns
+ local action_y = function(pos,line)
+ for j = 1, #fold_symbols_patterns do
+ for s, match in gmatch(line,fold_symbols_patterns[j]) do -- '()('..patterns[i]..')'
+ local symbols = fold_symbols[get_style_at(start_pos + pos + s - 1)]
+ local l = symbols and symbols[match]
+ local t = type(l)
+ if t == 'number' then
+ current_level = current_level + l
+ elseif t == 'function' then
+ current_level = current_level + l(text, pos, line, s, match)
end
end
end
+ folds[line_num] = prev_level
+ if current_level > prev_level then
+ folds[line_num] = prev_level + FOLD_HEADER
+ end
+ if current_level < FOLD_BASE then
+ current_level = FOLD_BASE
+ end
+ prev_level = current_level
+ line_num = line_num + 1
end
+ local action_n = function()
+ folds[line_num] = prev_level + FOLD_BLANK
+ line_num = line_num + 1
+ end
+ pattern = (p_yes/action_y + p_nop/action_n)^0
end
- if current_level > prev_level then
- folds[line_num] = h_table[prev_level] -- { prev_level, FOLD_HEADER }
- else
- folds[line_num] = n_table[prev_level] -- { prev_level }
+ --
+ local reset_parser = lexer._reset_parser
+ --
+ folder = function(_text_,_start_pos_,_start_line_,_start_level_)
+ if reset_parser then
+ reset_parser()
+ end
+ folds = { }
+ text = _text_
+ start_pos = _start_pos_
+ line_num = _start_line_
+ prev_level = _start_level_
+ current_level = prev_level
+ lpegmatch(pattern,text)
+-- return folds
+local t = folds
+folds = nil
+return t -- so folds can be collected
end
- prev_level = current_level
- line_num = line_num + 1
+ folders[lexer] = folder
end
- local function action_n()
- folds[line_num] = b_table[prev_level] -- { prev_level, FOLD_BLANK }
- line_num = line_num + 1
- end
- if lexer._reset_parser then
- lexer._reset_parser()
- end
- local lpegpattern = (p_yes/action_y + p_nop/action_n)^0 -- not too efficient but indirect function calls are neither but
- lpegmatch(lpegpattern,text) -- keys are not pressed that fast ... large files are slow anyway
- return folds
+ return folder(text,start_pos,start_line,start_level,lexer)
end
-local function fold_by_indentation(text,start_pos,start_line,start_level)
- local folds = { }
- local current_line = start_line
- local prev_level = start_level
- for _, line in gmatch(text,'([\t ]*)(.-)\r?\n') do
- if line ~= "" then
- local current_level = FOLD_BASE + get_indent_amount(current_line)
- if current_level > prev_level then -- next level
- local i = current_line - 1
- while true do
- local f = folds[i]
- if f and f[2] == FOLD_BLANK then
- i = i - 1
- else
- break
- end
- end
- local f = folds[i]
- if f then
- f[2] = FOLD_HEADER
- end -- low indent
- folds[current_line] = n_table[current_level] -- { current_level } -- high indent
- elseif current_level < prev_level then -- prev level
- local f = folds[current_line - 1]
- if f then
- f[1] = prev_level -- high indent
- end
- folds[current_line] = n_table[current_level] -- { current_level } -- low indent
- else -- same level
- folds[current_line] = n_table[prev_level] -- { prev_level }
+-- local function fold_by_indentation(text,start_pos,start_line,start_level)
+-- local folds = { }
+-- local current_line = start_line
+-- local prev_level = start_level
+-- for line in gmatch(text,'[\t ]*(.-)\r?\n') do
+-- if line ~= "" then
+-- local current_level = FOLD_BASE + get_indent_amount(current_line)
+-- if current_level > prev_level then -- next level
+-- local i = current_line - 1
+-- while true do
+-- local f = folds[i]
+-- if f and f[2] == FOLD_BLANK then
+-- i = i - 1
+-- else
+-- break
+-- end
+-- end
+-- local f = folds[i]
+-- if f then
+-- f[2] = FOLD_HEADER
+-- end -- low indent
+-- folds[current_line] = n_table[current_level] -- { current_level } -- high indent
+-- elseif current_level < prev_level then -- prev level
+-- local f = folds[current_line - 1]
+-- if f then
+-- f[1] = prev_level -- high indent
+-- end
+-- folds[current_line] = n_table[current_level] -- { current_level } -- low indent
+-- else -- same level
+-- folds[current_line] = n_table[prev_level] -- { prev_level }
+-- end
+-- prev_level = current_level
+-- else
+-- folds[current_line] = b_table[prev_level] -- { prev_level, FOLD_BLANK }
+-- end
+-- current_line = current_line + 1
+-- end
+-- return folds
+-- end
+
+-- local function fold_by_indentation(text,start_pos,start_line,start_level)
+-- local folds = { }
+-- local current_line = start_line
+-- local prev_level = start_level
+-- for line in gmatch(text,'[\t ]*(.-)\r?\n') do
+-- if line ~= '' then
+-- local current_level = FOLD_BASE + get_indent_amount(current_line)
+-- if current_level > prev_level then -- next level
+-- local i = current_line - 1
+-- local f
+-- while true do
+-- f = folds[i]
+-- if not f then
+-- break
+-- elseif f[2] == FOLD_BLANK then
+-- i = i - 1
+-- else
+-- f[2] = FOLD_HEADER -- low indent
+-- break
+-- end
+-- end
+-- folds[current_line] = { current_level } -- high indent
+-- elseif current_level < prev_level then -- prev level
+-- local f = folds[current_line - 1]
+-- if f then
+-- f[1] = prev_level -- high indent
+-- end
+-- folds[current_line] = { current_level } -- low indent
+-- else -- same level
+-- folds[current_line] = { prev_level }
+-- end
+-- prev_level = current_level
+-- else
+-- folds[current_line] = { prev_level, FOLD_BLANK }
+-- end
+-- current_line = current_line + 1
+-- end
+-- for line, level in next, folds do
+-- folds[line] = level[1] + (level[2] or 0)
+-- end
+-- return folds
+-- end
+
+local folds, current_line, prev_level
+
+local function action_y()
+ local current_level = FOLD_BASE + get_indent_amount(current_line)
+ if current_level > prev_level then -- next level
+ local i = current_line - 1
+ local f
+ while true do
+ f = folds[i]
+ if not f then
+ break
+ elseif f[2] == FOLD_BLANK then
+ i = i - 1
+ else
+ f[2] = FOLD_HEADER -- low indent
+ break
end
- prev_level = current_level
- else
- folds[current_line] = b_table[prev_level] -- { prev_level, FOLD_BLANK }
end
- current_line = current_line + 1
+ folds[current_line] = { current_level } -- high indent
+ elseif current_level < prev_level then -- prev level
+ local f = folds[current_line - 1]
+ if f then
+ f[1] = prev_level -- high indent
+ end
+ folds[current_line] = { current_level } -- low indent
+ else -- same level
+ folds[current_line] = { prev_level }
end
- return folds
+ prev_level = current_level
+ current_line = current_line + 1
+end
+
+local function action_n()
+ folds[current_line] = { prev_level, FOLD_BLANK }
+ current_line = current_line + 1
+end
+
+local pattern = ( S("\t ")^0 * ( (1-S("\n\r"))^1 / action_y + P(true) / action_n) * newline )^0
+
+local function fold_by_indentation(text,start_pos,start_line,start_level)
+ -- initialize
+ folds = { }
+ current_line = start_line
+ prev_level = start_level
+ -- define
+ -- -- not here .. pattern binds and local functions are not frozen
+ -- analyze
+ lpegmatch(pattern,text)
+ -- flatten
+ for line, level in next, folds do
+ folds[line] = level[1] + (level[2] or 0)
+ end
+ -- done
+-- return folds
+local t = folds
+folds = nil
+return t -- so folds can be collected
end
local function fold_by_line(text,start_pos,start_line,start_level)
local folds = { }
+ -- can also be lpeg'd
for _ in gmatch(text,".-\r?\n") do
folds[start_line] = n_table[start_level] -- { start_level }
start_line = start_line + 1
@@ -501,7 +741,7 @@ function context.fold(text,start_pos,start_line,start_level) -- hm, we had size
if filesize <= threshold_by_lexer then
return fold_by_lexer(text,start_pos,start_line,start_level,lexer)
end
- elseif fold_by_symbols and get_property('fold.by.parsing',1) > 0 then
+ elseif fold_by_symbols then -- and get_property('fold.by.parsing',1) > 0 then
if filesize <= threshold_by_parsing then
return fold_by_parsing(text,start_pos,start_line,start_level,lexer)
end
@@ -589,6 +829,10 @@ local function build_grammar(lexer, initial_rule)
end
-- so far. We need these local functions in the next one.
+--
+-- Before 3.24 we had tokens[..] = { category, position }, now it's a two values.
+
+local lineparsers = { }
function context.lex(text,init_style)
local lexer = global._LEXER
@@ -599,50 +843,75 @@ function context.lex(text,init_style)
local tokens = { }
local offset = 0
local noftokens = 0
- if true then
- for line in gmatch(text,'[^\r\n]*\r?\n?') do -- could be an lpeg
- local line_tokens = lpegmatch(grammar,line)
+ -- -- pre 3.24
+ --
+ -- for line in gmatch(text,'[^\r\n]*\r?\n?') do -- could be an lpeg
+ -- local line_tokens = lpegmatch(grammar,line)
+ -- if line_tokens then
+ -- for i=1,#line_tokens do
+ -- local token = line_tokens[i]
+ -- token[2] = token[2] + offset
+ -- noftokens = noftokens + 1
+ -- tokens[noftokens] = token
+ -- end
+ -- end
+ -- offset = offset + #line
+ -- if noftokens > 0 and tokens[noftokens][2] ~= offset then
+ -- noftokens = noftokens + 1
+ -- tokens[noftokens] = { 'default', offset + 1 }
+ -- end
+ -- end
+
+ -- for line in gmatch(text,'[^\r\n]*\r?\n?') do
+ -- local line_tokens = lpegmatch(grammar,line)
+ -- if line_tokens then
+ -- for i=1,#line_tokens,2 do
+ -- noftokens = noftokens + 1
+ -- tokens[noftokens] = line_tokens[i]
+ -- noftokens = noftokens + 1
+ -- tokens[noftokens] = line_tokens[i + 1] + offset
+ -- end
+ -- end
+ -- offset = offset + #line
+ -- if noftokens > 0 and tokens[noftokens] ~= offset then
+ -- noftokens = noftokens + 1
+ -- tokens[noftokens] = 'default'
+ -- noftokens = noftokens + 1
+ -- tokens[noftokens] = offset + 1
+ -- end
+ -- end
+
+ local lineparser = lineparsers[lexer]
+ if not lineparser then -- probably a cmt is more efficient
+ lineparser = C((1-newline)^0 * newline) / function(line)
+ local length = #line
+ local line_tokens = length > 0 and lpegmatch(grammar,line)
if line_tokens then
- for i=1,#line_tokens do
- local token = line_tokens[i]
- token[2] = token[2] + offset
+ for i=1,#line_tokens,2 do
noftokens = noftokens + 1
- tokens[noftokens] = token
- end
- end
- offset = offset + #line
- if noftokens > 0 and tokens[noftokens][2] ~= offset then
- noftokens = noftokens + 1
- tokens[noftokens] = { 'default', offset + 1 }
- end
- end
- else -- alternative
- local lasttoken, lastoffset
- for line in gmatch(text,'[^\r\n]*\r?\n?') do -- could be an lpeg
- local line_tokens = lpegmatch(grammar,line)
- if line_tokens then
- for i=1,#line_tokens do
- lasttoken = line_tokens[i]
- lastoffset = lasttoken[2] + offset
- lasttoken[2] = lastoffset
+ tokens[noftokens] = line_tokens[i]
noftokens = noftokens + 1
- tokens[noftokens] = lasttoken
+ tokens[noftokens] = line_tokens[i + 1] + offset
end
end
- offset = offset + #line
- if lastoffset ~= offset then
- lastoffset = offset + 1
- lasttoken = { 'default', lastoffset }
+ offset = offset + length
+ if noftokens > 0 and tokens[noftokens] ~= offset then
+ noftokens = noftokens + 1
+ tokens[noftokens] = 'default'
noftokens = noftokens + 1
- tokens[noftokens] = lasttoken
+ tokens[noftokens] = offset + 1
end
end
+ lineparser = lineparser^0
+ lineparsers[lexer] = lineparser
end
+ lpegmatch(lineparser,text)
return tokens
+
elseif lexer._CHILDREN then
-- as we cannot print, tracing is not possible ... this might change as we can as well
-- generate them all in one go (sharing as much as possible)
- local _hash = lexer._HASH
+ local hash = lexer._HASH -- hm, was _hash
if not hash then
hash = { }
lexer._HASH = hash
@@ -678,8 +947,14 @@ end
-- todo: keywords: one lookup and multiple matches
+-- function context.token(name, patt)
+-- return Ct(patt * Cc(name) * Cp())
+-- end
+--
+-- -- hm, changed in 3.24 .. no longer a table
+
function context.token(name, patt)
- return Ct(patt * Cc(name) * Cp())
+ return patt * Cc(name) * Cp()
end
lexer.fold = context.fold
diff --git a/Master/texmf-dist/context/data/scite/lexers/themes/scite-context-theme.lua b/Master/texmf-dist/context/data/scite/lexers/themes/scite-context-theme.lua
index 7b305d3e5d5..e32fe9dee15 100644
--- a/Master/texmf-dist/context/data/scite/lexers/themes/scite-context-theme.lua
+++ b/Master/texmf-dist/context/data/scite/lexers/themes/scite-context-theme.lua
@@ -107,7 +107,6 @@ local style_tag = style { fore = colors.cyan }
----- style_standout = style { fore = colors.orange, bold = true }
local style_command = style { fore = colors.green, bold = true }
local style_internal = style { fore = colors.orange, bold = true }
-local style_internal = style { fore = colors.orange, bold = true }
local style_preamble = style { fore = colors.yellow }
local style_grouping = style { fore = colors.red }
diff --git a/Master/texmf-dist/context/data/scite/scite-context-data-context.properties b/Master/texmf-dist/context/data/scite/scite-context-data-context.properties
index 37a39e1e0c8..4af84cde5c9 100644
--- a/Master/texmf-dist/context/data/scite/scite-context-data-context.properties
+++ b/Master/texmf-dist/context/data/scite/scite-context-data-context.properties
@@ -1,130 +1,178 @@
+keywordclass.context.constants=\
+zerocount minusone minustwo plusone \
+plustwo plusthree plusfour plusfive plussix \
+plusseven pluseight plusnine plusten plussixteen \
+plushundred plusthousand plustenthousand plustwentythousand medcard \
+maxcard zeropoint onepoint halfapoint onebasepoint \
+maxdimen scaledpoint thousandpoint points halfpoint \
+zeroskip zeromuskip onemuskip pluscxxvii pluscxxviii \
+pluscclv pluscclvi normalpagebox endoflinetoken outputnewlinechar \
+emptytoks empty undefined voidbox emptybox \
+emptyvbox emptyhbox bigskipamount medskipamount smallskipamount \
+fmtname fmtversion texengine texenginename texengineversion \
+luatexengine pdftexengine xetexengine unknownengine etexversion \
+pdftexversion xetexversion xetexrevision activecatcode bgroup \
+egroup endline conditionaltrue conditionalfalse attributeunsetvalue \
+uprotationangle rightrotationangle downrotationangle leftrotationangle inicatcodes \
+ctxcatcodes texcatcodes notcatcodes txtcatcodes vrbcatcodes \
+prtcatcodes nilcatcodes luacatcodes tpacatcodes tpbcatcodes \
+xmlcatcodes escapecatcode begingroupcatcode endgroupcatcode mathshiftcatcode \
+alignmentcatcode endoflinecatcode parametercatcode superscriptcatcode subscriptcatcode \
+ignorecatcode spacecatcode lettercatcode othercatcode activecatcode \
+commentcatcode invalidcatcode tabasciicode newlineasciicode formfeedasciicode \
+endoflineasciicode endoffileasciicode spaceasciicode hashasciicode dollarasciicode \
+commentasciicode ampersandasciicode colonasciicode backslashasciicode circumflexasciicode \
+underscoreasciicode leftbraceasciicode barasciicode rightbraceasciicode tildeasciicode \
+delasciicode lessthanasciicode morethanasciicode doublecommentsignal atsignasciicode \
+exclamationmarkasciicode questionmarkasciicode doublequoteasciicode singlequoteasciicode forwardslashasciicode \
+primeasciicode activemathcharcode activetabtoken activeformfeedtoken activeendoflinetoken \
+batchmodecode nonstopmodecode scrollmodecode errorstopmodecode bottomlevelgroupcode \
+simplegroupcode hboxgroupcode adjustedhboxgroupcode vboxgroupcode vtopgroupcode \
+aligngroupcode noaligngroupcode outputgroupcode mathgroupcode discretionarygroupcode \
+insertgroupcode vcentergroupcode mathchoicegroupcode semisimplegroupcode mathshiftgroupcode \
+mathleftgroupcode vadjustgroupcode charnodecode hlistnodecode vlistnodecode \
+rulenodecode insertnodecode marknodecode adjustnodecode ligaturenodecode \
+discretionarynodecode whatsitnodecode mathnodecode gluenodecode kernnodecode \
+penaltynodecode unsetnodecode mathsnodecode charifcode catifcode \
+numifcode dimifcode oddifcode vmodeifcode hmodeifcode \
+mmodeifcode innerifcode voidifcode hboxifcode vboxifcode \
+xifcode eofifcode trueifcode falseifcode caseifcode \
+definedifcode csnameifcode fontcharifcode fontslantperpoint fontinterwordspace \
+fontinterwordstretch fontinterwordshrink fontexheight fontemwidth fontextraspace \
+slantperpoint interwordspace interwordstretch interwordshrink exheight \
+emwidth extraspace mathsupdisplay mathsupnormal mathsupcramped \
+mathsubnormal mathsubcombined mathaxisheight startmode stopmode \
+startnotmode stopnotmode startmodeset stopmodeset doifmode \
+doifmodeelse doifnotmode startallmodes stopallmodes startnotallmodes \
+stopnotallmodes doifallmodes doifallmodeselse doifnotallmodes startenvironment \
+stopenvironment environment startcomponent stopcomponent component \
+startproduct stopproduct product startproject stopproject \
+project starttext stoptext startnotext stopnotext \
+startdocument stopdocument documentvariable setupdocument startmodule \
+stopmodule usemodule usetexmodule useluamodule startTEXpage \
+stopTEXpage enablemode disablemode preventmode globalenablemode \
+globaldisablemode globalpreventmode pushmode popmode typescriptone \
+typescripttwo typescriptthree mathsizesuffix mathordcode mathopcode \
+mathbincode mathrelcode mathopencode mathclosecode mathpunctcode \
+mathalphacode mathinnercode mathnothingcode mathlimopcode mathnolopcode \
+mathboxcode mathchoicecode mathaccentcode mathradicalcode constantnumber \
+constantnumberargument constantdimen constantdimenargument constantemptyargument continueifinputfile \
+luastringsep !!bs !!es
+
keywordclass.context.helpers=\
startsetups stopsetups startxmlsetups stopxmlsetups \
startluasetups stopluasetups starttexsetups stoptexsetups startrawsetups \
stoprawsetups startlocalsetups stoplocalsetups starttexdefinition stoptexdefinition \
-starttexcode stoptexcode doifsetupselse doifsetups doifnotsetups \
-setup setups texsetup xmlsetup luasetup \
-directsetup newmode setmode resetmode newsystemmode \
+starttexcode stoptexcode startcontextcode stopcontextcode doifsetupselse \
+doifsetups doifnotsetups setup setups texsetup \
+xmlsetup luasetup directsetup doifelsecommandhandler doifnotcommandhandler \
+doifcommandhandler newmode setmode resetmode newsystemmode \
setsystemmode resetsystemmode pushsystemmode popsystemmode booleanmodevalue \
newcount newdimen newskip newmuskip newbox \
newtoks newread newwrite newmarks newinsert \
newattribute newif newlanguage newfamily newfam \
-newhelp then donothing dontcomplain donetrue \
-donefalse htdp unvoidbox vfilll mathbox \
-mathlimop mathnolop mathnothing mathalpha currentcatcodetable \
-defaultcatcodetable catcodetablename newcatcodetable startcatcodetable stopcatcodetable \
-startextendcatcodetable stopextendcatcodetable pushcatcodetable popcatcodetable restorecatcodes \
-setcatcodetable letcatcodecommand defcatcodecommand uedcatcodecommand hglue \
-vglue hfillneg vfillneg hfilllneg vfilllneg \
-ruledhss ruledhfil ruledhfill ruledhfilneg ruledhfillneg \
-normalhfillneg ruledvss ruledvfil ruledvfill ruledvfilneg \
-ruledvfillneg normalvfillneg ruledhbox ruledvbox ruledvtop \
-ruledvcenter ruledhskip ruledvskip ruledkern ruledmskip \
-ruledmkern ruledhglue ruledvglue normalhglue normalvglue \
-ruledpenalty scratchcounter globalscratchcounter scratchdimen globalscratchdimen \
+newhelp then firstargumentfalse firstargumenttrue secondargumentfalse \
+secondargumenttrue thirdargumentfalse thirdargumenttrue fourthargumentfalse fourthargumenttrue \
+fifthargumentfalse fifthsargumenttrue sixthargumentfalse sixtsargumenttrue doglobal \
+dodoglobal redoglobal resetglobal donothing dontcomplain \
+forgetall donetrue donefalse htdp unvoidbox \
+hfilll vfilll mathbox mathlimop mathnolop \
+mathnothing mathalpha currentcatcodetable defaultcatcodetable catcodetablename \
+newcatcodetable startcatcodetable stopcatcodetable startextendcatcodetable stopextendcatcodetable \
+pushcatcodetable popcatcodetable restorecatcodes setcatcodetable letcatcodecommand \
+defcatcodecommand uedcatcodecommand hglue vglue hfillneg \
+vfillneg hfilllneg vfilllneg ruledhss ruledhfil \
+ruledhfill ruledhfilneg ruledhfillneg normalhfillneg ruledvss \
+ruledvfil ruledvfill ruledvfilneg ruledvfillneg normalvfillneg \
+ruledhbox ruledvbox ruledvtop ruledvcenter ruledhskip \
+ruledvskip ruledkern ruledmskip ruledmkern ruledhglue \
+ruledvglue normalhglue normalvglue ruledpenalty filledhboxb \
+filledhboxr filledhboxg filledhboxc filledhboxm filledhboxy \
+filledhboxk scratchcounter globalscratchcounter scratchdimen globalscratchdimen \
scratchskip globalscratchskip scratchmuskip globalscratchmuskip scratchtoks \
-globalscratchtoks scratchbox globalscratchbox nextbox dowithnextbox \
-dowithnextboxcs dowithnextboxcontent dowithnextboxcontentcs scratchwidth scratchheight \
-scratchdepth scratchoffset scratchdistance scratchhsize scratchvsize \
-scratchcounterone scratchcountertwo scratchcounterthree scratchdimenone scratchdimentwo \
-scratchdimenthree scratchskipone scratchskiptwo scratchskipthree scratchmuskipone \
-scratchmuskiptwo scratchmuskipthree scratchtoksone scratchtokstwo scratchtoksthree \
-scratchboxone scratchboxtwo scratchboxthree doif doifnot \
-doifelse doifinset doifnotinset doifinsetelse doifnextcharelse \
-doifnextoptionalelse doifnextbgroupelse doifnextparenthesiselse doiffastoptionalcheckelse doifundefinedelse \
-doifdefinedelse doifundefined doifdefined doifelsevalue doifvalue \
-doifnotvalue doifnothing doifsomething doifelsenothing doifsomethingelse \
-doifvaluenothing doifvaluesomething doifelsevaluenothing doifdimensionelse doifnumberelse \
-doifcommonelse doifcommon doifnotcommon doifinstring doifnotinstring \
-doifinstringelse doifassignmentelse tracingall tracingnone loggingall \
-appendtoks prependtoks appendtotoks prependtotoks to \
-endgraf empty null space quad \
-enspace obeyspaces obeylines normalspace executeifdefined \
-singleexpandafter doubleexpandafter tripleexpandafter dontleavehmode removelastspace \
-removeunwantedspaces wait writestatus define redefine \
-setmeasure setemeasure setgmeasure setxmeasure definemeasure \
-measure getvalue setvalue setevalue setgvalue \
+globalscratchtoks scratchbox globalscratchbox availablehsize localhsize \
+setlocalhsize nextbox dowithnextbox dowithnextboxcs dowithnextboxcontent \
+dowithnextboxcontentcs scratchwidth scratchheight scratchdepth scratchoffset \
+scratchdistance scratchhsize scratchvsize scratchxoffset scratchyoffset \
+scratchhoffset scratchvoffset scratchxposition scratchyposition scratchtopoffset \
+scratchbottomoffset scratchleftoffset scratchrightoffset scratchcounterone scratchcountertwo \
+scratchcounterthree scratchdimenone scratchdimentwo scratchdimenthree scratchskipone \
+scratchskiptwo scratchskipthree scratchmuskipone scratchmuskiptwo scratchmuskipthree \
+scratchtoksone scratchtokstwo scratchtoksthree scratchboxone scratchboxtwo \
+scratchboxthree scratchnx scratchny scratchmx scratchmy \
+scratchunicode scratchleftskip scratchrightskip scratchtopskip scratchbottomskip \
+doif doifnot doifelse doifinset doifnotinset \
+doifinsetelse doifnextcharelse doifnextoptionalelse doifnextbgroupelse doifnextparenthesiselse \
+doiffastoptionalcheckelse doifundefinedelse doifdefinedelse doifundefined doifdefined \
+doifelsevalue doifvalue doifnotvalue doifnothing doifsomething \
+doifelsenothing doifsomethingelse doifvaluenothing doifvaluesomething doifelsevaluenothing \
+doifdimensionelse doifnumberelse doifnumber doifnotnumber doifcommonelse \
+doifcommon doifnotcommon doifinstring doifnotinstring doifinstringelse \
+doifassignmentelse docheckassignment tracingall tracingnone loggingall \
+removetoks appendtoks prependtoks appendtotoks prependtotoks \
+to endgraf endpar everyendpar reseteverypar \
+finishpar empty null space quad \
+enspace obeyspaces obeylines obeyedspace obeyedline \
+normalspace executeifdefined singleexpandafter doubleexpandafter tripleexpandafter \
+dontleavehmode removelastspace removeunwantedspaces keepunwantedspaces wait \
+writestatus define redefine setmeasure setemeasure \
+setgmeasure setxmeasure definemeasure freezemeasure measure \
+installcorenamespace getvalue setvalue setevalue setgvalue \
setxvalue letvalue letgvalue resetvalue undefinevalue \
ignorevalue setuvalue setuevalue setugvalue setuxvalue \
-globallet glet getparameters geteparameters getgparameters \
-getxparameters forgetparameters copyparameters processcommalist processcommacommand \
-quitcommalist quitprevcommalist processaction processallactions processfirstactioninset \
-processallactionsinset unexpanded expanded startexpanded stopexpanded \
-protected protect unprotect firstofoneargument firstoftwoarguments \
-secondoftwoarguments firstofthreearguments secondofthreearguments thirdofthreearguments firstoffourarguments \
-secondoffourarguments thirdoffourarguments fourthoffourarguments firstoffivearguments secondoffivearguments \
-thirdoffivearguments fourthoffivearguments fifthoffivearguments firstofsixarguments secondofsixarguments \
-thirdofsixarguments fourthofsixarguments fifthofsixarguments sixthofsixarguments firstofoneunexpanded \
-gobbleoneargument gobbletwoarguments gobblethreearguments gobblefourarguments gobblefivearguments \
-gobblesixarguments gobblesevenarguments gobbleeightarguments gobbleninearguments gobbletenarguments \
-gobbleoneoptional gobbletwooptionals gobblethreeoptionals gobblefouroptionals gobblefiveoptionals \
-dorecurse doloop exitloop dostepwiserecurse recurselevel \
-recursedepth dofastloopcs newconstant setnewconstant newconditional \
-settrue setfalse setconstant newmacro setnewmacro \
-newfraction dosingleempty dodoubleempty dotripleempty doquadrupleempty \
-doquintupleempty dosixtupleempty doseventupleempty dosingleargument dodoubleargument \
-dotripleargument doquadrupleargument dosinglegroupempty dodoublegroupempty dotriplegroupempty \
-doquadruplegroupempty doquintuplegroupempty nopdfcompression maximumpdfcompression normalpdfcompression \
-modulonumber dividenumber getfirstcharacter doiffirstcharelse startnointerference \
-stopnointerference strut setstrut strutbox strutht \
-strutdp strutwd begstrut endstrut
-
-keywordclass.context.constants=\
-zerocount minusone minustwo plusone \
-plustwo plusthree plusfour plusfive plussix \
-plusseven pluseight plusnine plusten plussixteen \
-plushundred plusthousand plustenthousand plustwentythousand medcard \
-maxcard zeropoint onepoint halfapoint onebasepoint \
-maxdimen scaledpoint thousandpoint points halfpoint \
-zeroskip pluscxxvii pluscxxviii pluscclv pluscclvi \
-normalpagebox endoflinetoken outputnewlinechar emptytoks empty \
-undefined voidbox emptybox emptyvbox emptyhbox \
-bigskipamount medskipamount smallskipamount fmtname fmtversion \
-texengine texenginename texengineversion luatexengine pdftexengine \
-xetexengine unknownengine etexversion pdftexversion xetexversion \
-xetexrevision activecatcode bgroup egroup endline \
-conditionaltrue conditionalfalse attributeunsetvalue uprotationangle rightrotationangle \
-downrotationangle leftrotationangle inicatcodes ctxcatcodes texcatcodes \
-notcatcodes txtcatcodes vrbcatcodes prtcatcodes nilcatcodes \
-luacatcodes tpacatcodes tpbcatcodes xmlcatcodes escapecatcode \
-begingroupcatcode endgroupcatcode mathshiftcatcode alignmentcatcode endoflinecatcode \
-parametercatcode superscriptcatcode subscriptcatcode ignorecatcode spacecatcode \
-lettercatcode othercatcode activecatcode commentcatcode invalidcatcode \
-tabasciicode newlineasciicode formfeedasciicode endoflineasciicode endoffileasciicode \
-spaceasciicode hashasciicode dollarasciicode commentasciicode ampersandasciicode \
-colonasciicode backslashasciicode circumflexasciicode underscoreasciicode leftbraceasciicode \
-barasciicode rightbraceasciicode tildeasciicode delasciicode lessthanasciicode \
-morethanasciicode doublecommentsignal atsignasciicode exclamationmarkasciicode questionmarkasciicode \
-doublequoteasciicode singlequoteasciicode forwardslashasciicode primeasciicode activemathcharcode \
-activetabtoken activeformfeedtoken activeendoflinetoken batchmodecode nonstopmodecode \
-scrollmodecode errorstopmodecode bottomlevelgroupcode simplegroupcode hboxgroupcode \
-adjustedhboxgroupcode vboxgroupcode vtopgroupcode aligngroupcode noaligngroupcode \
-outputgroupcode mathgroupcode discretionarygroupcode insertgroupcode vcentergroupcode \
-mathchoicegroupcode semisimplegroupcode mathshiftgroupcode mathleftgroupcode vadjustgroupcode \
-charnodecode hlistnodecode vlistnodecode rulenodecode insertnodecode \
-marknodecode adjustnodecode ligaturenodecode discretionarynodecode whatsitnodecode \
-mathnodecode gluenodecode kernnodecode penaltynodecode unsetnodecode \
-mathsnodecode charifcode catifcode numifcode dimifcode \
-oddifcode vmodeifcode hmodeifcode mmodeifcode innerifcode \
-voidifcode hboxifcode vboxifcode xifcode eofifcode \
-trueifcode falseifcode caseifcode definedifcode csnameifcode \
-fontcharifcode fontslantperpoint fontinterwordspace fontinterwordstretch fontinterwordshrink \
-fontexheight fontemwidth fontextraspace slantperpoint interwordspace \
-interwordstretch interwordshrink exheight emwidth extraspace \
-mathsupdisplay mathsupnormal mathsupcramped mathsubnormal mathsubcombined \
-mathaxisheight startmode stopmode startnotmode stopnotmode \
-startmodeset stopmodeset doifmode doifmodeelse doifnotmode \
-startallmodes stopallmodes startnotallmodes stopnotallmodes doifallmodes \
-doifallmodeselse doifnotallmodes startenvironment stopenvironment environment \
-startcomponent stopcomponent component startproduct stopproduct \
-product startproject stopproject project starttext \
-stoptext startnotext stopnotext startdocument stopdocument \
-documentvariable startmodule stopmodule usemodule startTEXpage \
-stopTEXpage enablemode disablemode preventmode pushmode \
-popmode typescriptone typescripttwo typescriptthree mathsizesuffix \
-mathordcode mathopcode mathbincode mathrelcode mathopencode \
-mathclosecode mathpunctcode mathalphacode mathinnercode mathnothingcode \
-mathlimopcode mathnolopcode mathboxcode mathchoicecode mathaccentcode \
-mathradicalcode constantnumber constantnumberargument constantdimen constantdimenargument \
-constantemptyargument continueifinputfile
+globallet glet udef ugdef uedef \
+uxdef getparameters geteparameters getgparameters getxparameters \
+forgetparameters copyparameters getdummyparameters dummyparameter directdummyparameter \
+setdummyparameter letdummyparameter usedummystyleandcolor usedummystyleparameter usedummycolorparameter \
+processcommalist processcommacommand quitcommalist quitprevcommalist processaction \
+processallactions processfirstactioninset processallactionsinset unexpanded expanded \
+startexpanded stopexpanded protected protect unprotect \
+firstofoneargument firstoftwoarguments secondoftwoarguments firstofthreearguments secondofthreearguments \
+thirdofthreearguments firstoffourarguments secondoffourarguments thirdoffourarguments fourthoffourarguments \
+firstoffivearguments secondoffivearguments thirdoffivearguments fourthoffivearguments fifthoffivearguments \
+firstofsixarguments secondofsixarguments thirdofsixarguments fourthofsixarguments fifthofsixarguments \
+sixthofsixarguments firstofoneunexpanded gobbleoneargument gobbletwoarguments gobblethreearguments \
+gobblefourarguments gobblefivearguments gobblesixarguments gobblesevenarguments gobbleeightarguments \
+gobbleninearguments gobbletenarguments gobbleoneoptional gobbletwooptionals gobblethreeoptionals \
+gobblefouroptionals gobblefiveoptionals dorecurse doloop exitloop \
+dostepwiserecurse recurselevel recursedepth dofastloopcs newconstant \
+setnewconstant newconditional settrue setfalse setconstant \
+newmacro setnewmacro newfraction newsignal dosingleempty \
+dodoubleempty dotripleempty doquadrupleempty doquintupleempty dosixtupleempty \
+doseventupleempty dosingleargument dodoubleargument dotripleargument doquadrupleargument \
+doquintupleargument dosixtupleargument doseventupleargument dosinglegroupempty dodoublegroupempty \
+dotriplegroupempty doquadruplegroupempty doquintuplegroupempty permitspacesbetweengroups dontpermitspacesbetweengroups \
+nopdfcompression maximumpdfcompression normalpdfcompression modulonumber dividenumber \
+getfirstcharacter doiffirstcharelse startnointerference stopnointerference twodigits \
+threedigits strut setstrut strutbox strutht \
+strutdp strutwd struthtdp begstrut endstrut \
+lineheight ordordspacing ordopspacing ordbinspacing ordrelspacing \
+ordopenspacing ordclosespacing ordpunctspacing ordinnerspacing opordspacing \
+opopspacing opbinspacing oprelspacing opopenspacing opclosespacing \
+oppunctspacing opinnerspacing binordspacing binopspacing binbinspacing \
+binrelspacing binopenspacing binclosespacing binpunctspacing bininnerspacing \
+relordspacing relopspacing relbinspacing relrelspacing relopenspacing \
+relclosespacing relpunctspacing relinnerspacing openordspacing openopspacing \
+openbinspacing openrelspacing openopenspacing openclosespacing openpunctspacing \
+openinnerspacing closeordspacing closeopspacing closebinspacing closerelspacing \
+closeopenspacing closeclosespacing closepunctspacing closeinnerspacing punctordspacing \
+punctopspacing punctbinspacing punctrelspacing punctopenspacing punctclosespacing \
+punctpunctspacing punctinnerspacing innerordspacing inneropspacing innerbinspacing \
+innerrelspacing inneropenspacing innerclosespacing innerpunctspacing innerinnerspacing \
+normalreqno startimath stopimath normalstartimath normalstopimath \
+startdmath stopdmath normalstartdmath normalstopdmath uncramped \
+cramped triggermathstyle mathstylefont mathsmallstylefont mathstyleface \
+mathsmallstyleface mathstylecommand mathpalette mathstylehbox mathstylevbox \
+mathstylevcenter mathstylevcenteredhbox mathstylevcenteredvbox mathtext setmathsmalltextbox \
+setmathtextbox triggerdisplaystyle triggertextstyle triggerscriptstyle triggerscriptscriptstyle \
+triggeruncrampedstyle triggercrampedstyle triggersmallstyle triggeruncrampedsmallstyle triggercrampedsmallstyle \
+triggerbigstyle triggeruncrampedbigstyle triggercrampedbigstyle luaexpr expdoifelse \
+expdoif expdoifnot expdoifcommonelse expdoifinsetelse ctxdirectlua \
+ctxlatelua ctxsprint ctxwrite ctxcommand ctxdirectcommand \
+ctxlatecommand ctxreport ctxlua luacode lateluacode \
+directluacode registerctxluafile ctxloadluafile luaversion luamajorversion \
+luaminorversion ctxluacode luaconditional luaexpanded startluaparameterset \
+stopluaparameterset luaparameterset definenamedlua obeylualines obeyluatokens \
+startluacode stopluacode startlua stoplua carryoverpar \
+Umathbotaccent
diff --git a/Master/texmf-dist/context/data/scite/scite-context-data-interfaces.properties b/Master/texmf-dist/context/data/scite/scite-context-data-interfaces.properties
index c205bb568d9..9c2ca4623fc 100644
--- a/Master/texmf-dist/context/data/scite/scite-context-data-interfaces.properties
+++ b/Master/texmf-dist/context/data/scite/scite-context-data-interfaces.properties
@@ -1,488 +1,3 @@
-keywordclass.context.it=\
-CAP Cap Caps GIORNOSETTIMANA \
-Lettera Lettere MESE Numeri Numeriromani \
-PAROLA PAROLE Parola Parole accoppiacarta \
-accoppiadocumento accoppiamarcatura accoppiapagina accoppiaregistro adattacampo \
-adattalayout al allineacentro allineadestra allineasinistra \
-altezzacarta altezzacartastampa altezzacima altezzaelenco altezzafondo \
-altezzaintestazione altezzamakeup altezzapdp altezzatesto ambiente \
-ampiezzabordo ampiezzabordodestro ampiezzabordosinistro ampiezzacarta ampiezzacartastampa \
-ampiezzaelenco ampiezzamakeup ampiezzamargine ampiezzamarginedestro ampiezzamarginesinistro \
-ampiezzatesto ap apagina appendix arg \
-atleftmargin atrightmargin barracolori barrainterazione barrasincronizzazione \
-bastablocchi bastafile cambiaafontdeltesto campi camporiempimento \
-cap capello chapter chim circondato \
-citazione clip clonacampo colonna colore \
-coloregrigio comment commento completecombinedlist completelistoffloats \
-completelistofsorts completelistofsynonyms completeregister componenet confrontagruppocolori \
-confrontatavolozza convertinumero copiacampo correggispaziobianco coupledregister \
-crlf cutspace da daqualcheparte data \
-datadioggi datareferral decrementnumber definebodyfontDEF definebodyfontREF \
-definecolumnbreak definecombination definedfont definefontfeature definefonthandling \
-defineindentedtext defineinmargin defineitemgroup definelayer definemathalignment \
-definepagebreak defineplacement definetypeface definisci definisciaccento \
-definisciambientefontdeltesto definisciblocco definiscibloccosezione definiscibuffer definiscicampo \
-definiscicampoprincipale definiscicapoversi definiscicarattere definiscicolore definiscicomando \
-definisciconversione definiscidescrizione definiscidimensionicarta definiscielenco definiscielencocombinato \
-definiscienumerazione definiscietichetta definiscifigurasimbolo definiscifont definiscifontdeltesto \
-definiscifontgrezzo definisciformatoriferimento definiscigruppocolonne definiscigruppocolori definiscihbox \
-definisciincorniciato definisciiniziatermina definiscilayout definiscilinea definiscilistariferimenti \
-definiscilogo definiscimakeup definiscimarcatura definiscimenuinterazione definiscimodellotabella \
-definiscioggettomobile definisciordinamento definiscioutput definisciposizionetesto definisciprofilo \
-definisciprogramma definisciregistro definisciriferimento definiscirigovuoto definiscisezione \
-definiscisimbolo definiscisinonimi definiscisinonimofont definiscisottocampo definiscisovrapposizione \
-definiscistackcampi definiscistile definiscistilefont definiscitabulato definiscitavolozza \
-definiscitesta definiscitesto definiscitestoincorniciato definiscitype definiscityping \
-definiscivariabiletesto definisciversion description determinacaratteristicheregistro determinacarattersticheelenco \
-determinanumerotesta dimensione disabilitamenuinterazione distanzabordo distanzabordodestro \
-distanzabordosinistro distanzacima distanzafondo distanzaintestazione distanzamargine \
-distanzamarginedestro distanzamarginesinistro distanzapdp domicilio el \
-elaborablocchi elaborapagina elementi elemento emptylines \
-enumeration etichetta etichette fatto figuraesterna \
-fondo forzablocchi framedtext frazione getnumber \
-giornosettimana griglia headsym hl ignoto \
-immediatebetweenlist immediatetolist impaccato impostaallineamento impostaambientefontdeltesto \
-impostaampiezzariga impostabarrainterazione impostabarrasincronizzazione impostablocchimargine impostablocco \
-impostabloccosezione impostabuffer impostacampi impostacampo impostacapoversi \
-impostacaption impostacaptions impostacima impostaclippling impostacolonne \
-impostacolore impostacolori impostacombinazioni impostacommento impostacommentopagina \
-impostadefinizionenotepdp impostadescrizioni impostadimensionicarta impostaelementi impostaelencazioni \
-impostaelenco impostaelencocombinato impostaenumerazioni impostafigureesterne impostafondo \
-impostafontdeltesto impostaforms impostaformule impostagruppocolonne impostaincorniciato \
-impostainiziatermina impostainmargine impostainstestazione impostainterazione impostainterlinea \
-impostalayout impostalegenda impostalinea impostalineemargine impostalineenere \
-impostalineeriempimento impostalineesottili impostalineetesto impostalingua impostalistariferimenti \
-impostamaiuscole impostamakeup impostamarcatura impostamenuinterazione impostamenzione \
-impostanotepdp impostanumerazione impostanumerazionecapoversi impostanumerazionepagina impostanumerazionerighe \
-impostanumeropagina impostanumerosottopagina impostanumerotesta impostaoggettimobili impostaoggettomobile \
-impostaordinamento impostaoutput impostaparranging impostapdp impostapiustretto \
-impostaposizionamento impostaposizionamentoopposti impostaposizionetesto impostaprofili impostaprogrammi \
-impostapubblicazioni impostapulsanti impostaregistro impostarientro impostariferimento \
-impostarighe impostarigheriempimento impostarigovuoto impostarotazione impostaschermi \
-impostaschermointerazione impostasegnosillabazione impostasetsimboli impostasezione impostasfondi \
-impostasfondo impostasincronizzazione impostasinonimi impostasistema impostasottolinea \
-impostaspaziatura impostaspaziobianco impostaspezzamentooggettomobile impostastrut impostatab \
-impostatabelle impostatabulato impostatavolozza impostatesta impostateste \
-impostatesticima impostatestifondo impostatestiincorniciati impostatestiintestazioni impostatestipdp \
-impostatesto impostatestoetichette impostatestointestazioni impostatestotesti impostatolleranza \
-impostatransizionepagina impostatype impostatyping impostaurl impostavariabiletesto \
-impostaversioni impostazioni in inaltromargine incorniciato \
-incrementanumero indentation indestra ininner iniziaallineamento \
-iniziaambiente iniziabloccomargine iniziacitazione iniziacodifica iniziacolonne \
-iniziacolore iniziacombinazione iniziacomponente iniziacorrezioneriga iniziadocumento \
-iniziafigura iniziaglobale iniziagruppocolonne iniziaimpaccato inizialineamargine \
-inizialineatesto inizialocale iniziamakeup inizianotepdplocali inizianumerazionerighe \
-iniziaopposto iniziaoverview iniziapiustretto iniziaposizionamento iniziaprodotto \
-iniziaprofilo iniziaprogetto iniziaraster iniziariga iniziarighe \
-iniziasetsimboli iniziasfondo iniziasincronizzazione iniziasovrapposizione iniziatabella \
-iniziatabelle iniziatesto iniziaunpacked iniziaversione inlatodestro \
-inlatosinistro inmaframed inmargine inmarginedestro inmarginesinistro \
-inneredgedistance inneredgewidth innermargindistance innermarginwidth inouter \
-inriga insinistra installalingua intorno labeling \
-leg lettera lettere lineamargine lineanera \
-lineasottile lineatesto lineenere lineeriempimento lineesottili \
-lingua linguaprincipale listsymbol livellotesta loadsorts \
-loadsynonyms logcampi lunghezzaelenco maframed mapfontsize \
-mar marcatura marcaversione matematica mediaeval \
-menuinterattivo menzione mese mettielenco mettielencocombinato \
-mettifiancoafianco mettiformula mettiingriglia mettilegenda mettilinea \
-mettiloghi mettinotepdp mettinotepdplocali mettinumeropagina mettiregistro \
-mettisegnalibro mettisottoformula mettiunosullaltro mettivariabiletesto mostraambientefontdeltesto \
-mostracampi mostracolore mostracornice mostrafiguresterne mostrafontdeltesto \
-mostragriglia mostragruppocolori mostraimpostazioni mostralyout mostramakeup \
-mostrasetsimboli mostrastampa mostrastruts mostratavolozza movesidefloat \
-name nascondiblocchi navigating nextsection nientedimensioni \
-nienteelenco nientelineecimafondo nientelineintestazionepdp nientemarcatura nienterientro \
-nientespazio nientespaziobianco nocap nome nomeunita \
-nop nota notapdp notest numberofsubpages \
-numeri numeriromani numeroformula numeropagina numeropaginacompleto \
-numerosottoformula numerotesta numerotestacorrente numerototaledipagine outeredgedistance \
-outeredgewidth outermargindistance outermarginwidth overbar overbars \
-overstrike overstrikes pagedepth pageoffset pagina \
-paragraph paroladestra parolainmargine part passaafontgrezzo \
-ped pedap perlungo placefloat placelistoffloats \
-placelistofsorts placelistofsynonyms placerawlist placereferencelist posizionanumerotesta \
-posizionatesto posizionatestotesta posizione prendibuffer prendimarcatura \
-prodotto progetto programma pubblicazione pulsante \
-pulsantemenu pulsantinterazione punti qualcheriga ran \
-referral referring register reimposta reimpostamarcatura \
-reservefloat resetnumber resettextcontent rientro rif \
-rifai riferimento riferimentopagina riferimentotesto riflessione \
-rigariempimento rigovuoto ruota saltablocchi scala \
-schermo scrividentroelenco scriviinelenco scriviinlistariferimenti scriviinregistro \
-section seeregister segnalibro seguiprofilo seguiversione \
-seguiversioneprofilo selezionablocchi selezionacarta selezionaversione separamarcatura \
-setnumber settext setupanswerarea setupcolumnsetlines setupcolumnsetstart \
-setupfonthandling setupfontsynonym setupindentedtext setupinterlinespace2 setupitemgroup \
-setuplistalternative setupmathalignment setuppaper setupplacement setvariabiletesto \
-sfondo sim simbolo sincronizza sort \
-spazifissi spazio spaziobianco spaziocima spaziodietro \
-spaziofisso spaziofondo spessoreriga spezzaoggettomobile spostaagriglia \
-spostaformula stackcampi startalignment startambiente startbuffer \
-startcitazione startcolore startcolumnmakeup startcolumns startcombination \
-startcomment startcomponenet startdescription startdocument startenumeration \
-startfatto startfigure startfloattext startformula startframedtext \
-starthiding startimpaccato startitemgroup startlegend startline \
-startlineamargine startlineatesto startlinecorrection startlinenumbering startlines \
-startlocal startlocalenvironment startlocalfootnotes startmakeup startmarginblock \
-startmenuinterattivo startnamemakeup startnarrower startopposite startoverlay \
-startoverview startparagraph startpositioning startpostponing startprodotto \
-startprofile startprogetto startregister startsfondo startsymbolset \
-startsynchronization starttable starttables starttabulate starttyping \
-startunpacked startversione stirato stopalignment stopambiente \
-stopbuffer stopcitazione stopcolore stopcolumnmakeup stopcolumns \
-stopcombination stopcomment stopcomponenet stopdescription stopdocument \
-stopenumeration stopfatto stopfigure stopfloattext stopformula \
-stopframedtext stophiding stopimpaccato stopitemgroup stoplegend \
-stopline stoplineamargine stoplineatesto stoplinecorrection stoplinenumbering \
-stoplines stoplocal stoplocalenvironment stoplocalfootnotes stopmakeup \
-stopmarginblock stopmenuinterattivo stopnamemakeup stopnarrower stopopposite \
-stopoverlay stopoverview stopparagraph stoppositioning stoppostponing \
-stopprodotto stopprofile stopprogetto stopsfondo stopsymbolset \
-stopsynchronization stoptable stoptables stoptabulate stoptyping \
-stopunpacked stopversione sub subject subpagenumber \
-subsection subsubject subsubsection subsubsubject synonym \
-tab terminaallineamento terminaambiente terminabloccomargine terminacitazione \
-terminacodifica terminacolonne terminacolore terminacombinazione terminacomponente \
-terminacorrezioneriga terminadocumento terminaglobale terminagruppocolonne terminaimpaccato \
-terminalineamargine terminalineatesto terminalocale terminamakeup terminanotepdplocali \
-terminanumerazionerighe terminaopposto terminaoverview terminapiustretto terminaposizionamento \
-terminaprodotto terminaprofili terminaprogetto terminaraster terminariga \
-terminarighe terminasfondo terminasincronizzazione terminasovrapposizione terminatabella \
-terminatabelle terminatesto terminaunpacked terminaversioni testa \
-testcolumn testoetichetta testoinmargine testoinstestazioni testonotapdp \
-testoriempimento testpage tex tieniblocchi title \
-titoloinmargine tooltip traduci txt typ \
-type typebuffer typefile underbar underbars \
-usaJSscripts usaURL usablocco usacartella usacodifica \
-usacolonnasonoraesterna usacomandi usadocumentoesterno usafiguraesterna usafileesterni \
-usafileesterno usamoduli usamodulo usariferimenti usasimboli \
-usaspecialita usaurl useXMLfilter usedirectory usetypescript \
-usetypescriptfile vaia vaiabox vaiapagina vaigiu \
-valorecolore valoregrigio variabiletesto versione vl
-
-keywordclass.context.fr=\
-CAP Cap Caps Caractere \
-Caracteres Chiffresromains JOURSEMAINE MOIS MOT \
-MOTS Mot Mots Numeros a \
-adaptedisposition affectenumero affectevariabletexte ajustechamp alaligne \
-alapage aligneadroite aligneagauche aligneaumilieu appendix \
-arg arriereplan atleftmargin atrightmargin baha \
-barrecouleur barreinteraction barresynchronisation bas bouton \
-boutonmenu boutonsinteraction but cacheblocs cap \
-caractere caracteres champ changepolicebrute changepolicecorps \
-chapter chem chiffresromains citation citer \
-clip clonechamp colonne comment commentaire \
-comparegroupecouleur comparepalette completecombinedlist completelistoffloats completelistofsorts \
-completelistofsynonyms completenumeropage completeregistre composant composeenalinea \
-concernant convertitnumero copitchamp corrigeespaceblanc couleur \
-couleurgrise coupledocument coupledregister couplemarquage couplepapier \
-coupleregistre crlf cutspace dactylographier dans \
-dansautremarge dansborddroit dansbordgauche dansdroite dansgauche \
-dansmarge dansmargedroite dansmargegauche date datecourante \
-daterecommandation de decouplemarquage decrementenumero definebodyfontDEF \
-definebodyfontREF definecombination definedfont definefontfeature definefonthandling \
-defineframed defineframedtext defineindentedtext defineitemgroup definemathalignment \
-defineplacement definetypeface definicaractere definit definitaccent \
-definitbloc definitblocsection definitbuffer definitcalque definitchamp \
-definitchampprincipal definitcommande definitconversion definitcouleur definitdactylo \
-definitdansmarge definitdemarrestoppe definitdescription definitdisposition definitenumeration \
-definitenvironnementpolicecorps definitetiquette definitflottant definitformatreference definitgroupecouleur \
-definithbox definitjeucolonne definitliste definitlisteimbriquee definitlistereference \
-definitlogo definitmakeup definitmarquage definitmenuinteraction definitnotepdp \
-definitpalette definitparagraphes definitpilechamp definitpolice definitpolicebrute \
-definitpolicecorps definitpositiontexte definitprofil definitprogramme definitreference \
-definitregistre definitregle definitrevetement definitsautdecolonne definitsautdepage \
-definitsection definitsortie definitsouschamp definitstyle definitstylepolice \
-definitsymbole definitsymbolefigure definitsynonymepolice definitsynonymes definittabulation \
-definittaillepapier definittete definittexte definittrametableau definittri \
-definittype definitvariabletexte definitversion definitvide demarrealignement \
-demarrearriereplan demarreblocmarge demarrecitation demarreciter demarrecodage \
-demarrecolonnes demarrecombinaison demarrecompoetroite demarrecomposant demarrecorrectionligne \
-demarrecouleur demarredegroupe demarredocument demarreenvironement demarrefigure \
-demarreglobal demarregroupe demarrejeucolonne demarrejeusymboles demarreligne \
-demarreligneregleetexte demarrelignes demarrelocal demarremakeup demarremargereglee \
-demarrenotespdplocales demarrenumerotationligne demarreopposition demarrepositionnement demarreproduit \
-demarreprofil demarreprojet demarreraster demarrerevetement demarresynchronisation \
-demarretableau demarretableaux demarretexte demarreversion demarrevuedensemble \
-deplaceformule deplacesurgrille description determinecaracteristiqueliste determinecaracteristiquesregistre \
-determinenumerotete dimension distancebord distanceborddroit distancebordgauche \
-distanceentete distanceinf distancemarge distancemargedroite distancemargegauche \
-distancepdp distancesup domicile echelle ecran \
-ecritdansliste ecritdanslistereference ecritentreliste ecritregistre el \
-element elements emptylines enumeration environement \
-espace espaceblanc espacefixe espaceinf espacesfixes \
-espacesup etiquette etiquettes etire fait \
-faitreference fichierdactylo figureexterne forceblocs fraction \
-framed framedtext gardeblocs getnumber grille \
-groupe haut hauteureditionpapier hauteurentete hauteurinf \
-hauteurliste hauteurmakeup hauteurpapier hauteurpdp hauteursup \
-hauteurtexte headsym hl immediatebetweenlist immediatetolist \
-inconnu incrementenumero indentation inframed infull \
-inhibemenuinteraction ininner inmframed inneredgedistance inneredgewidth \
-innermargindistance innermarginwidth inouter installelangue joursemaine \
-labeling labeltexte langue langueprincipale largeurbord \
-largeurborddroit largeurbordgauche largeureditionpapier largeurligne largeurliste \
-largeurmakeup largeurmarge largeurmargedroite largeurmargegauche largeurpapier \
-largeurtexte leg ligneh lignenoire ligneregleetexte \
-lignesnoires listesymbole llongueurliste loadsorts loadsynonyms \
-logchamp mapfontsize mar margereglee marquage \
-marquageversion marquepage mathematique mediaeval menuinteraction \
-mframed mois montrecadre montrechamps montrecouleur \
-montredisposition montreedition montreenvironnementpolicecorps montrefiguresexternes montregrille \
-montregroupecouleur montrejeusymboles montremakeup montrepalette montrepolicecorps \
-montrereglages montrestruts motdroit motmarge movesidefloat \
-name navigating nextsection niveautete nocap \
-nombredesouspages nombretotaldepages nommacro nop note \
-notepdp numeroformule numeropage numeros numerosousformule \
-numerotete numerotetecourant obtientmarquage oriente outeredgedistance \
-outeredgewidth outermargindistance outermarginwidth overbar overbars \
-overstrike overstrikes page pagedepth pagedouble \
-pageoffset paragraph part pasplusdeblocs pasplusdefichiers \
-periodes pilechamp placecoteacote placeflottant placeformule \
-placelegende placelesunsaudessusdesautres placeliste placelisteinmbriquee placelistereference \
-placelistoffloats placelistofsorts placelistofsynonyms placelogos placemarquespages \
-placenotespdp placenotespdplocales placenumeropage placenumerotete placerawlist \
-placeregistre placeregle placesousformule placesurgrille placetextetete \
-placevariabletexte position positionnetexte prendbuffer produit \
-programme projet publication qqpart ran \
-raz razmarquage raznumero recommandation ref \
-refait reference referencepage referencetexte reflete \
-register reglages reglealignement reglearrangement reglearriereplan \
-reglearriereplans reglebarreinteraction reglebarresynchronisation reglebloc regleblocmarge \
-regleblocsection regleboutons reglebuffer reglecapitales reglechamp \
-reglechamps regleclipping reglecolonnes reglecombinaisons reglecommentaire \
-reglecommentairepage reglecompoetroite reglecomposeenalinea reglecouleur reglecouleurs \
-regledactylo regledansmarge regledemarrestoppe regledescriptions regledisposition \
-regleecraninteraction regleecrans regleelements regleencadre regleentete \
-regleenumerations regleenvironnementpolicecorps regleepaisseurligne regleespaceblanc regleespacement \
-regleespacementinterligne reglefiguresexternes regleflottant regleflottants regleformulaires \
-regleformules reglegroupeselements regleinf regleinteraction regleintitule \
-regleintitules reglejeucolonne reglejeusymboles reglelabeltexte reglelangue \
-reglelegende reglelignes reglelignesnoires reglelignesreglestexte regleliste \
-reglelisteimbriquee reglelistereference reglemakeup reglemargereglee reglemarquage \
-reglemarquagehyphenation reglemenuinteraction reglenotepdp reglenumero reglenumeropage \
-reglenumerotation reglenumerotationligne reglenumerotationpage reglenumerotationparagraphe reglenumerotete \
-regleoriente reglepalette reglepapier regleparagraphes reglepdp \
-regleplacementopposition reglepolicecorps reglepositionnement reglepositiontexte regleprofils \
-regleprogrammes reglepublications reglereferencage regleregistre regleregle \
-regleremplitligne regleremplitlignesreglees reglesection regleseparationflottant reglesortie \
-reglesouslignage reglesousnumeropage reglestrut reglesup reglesynchronisation \
-reglesynonymes reglesysteme regletab regletableaux regletabulation \
-regletaillepapier regletete regletetes regletexte regletextesentete \
-regletextesinf regletextespdp regletextessup regletextestexte regletextetete \
-regletolerance regletraitsfins regletransitionspage regletri regletype \
-regleurl reglevariabletexte regleversions remplitchamp remplitligne \
-remplitlignesreglees remplittexte reservefloat resettextcontent retourarriere \
-sansalinea sansdimension sansespace sansespaceblanc sanslignesenteteetpdp \
-sanslignessupetinf sansliste sansmarquage sanstest sauteblocs \
-section seeregister selectionneblocs selectionnepapier selectionneversion \
-sensunite separeflottant settext setupanswerarea setupcolumnsetlines \
-setupcolumnsetstart setupfonthandling setupfontsynonym setupframedtexts setupindentedtext \
-setupinterlinespace2 setupitemgroup setuplistalternative setupmathalignment setupplacement \
-sort sousnumeropage startalignment startarriereplan startbuffer \
-startcitation startcolumnmakeup startcolumns startcombination startcomment \
-startcomposant startcouleur startdescription startdocument startenumeration \
-startenvironement startfait startfigure startfloattext startformula \
-startframedtext startgroupe starthiding startitemgroup startlegend \
-startligneregleetexte startline startlinecorrection startlinenumbering startlines \
-startlocal startlocalenvironment startlocalfootnotes startmakeup startmargereglee \
-startmarginblock startmenuinteraction startnamemakeup startnarrower startopposite \
-startoverlay startoverview startparagraph startpositioning startpostponing \
-startproduit startprofile startprojet startregister startsymbolset \
-startsynchronization starttable starttables starttabulate starttyping \
-startunpacked startversion stopalignment stoparriereplan stopbuffer \
-stopcitation stopcolumnmakeup stopcolumns stopcombination stopcomment \
-stopcompoetroite stopcomposant stopcouleur stopdescription stopdocument \
-stopenumeration stopenvironement stopfait stopfigure stopfloattext \
-stopformula stopframedtext stopgroupe stophiding stopitemgroup \
-stoplegend stopligneregleetexte stopline stoplinecorrection stoplinenumbering \
-stoplines stoplocal stoplocalenvironment stoplocalfootnotes stopmakeup \
-stopmargereglee stopmarginblock stopmenuinteraction stopnamemakeup stopnarrower \
-stopopposite stopoverlay stopoverview stopparagraph stoppealignement \
-stoppearriereplan stoppeblocmarge stoppecitation stoppecodage stoppecolonnes \
-stoppecombinaison stoppecomposant stoppecorrectionligne stoppecouleur stoppedegroupe \
-stoppedocument stoppeenvironement stoppeglobal stoppegroupe stoppejeucolonne \
-stoppeligne stoppeligneregleetexte stoppelignes stoppelocal stoppemakeup \
-stoppemargereglee stoppenotespdplocales stoppenumerotationligne stoppeopposition stoppepositionnement \
-stoppeproduit stoppeprofil stoppeprojet stopperaster stopperevetement \
-stoppesynchronisation stoppetableau stoppetableaux stoppetexte stoppeversion \
-stoppevuedensemble stoppositioning stoppostponing stopproduit stopprofile \
-stopprojet stopsymbolset stopsynchronization stoptable stoptables \
-stoptabulate stoptyping stopunpacked stopversion sub \
-subject subsection subsubject subsubsection subsubsubject \
-suggestion suivantprofil suivantversion suivantversionprofil sym \
-symbole synchronise synonym tab tapebuffer \
-testcolumn testpage tete tex textemarge \
-textenotepdp textetete title titremarge traduire \
-traiteblocs traitepage traitfin traitsfins txt \
-typ underbar underbars uneligne useXMLfilter \
-usedirectory usetypescript usetypescriptfile utiliseJSscripts utiliseURL \
-utiliseblocs utilisechemin utilisecommandes utilisedocumentexterne utiliseencodage \
-utilisefichierexterne utilisefichiersexternes utilisefigureexterne utilisemodule utilisemodules \
-utilisepsiteaudioexterne utilisereferences utilisespecialites utilisesymboles utiliseurl \
-va vaalaboite vaalapage vaenbas valeurcouleur \
-valeurgris variabletexte version vide vl
-
-keywordclass.context.de=\
-Buchstabe Buchstaben CAP Cap \
-Caps KAP Kap Kaps MONAT \
-Roemischezahlen WOCHENTAG WOERTER WORT Woerter \
-Wort Ziffern abstandlinkerrand abstandoben abstandrechterrand \
-abstandunten amgitterausrichten amgitterneuausrichten appendix arg \
-atleftmargin atrightmargin aufseite ausfuellfeld ausfuelltext \
-ausschnitt bearbeitebloecke bearbeiteseite bedeutung behaltebloecke \
-bei bemerkung benutzekodierung benutzespezielles benutzeverzeichnis \
-beschrifteversion beschriftung bestimmekopfnummer bestimmelistencharakeristika bestimmeregistercharakteristika \
-bildschirm blanko bookmark bottomspace breitelinkerrand \
-breiterechterrand bruch buchstabe buchstaben but \
-bypassblocks cap chapter chem comment \
-completecombinedlist completelistoffloats completelistofsorts completelistofsynonyms completepagenumber \
-completeregister coupledregister crlf cutspace datum \
-decrementnumber definebodyfontDEF definebodyfontREF definecolumnbreak definecolumnset \
-definecombination definedfont definefontfeature definefonthandling defineindentedtext \
-defineinmargin defineitemgroup definelayer definelayout definemathalignment \
-defineoutput definepagebreak defineplacement definerawfont definerule \
-defineschriftsynonym definetextposition definetextvariable definetype definetypeface \
-definiereabbsymbol definiereabsaetze definiereabschnitt definiereabschnittsblock definiereakzent \
-definierebefehl definierebeschreibung definierebeschreibungen definierebeschriftung definiereblanko \
-definiereblock definierefarbe definierefarbengruppe definierefeld definierefeldstapel \
-definierefliesstext definierefliesstextumgebung definieregleitobjekt definierehauptfeld definierehbox \
-definiereinteraktionsmenue definierekonversion definierelabel definiereliste definierelogo \
-definieren definierenummerierung definiereoverlay definierepalette definierepapierformat \
-definiereprofil definiereprogramme definierepuffer definierereferenz definierereferenzformat \
-definierereferenzliste definiereregister definiereschrift definiereschriftstil definieresortieren \
-definierestartstop definierestil definieresubfeld definieresymbol definieresynonyme \
-definieretabellenvorlage definieretabulator definieretext definieretippen definiereueberschrift \
-definiereumbruch definiereumrahmt definiereumrahmtertext definiereversion definierezeichen \
-definierezusammengestellteliste description dimension doppelseite doppelseitigespapier \
-drehen duennelinie duennerumriss einezeile einstellungen \
-einziehen emptylines entknuepfebeschriftung enumeration externeabbildung \
-farbbalken farbe farbewert feld feldstapel \
-festesspatium folgeprofil folgeprofilversion folgeversion footnotetext \
-forceblocks format formelnummer framedtext fussnote \
-fusszeileabstand fusszeilenhoehe gefuelltesrechteck gefuelltezeile geg \
-gesamtseitenanzahl gestreckt getnumber gitter graufarbe \
-grauwert haarlinie hauptsprache headsym heutigesdatum \
-heutigeskopfnummer hintergrund hl hoch hoeheoben \
-hoeheunten holebeschriftung holepuffer imlinken imlinkenrand \
-immaumrise immediatebetweenlist immediatetolist imrechten imrechtenrand \
-imumriss in inaktiviereinteraktionsmenue inanderermarginale indentation \
-ininner inlinkermarginale inmarginalie inneredgedistance inneredgewidth \
-innermargindistance innermarginwidth inouter inrechtermarginale installieresprache \
-interaktionsbalken interaktionsknopfe interaktionsmenue inzeile irgendwo \
-its kap keindimension keinebeschriftung keinebloeckemehr \
-keinedateienmehr keinekopfundfusszeilen keineliste keinspatium keintest \
-keinzeilenobenundunten keinzwischenraum kleinerdurchschuss klonierefeld knopf \
-komponente konvertierezahl kopf kopfniveau kopfnummer \
-kopfweite kopfzeilenabstand kopfzeilenhoehe kopierefeld korrigierezwischenraum \
-label labeling labels labeltext leg \
-liniendicke linkemarginalafstand linkemarginalbreite linksbuendig listenbreite \
-listenhoehe listenlaenge listsymbol loadsorts loadsynonyms \
-mapfontsize mar marginalafstand marginalbreite marginallinie \
-marginaltext marginaltitel marginalwort mathematik maumrise \
-mediaeval menueknopf monat moveformula movesidefloat \
-nachunten name navigating nextsection nichteinziehen \
-nocap nokap nop notiz numberofsubpages \
-nummererhoehen outeredgedistance outeredgewidth outermargindistance outermarginwidth \
-overbar overbars overstrike overstrikes pagedepth \
-pageoffset papierbreite papierhoehe paragraph part \
-passelayoutan passendfeld placefloat placeheadnumber placeheadtext \
-placelistoffloats placelistofsorts placelistofsynonyms placepagenumber placerawlist \
-placereferencelist placerule placetextvariable platzierebookmarks platziereformel \
-platzierefussnoten platzierelegende platziereliste platzierelogo platzierelokalefussnoten \
-platzierenebeneinander platziereregister platziereuntereinander platziereunterformel platzierezusammengestellteliste \
-pos position positiontext posten printpapierbreite \
-printpapierhoehe produkt programm projekt publikation \
-punkt ran randabstand randbreite rechteck \
-rechtecke rechtemarginalafstand rechtemarginalbreite rechtsbuendig ref \
-referenz referieren register registrierefelder reservefloat \
-resetnumber resettextcontent roemischezahlen ruecksetzten ruecksetztenbeschriftung \
-rumpfweite satzbreite satzhoehe schreibezumregister schreibezurliste \
-schreibezurreferenzliste schreibezwischenliste section seeregister seite \
-seitenreferenz seitenummer setnumber settext settextvariable \
-setupanswerarea setupcolumnset setupcolumnsetlines setupcolumnsetstart setupfonthandling \
-setupfontsynonym setupforms setupindentedtext setupinterlinespace2 setupitemgroup \
-setuplistalternative setupmathalignment setupnumber setuppaper setupplacement \
-setuprule setupstartstop setupstrut setuptextposition setuptextvariable \
-showsymbolset sort spalte spatium spiegeln \
-sprache startabbildung startalignment startausrichtung startbuffer \
-startcolumnmakeup startcolumns startcolumnset startcombination startcomment \
-startdescription startdocument startdokument startenger startenumeration \
-startfarbe startfigure startfloattext startformula startframedtext \
-startgeg startgegenueber startglobal startgrosserdurchschuss starthiding \
-starthintergrund startinteraktionsmenue startitemgroup startkleinerdurchschuss startkodierung \
-startkombination startkomponente startlegend startline startlinecorrection \
-startlinenumbering startlines startlocal startlocalenvironment startlocalfootnotes \
-startlokal startlokalefussnoten startmakeup startmarginalblock startmarginallinie \
-startmarginblock startnamemakeup startnarrower startopposite startoverlay \
-startoverview startparagraph startpositionieren startpositioning startpostponing \
-startprodukt startprofil startprofile startprojekt startraster \
-startregister startspalten startsymbolset startsynchronisation startsynchronization \
-starttabelle starttabellen starttable starttables starttabulate \
-starttext starttextlinie starttyping startueberblick startumbruch \
-startumgebung startunpacked startversion startzeile startzeilen \
-startzeilenkorrektur startzeilennumerierung startzitat stelleabsaetzeein stelleabsatznummerierungein \
-stelleabschnittein stelleabschnittsblockein stelleanordnenein stelleaufzaehlungenein stelleausgabeein \
-stelleausrichtungein stelleausschnittein stellebeschreibungein stellebeschriftungein stellebilderunterschriftein \
-stellebildunterschriftein stellebindestrichein stelleblankoein stelleblockein stelledrehenein \
-stelleduennerumrissein stelleeinziehenein stelleengerein stelleexterneabbildungenein stellefarbeein \
-stellefarbenein stellefeldein stellefelderin stellefliesstextein stellefliesstextumgebungein \
-stelleformelnein stellefussnotendefinitionein stellefussnotenein stellefusszeileein stellefusszeilentextein \
-stellegefuelltesrechteckein stellegefuelltezeileein stellegegenueberplatzierenein stellegleitobjekteein stellegleitobjektein \
-stellehintergruendeein stellehintergrundein stelleinmarginalieein stelleinteraktionein stelleinteraktionsbalkenein \
-stelleinteraktionsbildschirmein stelleinteraktionsmenueein stelleknopfein stellekombinationein stellekommentarein \
-stellekopfzahlein stellekopfzeileein stellekopfzeilentextein stellelabeltextein stellelayoutein \
-stellelegendeein stellelinienbreiteein stellelisteein stellemarginalblockein stellemarginallinieein \
-stellenobenein stellenummerierungein stellepaletteein stellepapierformatein stelleplatziegeteiltegleitobjekt \
-stellepositionierenein stellepostenein stelleprofilein stelleprogrammein stellepublikationein \
-stellepufferein stellerasterein stellerechteckein stellereferenzierenein stellereferenzlisteein \
-stelleregisterein stelleseitenkommentarein stelleseitennummerein stelleseitennummeriernungein stelleseitenuebergangein \
-stellesortierenein stellespaltenein stellespatiumein stellespracheein stellesymbolsetein \
-stellesynchronisationein stellesynchronisationsbalkenein stellesynonymein stellesystemein stelletabein \
-stelletabellenein stelletabulatorein stelletextein stelletextobenein stelletexttexteein \
-stelletextumrissein stelletextuntenein stelletipein stelletippenein stelletoleranzein \
-stelleueberschriftein stelleueberschriftenein stelleueberschrifttextein stelleumbruchein stelleumrahmtein \
-stelleumrahmtetexteein stelleuntenein stelleunterseitennummerein stelleunterstreichenein stelleurlein \
-stelleversalienein stelleversionein stellezeilenabstandein stellezeilenein stellezeilennumerierungein \
-stellezitierenein stellezusammengestelltelisteein stellezwischenraumein stopalignment stopausrichtung \
-stopbuffer stopcolumnmakeup stopcolumns stopcolumnset stopcombination \
-stopcomment stopdescription stopdocument stopdokument stopenger \
-stopenumeration stopfarbe stopfigure stopfloattext stopformula \
-stopframedtext stopgeg stopgegenueber stopglobal stopgrosserdurchschuss \
-stophiding stophintergrund stopinteraktionsmenue stopitemgroup stopkleinerdurchschuss \
-stopkodierung stopkombination stopkomponente stoplegend stopline \
-stoplinecorrection stoplinenumbering stoplines stoplocal stoplocalenvironment \
-stoplocalfootnotes stoplokal stoplokalefussnoten stopmakeup stopmarginalblock \
-stopmarginallinie stopmarginblock stopnamemakeup stopnarrower stopopposite \
-stopoverlay stopoverview stopparagraph stoppositionieren stoppositioning \
-stoppostponing stopprodukt stopprofil stopprofile stopprojekt \
-stopraster stopspalten stopsymbolset stopsynchronisation stopsynchronization \
-stoptabelle stoptabellen stoptable stoptables stoptabulate \
-stoptext stoptextlinie stoptyping stopueberblick stopumbruch \
-stopumgebung stopunpacked stopversion stopzeile stopzeilen \
-stopzeilenkorrektur stopzeilennumerierung stopzitat sub subject \
-subpagenumber subsection subsubject subsubsection subsubsubject \
-switchtorawfont sym symbol synchronisationsbalken synchronisieren \
-synonym tab teilegleitobjekt testcolumn testpage \
-tex textbreite texthoehe textlinie textreferenz \
-textvariable tief tiho tip tippedatei \
-tippen tippepuffer title tooltip txt \
-ueber ueberschrifttext uebersetzten umgebung umrahmt \
-unbekant underbar underbars unterformelnummer useXMLfilter \
-usedirectory usetypescript usetypescriptfile verbergebloecke vergleichefarbengruppe \
-vergleichepalette verknuepfebeschriftung verknuepfedokument verknuepfregister version \
-verweis verweisdatum verwendeJSscript verwendeURL verwendebefehl \
-verwendebloecke verwendeexteresdokument verwendeexterneabbildung verwendeexternedatei verwendeexternedateien \
-verwendeexternestonstueck verwendemodul verwendemodule verwendereferenzen verwendesymbole \
-verwendeurl vl volleswort von waehlebloeckeaus \
-waehlepapieraus waehleversionaus wechselezumfliesstext wiederholen wochentag \
-wohnort wortrechts zeigedruck zeigeeinstellungen zeigeexterneabbildungen \
-zeigefarbe zeigefarbengruppe zeigefelder zeigefliesstext zeigefliesstextumgebung \
-zeigegitter zeigelayout zeigepalette zeigerahmen zeigestruts \
-zeigeumbruch zentriert ziffern zitat zitieren \
-zu zurbox zurseite zwischenraum
-
keywordclass.context.cs=\
CAP Cap Caps Cisla \
KAP Kap Kaps MESIC Rimskecislice \
@@ -643,6 +158,165 @@ ziskejbuffer ziskejznaceni zlomek znaceni znak \
znaky zpracujbloky zpracujstranu zrcadlit zref \
zvysujicicislo
+keywordclass.context.de=\
+Buchstabe Buchstaben CAP Cap \
+Caps KAP Kap Kaps MONAT \
+Roemischezahlen WOCHENTAG WOERTER WORT Woerter \
+Wort Ziffern abstandlinkerrand abstandoben abstandrechterrand \
+abstandunten amgitterausrichten amgitterneuausrichten appendix arg \
+atleftmargin atrightmargin aufseite ausfuellfeld ausfuelltext \
+ausschnitt bearbeitebloecke bearbeiteseite bedeutung behaltebloecke \
+bei bemerkung benutzekodierung benutzespezielles benutzeverzeichnis \
+beschrifteversion beschriftung bestimmekopfnummer bestimmelistencharakeristika bestimmeregistercharakteristika \
+bildschirm blanko bookmark bottomspace breitelinkerrand \
+breiterechterrand bruch buchstabe buchstaben but \
+bypassblocks cap chapter chem comment \
+completecombinedlist completelistoffloats completelistofsorts completelistofsynonyms completepagenumber \
+completeregister coupledregister crlf cutspace datum \
+decrementnumber definebodyfontDEF definebodyfontREF definecolumnbreak definecolumnset \
+definecombination definedfont definefontfeature definefonthandling defineindentedtext \
+defineinmargin defineitemgroup definelayer definelayout definemathalignment \
+defineoutput definepagebreak defineplacement definerawfont definerule \
+defineschriftsynonym definetextposition definetextvariable definetype definetypeface \
+definiereabbsymbol definiereabsaetze definiereabschnitt definiereabschnittsblock definiereakzent \
+definierebefehl definierebeschreibung definierebeschreibungen definierebeschriftung definiereblanko \
+definiereblock definierefarbe definierefarbengruppe definierefeld definierefeldstapel \
+definierefliesstext definierefliesstextumgebung definieregleitobjekt definierehauptfeld definierehbox \
+definiereinteraktionsmenue definierekonversion definierelabel definiereliste definierelogo \
+definieren definierenummerierung definiereoverlay definierepalette definierepapierformat \
+definiereprofil definiereprogramme definierepuffer definierereferenz definierereferenzformat \
+definierereferenzliste definiereregister definiereschrift definiereschriftstil definieresortieren \
+definierestartstop definierestil definieresubfeld definieresymbol definieresynonyme \
+definieretabellenvorlage definieretabulator definieretext definieretippen definiereueberschrift \
+definiereumbruch definiereumrahmt definiereumrahmtertext definiereversion definierezeichen \
+definierezusammengestellteliste description dimension doppelseite doppelseitigespapier \
+drehen duennelinie duennerumriss einezeile einstellungen \
+einziehen emptylines entknuepfebeschriftung enumeration externeabbildung \
+farbbalken farbe farbewert feld feldstapel \
+festesspatium folgeprofil folgeprofilversion folgeversion footnotetext \
+forceblocks format formelnummer framedtext fussnote \
+fusszeileabstand fusszeilenhoehe gefuelltesrechteck gefuelltezeile geg \
+gesamtseitenanzahl gestreckt getnumber gitter graufarbe \
+grauwert haarlinie hauptsprache headsym heutigesdatum \
+heutigeskopfnummer hintergrund hl hoch hoeheoben \
+hoeheunten holebeschriftung holepuffer imlinken imlinkenrand \
+immaumrise immediatebetweenlist immediatetolist imrechten imrechtenrand \
+imumriss in inaktiviereinteraktionsmenue inanderermarginale indentation \
+ininner inlinkermarginale inmarginalie inneredgedistance inneredgewidth \
+innermargindistance innermarginwidth inouter inrechtermarginale installieresprache \
+interaktionsbalken interaktionsknopfe interaktionsmenue inzeile irgendwo \
+its kap keindimension keinebeschriftung keinebloeckemehr \
+keinedateienmehr keinekopfundfusszeilen keineliste keinspatium keintest \
+keinzeilenobenundunten keinzwischenraum kleinerdurchschuss klonierefeld knopf \
+komponente konvertierezahl kopf kopfniveau kopfnummer \
+kopfweite kopfzeilenabstand kopfzeilenhoehe kopierefeld korrigierezwischenraum \
+label labeling labels labeltext leg \
+liniendicke linkemarginalafstand linkemarginalbreite linksbuendig listenbreite \
+listenhoehe listenlaenge listsymbol loadsorts loadsynonyms \
+mapfontsize mar marginalafstand marginalbreite marginallinie \
+marginaltext marginaltitel marginalwort mathematik maumrise \
+mediaeval menueknopf monat moveformula movesidefloat \
+nachunten name navigating nextsection nichteinziehen \
+nocap nokap nop notiz numberofsubpages \
+nummererhoehen outeredgedistance outeredgewidth outermargindistance outermarginwidth \
+overbar overbars overstrike overstrikes pagedepth \
+pageoffset papierbreite papierhoehe paragraph part \
+passelayoutan passendfeld placefloat placeheadnumber placeheadtext \
+placelistoffloats placelistofsorts placelistofsynonyms placepagenumber placerawlist \
+placereferencelist placerule placetextvariable platzierebookmarks platziereformel \
+platzierefussnoten platzierelegende platziereliste platzierelogo platzierelokalefussnoten \
+platzierenebeneinander platziereregister platziereuntereinander platziereunterformel platzierezusammengestellteliste \
+pos position positiontext posten printpapierbreite \
+printpapierhoehe produkt programm projekt publikation \
+punkt ran randabstand randbreite rechteck \
+rechtecke rechtemarginalafstand rechtemarginalbreite rechtsbuendig ref \
+referenz referieren register registrierefelder reservefloat \
+resetnumber resettextcontent roemischezahlen ruecksetzten ruecksetztenbeschriftung \
+rumpfweite satzbreite satzhoehe schreibezumregister schreibezurliste \
+schreibezurreferenzliste schreibezwischenliste section seeregister seite \
+seitenreferenz seitenummer setnumber settext settextvariable \
+setupanswerarea setupcolumnset setupcolumnsetlines setupcolumnsetstart setupfonthandling \
+setupfontsynonym setupforms setupindentedtext setupinterlinespace2 setupitemgroup \
+setuplistalternative setupmathalignment setupnumber setuppaper setupplacement \
+setuprule setupstartstop setupstrut setuptextposition setuptextvariable \
+showsymbolset sort spalte spatium spiegeln \
+sprache startabbildung startalignment startausrichtung startbuffer \
+startcolumnmakeup startcolumns startcolumnset startcombination startcomment \
+startdescription startdocument startdokument startenger startenumeration \
+startfarbe startfigure startfloattext startformula startframedtext \
+startgeg startgegenueber startglobal startgrosserdurchschuss starthiding \
+starthintergrund startinteraktionsmenue startitemgroup startkleinerdurchschuss startkodierung \
+startkombination startkomponente startlegend startline startlinecorrection \
+startlinenumbering startlines startlocal startlocalenvironment startlocalfootnotes \
+startlokal startlokalefussnoten startmakeup startmarginalblock startmarginallinie \
+startmarginblock startnamemakeup startnarrower startopposite startoverlay \
+startoverview startparagraph startpositionieren startpositioning startpostponing \
+startprodukt startprofil startprofile startprojekt startraster \
+startregister startspalten startsymbolset startsynchronisation startsynchronization \
+starttabelle starttabellen starttable starttables starttabulate \
+starttext starttextlinie starttyping startueberblick startumbruch \
+startumgebung startunpacked startversion startzeile startzeilen \
+startzeilenkorrektur startzeilennumerierung startzitat stelleabsaetzeein stelleabsatznummerierungein \
+stelleabschnittein stelleabschnittsblockein stelleanordnenein stelleaufzaehlungenein stelleausgabeein \
+stelleausrichtungein stelleausschnittein stellebeschreibungein stellebeschriftungein stellebilderunterschriftein \
+stellebildunterschriftein stellebindestrichein stelleblankoein stelleblockein stelledrehenein \
+stelleduennerumrissein stelleeinziehenein stelleengerein stelleexterneabbildungenein stellefarbeein \
+stellefarbenein stellefeldein stellefelderin stellefliesstextein stellefliesstextumgebungein \
+stelleformelnein stellefussnotendefinitionein stellefussnotenein stellefusszeileein stellefusszeilentextein \
+stellegefuelltesrechteckein stellegefuelltezeileein stellegegenueberplatzierenein stellegleitobjekteein stellegleitobjektein \
+stellehintergruendeein stellehintergrundein stelleinmarginalieein stelleinteraktionein stelleinteraktionsbalkenein \
+stelleinteraktionsbildschirmein stelleinteraktionsmenueein stelleknopfein stellekombinationein stellekommentarein \
+stellekopfzahlein stellekopfzeileein stellekopfzeilentextein stellelabeltextein stellelayoutein \
+stellelegendeein stellelinienbreiteein stellelisteein stellemarginalblockein stellemarginallinieein \
+stellenobenein stellenummerierungein stellepaletteein stellepapierformatein stelleplatziegeteiltegleitobjekt \
+stellepositionierenein stellepostenein stelleprofilein stelleprogrammein stellepublikationein \
+stellepufferein stellerasterein stellerechteckein stellereferenzierenein stellereferenzlisteein \
+stelleregisterein stelleseitenkommentarein stelleseitennummerein stelleseitennummeriernungein stelleseitenuebergangein \
+stellesortierenein stellespaltenein stellespatiumein stellespracheein stellesymbolsetein \
+stellesynchronisationein stellesynchronisationsbalkenein stellesynonymein stellesystemein stelletabein \
+stelletabellenein stelletabulatorein stelletextein stelletextobenein stelletexttexteein \
+stelletextumrissein stelletextuntenein stelletipein stelletippenein stelletoleranzein \
+stelleueberschriftein stelleueberschriftenein stelleueberschrifttextein stelleumbruchein stelleumrahmtein \
+stelleumrahmtetexteein stelleuntenein stelleunterseitennummerein stelleunterstreichenein stelleurlein \
+stelleversalienein stelleversionein stellezeilenabstandein stellezeilenein stellezeilennumerierungein \
+stellezitierenein stellezusammengestelltelisteein stellezwischenraumein stopalignment stopausrichtung \
+stopbuffer stopcolumnmakeup stopcolumns stopcolumnset stopcombination \
+stopcomment stopdescription stopdocument stopdokument stopenger \
+stopenumeration stopfarbe stopfigure stopfloattext stopformula \
+stopframedtext stopgeg stopgegenueber stopglobal stopgrosserdurchschuss \
+stophiding stophintergrund stopinteraktionsmenue stopitemgroup stopkleinerdurchschuss \
+stopkodierung stopkombination stopkomponente stoplegend stopline \
+stoplinecorrection stoplinenumbering stoplines stoplocal stoplocalenvironment \
+stoplocalfootnotes stoplokal stoplokalefussnoten stopmakeup stopmarginalblock \
+stopmarginallinie stopmarginblock stopnamemakeup stopnarrower stopopposite \
+stopoverlay stopoverview stopparagraph stoppositionieren stoppositioning \
+stoppostponing stopprodukt stopprofil stopprofile stopprojekt \
+stopraster stopspalten stopsymbolset stopsynchronisation stopsynchronization \
+stoptabelle stoptabellen stoptable stoptables stoptabulate \
+stoptext stoptextlinie stoptyping stopueberblick stopumbruch \
+stopumgebung stopunpacked stopversion stopzeile stopzeilen \
+stopzeilenkorrektur stopzeilennumerierung stopzitat sub subject \
+subpagenumber subsection subsubject subsubsection subsubsubject \
+switchtorawfont sym symbol synchronisationsbalken synchronisieren \
+synonym tab teilegleitobjekt testcolumn testpage \
+tex textbreite texthoehe textlinie textreferenz \
+textvariable tief tiho tip tippedatei \
+tippen tippepuffer title tooltip txt \
+ueber ueberschrifttext uebersetzten umgebung umrahmt \
+unbekant underbar underbars unterformelnummer useXMLfilter \
+usedirectory usetypescript usetypescriptfile verbergebloecke vergleichefarbengruppe \
+vergleichepalette verknuepfebeschriftung verknuepfedokument verknuepfregister version \
+verweis verweisdatum verwendeJSscript verwendeURL verwendebefehl \
+verwendebloecke verwendeexteresdokument verwendeexterneabbildung verwendeexternedatei verwendeexternedateien \
+verwendeexternestonstueck verwendemodul verwendemodule verwendereferenzen verwendesymbole \
+verwendeurl vl volleswort von waehlebloeckeaus \
+waehlepapieraus waehleversionaus wechselezumfliesstext wiederholen wochentag \
+wohnort wortrechts zeigedruck zeigeeinstellungen zeigeexterneabbildungen \
+zeigefarbe zeigefarbengruppe zeigefelder zeigefliesstext zeigefliesstextumgebung \
+zeigegitter zeigelayout zeigepalette zeigerahmen zeigestruts \
+zeigeumbruch zentriert ziffern zitat zitieren \
+zu zurbox zurseite zwischenraum
+
keywordclass.context.en=\
CAP Cap Caps Character \
Characters MONTH Numbers Romannumerals WEEKDAY \
@@ -779,340 +453,345 @@ stopsymbolset stopsynchronization stoptable stoptables stoptabulate \
stoptext stoptextrule stoptyping stopunpacked stopversion \
stretched sub subformulanumber subject subpagenumber \
subsection subsubject subsubsection subsubsubject switchtobodyfont \
-switchtorawfont sym symbol synchronizationbar synchronize \
-synonym tab testcolumn testpage tex \
-textheight textreference textrule textvariable textwidth \
-thinrule thinrules title tooltip topdistance \
-topheight topspace totalnumberofpages translate txt \
-typ type typebuffer typefile underbar \
-underbars unitmeaning unknown useJSscripts useURL \
-useXMLfilter useblocks usecommands usedirectory useencoding \
-useexternaldocument useexternalfigure useexternalfile useexternalfiles useexternalsoundtrack \
-usemodule usemodules usereferences usespecials usesymbols \
-usetypescript usetypescriptfile useurl version vl \
-weekday whitespace wordright writebetweenlist writetolist \
-writetoreferencelist writetoregister
+switchtorawfont sym symbol symoffset synchronizationbar \
+synchronize synonym tab testcolumn testpage \
+tex textheight textreference textrule textvariable \
+textwidth thinrule thinrules title tooltip \
+topdistance topheight topspace totalnumberofpages translate \
+txt typ type typebuffer typefile \
+underbar underbars unitmeaning unknown useJSscripts \
+useURL useXMLfilter useblocks usecommands usedirectory \
+useencoding useexternaldocument useexternalfigure useexternalfile useexternalfiles \
+useexternalsoundtrack usemodule usemodules usereferences usespecials \
+usesymbols usetypescript usetypescriptfile useurl version \
+vl weekday whitespace wordright writebetweenlist \
+writetolist writetoreferencelist writetoregister
-keywordclass.context.ro=\
-CAP CUVANT CUVINTE Cap \
-Caps Cuvant Cuvinte KAP Kap \
-Kaps LUNA Litera Litere Numere \
-Numereromane ZIDINSAPTAMANA adapteazaaspect adubuffer adumarcaje \
-afiseazaaspect afiseazacampuri afiseazaculoare afiseazafiguriexterne afiseazafonttext \
-afiseazagrid afiseazagrupculoare afiseazamakeup afiseazamediufonttext afiseazapaleta \
-afiseazarama afiseazasetari afiseazasetsimboluri afiseazastruts afiseazatiparire \
-aliniat aliniatcentru aliniatdreapta aliniatstanga appendix \
-arg ascundeblocuri atleftmargin atrightmargin baraculoare \
-barainteractiune barasincronizare blanc but butoaneinteractiune \
-buton butonmeniu camp campumplere cap \
-chapter chem citat clip cloneazacamp \
-coloana comment comparagrupculoare comparapaleta completeazanumarpagina \
-completecombinedlist completelistoffloats completelistofsorts completelistofsynonyms completeregister \
-componenta convertestenumar copiazacamp corecteazaspatiualb coupledregister \
-crlf culoare culoaregri cupleazadocument cupleazamarcaje \
-cupleazaregistru cutspace cuvantdreapta cuvantmarginal data \
-datacurenta datareferit decrementnumber decupleazamarcaje definebodyfontDEF \
-definebodyfontREF definecolumnbreak definecolumnset definecombination definedfont \
-definefontfeature definefonthandling defineindentedtext defineinmargin defineitemgroup \
-definelayer definelayout definemathalignment definepagebreak defineplacement \
-defineste definesteaccent definesteantet definesteblanc definestebloc \
-definesteblocsectiune definestebuffer definestecamp definestecampprincipal definestecaracter \
-definestecomanda definesteconversie definesteculoare definestedescriere definestedimensiunehartie \
-definesteenumerare definesteeticheta definestefloat definestefont definestefontraw \
-definestefonttext definesteformatreferinte definestegrupculori definestehbox definesteinconjurare \
-definestelista definestelistacombinata definestelistareferinte definestelogo definestemakeup \
-definestemarcaje definestemediulfonttext definestemeniuinteractiune definesteoutput definesteoverlay \
-definestepaleta definesteparagraf definestepozitietext definesteprofil definesteprogram \
-definestereferinte definesteregistru definesterigla definestesablontabel definestesectiune \
-definestesimbol definestesimbolfigura definestesinonim definestesinonimfont definestesortare \
-definestestartstop definestestil definestestilfont definestestivacampuri definestesubcamp \
-definestetabulatori definestetext definestetexteinconjurate definestetextinconjurat definestetyping \
-definestevariabilatext definesteversiune definetype definetypeface description \
-despre determinacaracteristicilelistei determinacaracteristiciregistru determinanumartitlu dezactiveazameniuinteractiune \
-dimensiune din distantaantet distantacolt distantacoltdreapta \
-distantacoltstanga distantajos distantamargine distantamarginedreapta distantamarginestanga \
-distantasubsol distantasus domiciliu dute dutebox \
-dutepagina ecran el element emptylines \
-enumeration eticheta etichete fact faraaliniat \
-faradimensiune farafisiere faraliniiantetsisubsol faraliniisussijos faralista \
-faramarcaje faraspatiu faraspatiualb figuraexterna firdepar \
-folosesteURL folosestebloc folosestecodificarea folosestecomenzi folosestedirector \
-folosestedocumentextern folosestefiguraexterna folosestefisiereexterne folosestefisierextern folosestemodul \
-folosestemodule folosestemuzicaexterna folosestereferinte folosestescriptJS folosestesimboluri \
-folosestespeciale folosesteurl footnotetext forteazablocuri fractie \
-framed framedtext fundal gatablocuri getnumber \
-grid grosimelinie hartiedubla headsym hl \
-immediatebetweenlist immediatetolist impachetat impartefloat in \
-inalt inaltamargine inaltimeantet inaltimehartie inaltimehartieimprimanta \
-inaltimejos inaltimelista inaltimemakeup inaltimesubsol inaltimesus \
-inaltimetext indentation indreapta inframed ininner \
-injos inlinie inmaframed inmargineadreapta inmargineastanga \
-inneredgedistance inneredgewidth innermargindistance innermarginwidth inouter \
-inparteadreapta inparteastanga instalarelimba instanga intins \
-jos jossus kap la labeling \
-lapagina latimecoltdreapta latimecoltstanga latimecolturi latimehartie \
-latimehartieimprimanta latimelista latimemakeup latimemargine latimemarginedreapta \
-latimemarginestanga latimetext leg limba limbaprincipala \
-liniemargine linieneagra liniesubtire linieumplere liniinegre \
-liniisubtiri listsymbol litera litere loadsorts \
-loadsynonyms logcampuri luna lungimelista maframed \
-mapfontsize mar marcaje marcheazaversiune marginal \
-matematica mediaeval mediu meniuinteractiune minicitat \
-moveformula movesidefloat mutapegrid name navigating \
-necunoscut nextsection niveltitlu nocap nokap \
-nop nota notasubsol numarformula numarincrement \
-numarpagina numarsubformula numartitlu numartitlucurent numartotalpagini \
-numberofsubpages nume numere numereromane numeunitate \
-nutesta olinie outeredgedistance outeredgewidth outermargindistance \
-outermarginwidth overbar overbars overstrike overstrikes \
-pagedepth pageoffset pagina paginadubla paragraph \
-part pastreazablocuri pelung placefloat placeheadnumber \
-placeheadtext placelistoffloats placelistofsorts placelistofsynonyms placerawlist \
-placereferencelist plaseazapegrid plaseazasemnecarte potrivestecamp pozitie \
-pozitietext proceseazabloc proceseazapagina produs program \
-proiect publicatie puncte punedeasuprafiecareia punefatainfata \
-puneformula punelegenda punelista punelistacombinata punelogouri \
-punenotesubsol punenotesubsollocale punenumarpagina puneregistru punerigla \
-punesubformula punevariabilatext ran ref refa \
-referinta referintapagina referintatext referit referring \
-reflexie register remarca reservefloat reset \
-reseteazamarcaje resetnumber resettextcontent riglatext rigleumplere \
-roteste saripesteblocuri scala scriebuffer scrieinlista \
-scrieinlistareferinte scrieinregistru scrieintreliste section seeregister \
-selecteazablocuri selecteazahartie selecteazaversiune semncarte setarebarasincronizare \
-setareitemization setarelimba setareoutput setarepozitie setaresincronizare \
-setari seteazaaliniat seteazaalinierea seteazaantet seteazaaranjareapag \
-seteazaaspect seteazabarainteractiune seteazablanc seteazabloc seteazablocsectiune \
-seteazablocurimarginale seteazabuffer seteazabutoane seteazacamp seteazacampuri \
-seteazaclipping seteazacoloane seteazacombinari seteazacomentariu seteazacomentariupagina \
-seteazaculoare seteazaculori seteazadefinireanotasubsol seteazadescriere seteazadimensiunihartie \
-seteazaecrane seteazaecraninteractiune seteazaelemente seteazaenumerare seteazafiguriexterne \
-seteazafloat seteazafloats seteazafonttext seteazaformulare seteazaformule \
-seteazafundal seteazafundaluri seteazagrosimelinie seteazaimpartireafloat seteazainconjurat \
-seteazaingust seteazainteractiunea seteazajos seteazalegenda seteazalegendele \
-seteazaliniesilabe seteazaliniesubtire seteazalinii seteazaliniimargine seteazaliniinegre \
-seteazaliniiumplere seteazalista seteazalistacombinata seteazalistareferinte seteazamajuscule \
-seteazamakeup seteazamarcaje seteazamarginal seteazamediulfonttext seteazameniuinteractiune \
-seteazaminicitat seteazanotasubsol seteazanumarpagina seteazanumarsubpagina seteazanumartitlu \
-seteazanumerotare seteazanumerotarelinii seteazanumerotarepagina seteazanumerotareparagrafe seteazapaleta \
-seteazaparagrafe seteazaplasareaopozita seteazapozitietext seteazaprofile seteazaprograme \
-seteazapublicatii seteazareferinte seteazaregistru seteazarigla seteazarigletext \
-seteazarigleumplere seteazarotare seteazasectiune seteazasimbol seteazasinonime \
-seteazasistem seteazasortare seteazaspatiu seteazaspatiualb seteazaspatiuinterliniar \
-seteazastrut seteazasublinie seteazasubsol seteazasus seteazatab \
-seteazatabele seteazatabulatori seteazatext seteazatexteantet seteazatextejos \
-seteazatextesubsol seteazatextesus seteazatextetext seteazatexteticheta seteazatexttitlu \
-seteazatitlu seteazatitluri seteazatoleranta seteazatranzitiepagina seteazatype \
-seteazatyping seteazaurl seteazavariabilatext seteazaversiuni setnumber \
-settextcontent setupanswerarea setupcolumnset setupcolumnsetlines setupcolumnsetstart \
-setupfonthandling setupfontsynonym setupindentedtext setupinterlinespace2 setupitemgroup \
-setuplistalternative setupmathalignment setupnumber setuppaper setupplacement \
-setupstartstop setvariabilatext sim simbol sincronizeaza \
-sort spatiifixate spatiu spatiualb spatiufixat \
-spatiujos spatiuspate spatiusus startalignment startaliniere \
-startblocmarginal startbuffer startcitat startcodificare startcoloane \
-startcolumnmakeup startcolumns startcolumnset startcombinare startcombination \
-startcomment startcomponenta startcorectielinie startculoare startdescription \
-startdocument startenumeration startfact startfigura startfigure \
-startfloattext startformula startframedtext startfundal startglobal \
-starthiding startimpachetat startingust startitemgroup startlegend \
-startline startlinecorrection startlinenumbering startlines startlinie \
-startliniemargine startlinii startlocal startlocalenvironment startlocalfootnotes \
-startmakeup startmarginblock startmediu startmeniuinteractiune startnamemakeup \
-startnarrower startneimpachetat startnotesubsollocale startnumerotarelinii startopozit \
-startopposite startoverlay startoverview startparagraph startpositioning \
-startpostponing startpozitionare startprodus startprofil startprofile \
-startproiect startraster startregister startriglatext startsetsimboluri \
-startsincronizare startsymbolset startsynchronization starttabel starttabele \
-starttable starttables starttabulate starttext starttyping \
-startunpacked startversiune stivacampuri stopalignment stopaliniere \
-stopblobal stopblocmarginal stopbuffer stopcitat stopcodificare \
-stopcoloane stopcolumnmakeup stopcolumns stopcolumnset stopcombinare \
-stopcombination stopcomment stopcomponenta stopcorectielinie stopculoare \
-stopdescription stopdocument stopenumeration stopfact stopfigure \
-stopfloattext stopformula stopframedtext stopfundal stophiding \
-stopimpachetat stopingust stopitemgroup stoplegend stopline \
-stoplinecorrection stoplinenumbering stoplines stoplinie stopliniemargine \
-stoplinii stoplocal stoplocalenvironment stoplocalfootnotes stopmakeup \
-stopmarginblock stopmediu stopmeniuinteractiune stopnamemakeup stopnarrower \
-stopneimpachetat stopnotesubsollocale stopnumerotarelinii stopopozit stopopposite \
-stopoverlay stopoverview stopparagraph stoppositioning stoppostponing \
-stoppozitionare stopprodus stopprofil stopprofile stopproiect \
-stopraster stopriglatext stopsincronizare stopsymbolset stopsynchronization \
-stoptabel stoptabele stoptable stoptables stoptabulate \
-stoptext stoptyping stopunpacked stopversiune sub \
-subject subpagenumber subsection subsubject subsubsection \
-subsubsubject synonym tab testcolumn testpage \
-tex texteticheta textmarginal texttitlu textumplere \
-title titlu titlumarginal tooltip traduce \
-trecilafontraw trecilafonttext txt typ type \
-typefile underbar underbars undeva urmeazaprofil \
-urmeazaversiune urmeazaversiuneprofil useXMLfilter usedirectory usetypescript \
-usetypescriptfile valoareculoare valoaregri variabilatext versiune \
-vl zidinsaptamana
+keywordclass.context.fr=\
+CAP Cap Caps Caractere \
+Caracteres Chiffresromains JOURSEMAINE MOIS MOT \
+MOTS Mot Mots Numeros a \
+adaptedisposition affectenumero affectevariabletexte ajustechamp alaligne \
+alapage aligneadroite aligneagauche aligneaumilieu appendix \
+arg arriereplan atleftmargin atrightmargin baha \
+barrecouleur barreinteraction barresynchronisation bas bouton \
+boutonmenu boutonsinteraction but cacheblocs cap \
+caractere caracteres champ changepolicebrute changepolicecorps \
+chapter chem chiffresromains citation citer \
+clip clonechamp colonne comment commentaire \
+comparegroupecouleur comparepalette completecombinedlist completelistoffloats completelistofsorts \
+completelistofsynonyms completenumeropage completeregistre composant composeenalinea \
+concernant convertitnumero copitchamp corrigeespaceblanc couleur \
+couleurgrise coupledocument coupledregister couplemarquage couplepapier \
+coupleregistre crlf cutspace dactylographier dans \
+dansautremarge dansborddroit dansbordgauche dansdroite dansgauche \
+dansmarge dansmargedroite dansmargegauche date datecourante \
+daterecommandation de decouplemarquage decrementenumero definebodyfontDEF \
+definebodyfontREF definecombination definedfont definefontfeature definefonthandling \
+defineframed defineframedtext defineindentedtext defineitemgroup definemathalignment \
+defineplacement definetypeface definicaractere definit definitaccent \
+definitbloc definitblocsection definitbuffer definitcalque definitchamp \
+definitchampprincipal definitcommande definitconversion definitcouleur definitdactylo \
+definitdansmarge definitdemarrestoppe definitdescription definitdisposition definitenumeration \
+definitenvironnementpolicecorps definitetiquette definitflottant definitformatreference definitgroupecouleur \
+definithbox definitjeucolonne definitliste definitlisteimbriquee definitlistereference \
+definitlogo definitmakeup definitmarquage definitmenuinteraction definitnotepdp \
+definitpalette definitparagraphes definitpilechamp definitpolice definitpolicebrute \
+definitpolicecorps definitpositiontexte definitprofil definitprogramme definitreference \
+definitregistre definitregle definitrevetement definitsautdecolonne definitsautdepage \
+definitsection definitsortie definitsouschamp definitstyle definitstylepolice \
+definitsymbole definitsymbolefigure definitsynonymepolice definitsynonymes definittabulation \
+definittaillepapier definittete definittexte definittrametableau definittri \
+definittype definitvariabletexte definitversion definitvide demarrealignement \
+demarrearriereplan demarreblocmarge demarrecitation demarreciter demarrecodage \
+demarrecolonnes demarrecombinaison demarrecompoetroite demarrecomposant demarrecorrectionligne \
+demarrecouleur demarredegroupe demarredocument demarreenvironement demarrefigure \
+demarreglobal demarregroupe demarrejeucolonne demarrejeusymboles demarreligne \
+demarreligneregleetexte demarrelignes demarrelocal demarremakeup demarremargereglee \
+demarrenotespdplocales demarrenumerotationligne demarreopposition demarrepositionnement demarreproduit \
+demarreprofil demarreprojet demarreraster demarrerevetement demarresynchronisation \
+demarretableau demarretableaux demarretexte demarreversion demarrevuedensemble \
+deplaceformule deplacesurgrille description determinecaracteristiqueliste determinecaracteristiquesregistre \
+determinenumerotete dimension distancebord distanceborddroit distancebordgauche \
+distanceentete distanceinf distancemarge distancemargedroite distancemargegauche \
+distancepdp distancesup domicile echelle ecran \
+ecritdansliste ecritdanslistereference ecritentreliste ecritregistre el \
+element elements emptylines enumeration environement \
+espace espaceblanc espacefixe espaceinf espacesfixes \
+espacesup etiquette etiquettes etire fait \
+faitreference fichierdactylo figureexterne forceblocs fraction \
+framed framedtext gardeblocs getnumber grille \
+groupe haut hauteureditionpapier hauteurentete hauteurinf \
+hauteurliste hauteurmakeup hauteurpapier hauteurpdp hauteursup \
+hauteurtexte headsym hl immediatebetweenlist immediatetolist \
+inconnu incrementenumero indentation inframed infull \
+inhibemenuinteraction ininner inmframed inneredgedistance inneredgewidth \
+innermargindistance innermarginwidth inouter installelangue joursemaine \
+labeling labeltexte langue langueprincipale largeurbord \
+largeurborddroit largeurbordgauche largeureditionpapier largeurligne largeurliste \
+largeurmakeup largeurmarge largeurmargedroite largeurmargegauche largeurpapier \
+largeurtexte leg ligneh lignenoire ligneregleetexte \
+lignesnoires listesymbole llongueurliste loadsorts loadsynonyms \
+logchamp mapfontsize mar margereglee marquage \
+marquageversion marquepage mathematique mediaeval menuinteraction \
+mframed mois montrecadre montrechamps montrecouleur \
+montredisposition montreedition montreenvironnementpolicecorps montrefiguresexternes montregrille \
+montregroupecouleur montrejeusymboles montremakeup montrepalette montrepolicecorps \
+montrereglages montrestruts motdroit motmarge movesidefloat \
+name navigating nextsection niveautete nocap \
+nombredesouspages nombretotaldepages nommacro nop note \
+notepdp numeroformule numeropage numeros numerosousformule \
+numerotete numerotetecourant obtientmarquage oriente outeredgedistance \
+outeredgewidth outermargindistance outermarginwidth overbar overbars \
+overstrike overstrikes page pagedepth pagedouble \
+pageoffset paragraph part pasplusdeblocs pasplusdefichiers \
+periodes pilechamp placecoteacote placeflottant placeformule \
+placelegende placelesunsaudessusdesautres placeliste placelisteinmbriquee placelistereference \
+placelistoffloats placelistofsorts placelistofsynonyms placelogos placemarquespages \
+placenotespdp placenotespdplocales placenumeropage placenumerotete placerawlist \
+placeregistre placeregle placesousformule placesurgrille placetextetete \
+placevariabletexte position positionnetexte prendbuffer produit \
+programme projet publication qqpart ran \
+raz razmarquage raznumero recommandation ref \
+refait reference referencepage referencetexte reflete \
+register reglages reglealignement reglearrangement reglearriereplan \
+reglearriereplans reglebarreinteraction reglebarresynchronisation reglebloc regleblocmarge \
+regleblocsection regleboutons reglebuffer reglecapitales reglechamp \
+reglechamps regleclipping reglecolonnes reglecombinaisons reglecommentaire \
+reglecommentairepage reglecompoetroite reglecomposeenalinea reglecouleur reglecouleurs \
+regledactylo regledansmarge regledemarrestoppe regledescriptions regledisposition \
+regleecraninteraction regleecrans regleelements regleencadre regleentete \
+regleenumerations regleenvironnementpolicecorps regleepaisseurligne regleespaceblanc regleespacement \
+regleespacementinterligne reglefiguresexternes regleflottant regleflottants regleformulaires \
+regleformules reglegroupeselements regleinf regleinteraction regleintitule \
+regleintitules reglejeucolonne reglejeusymboles reglelabeltexte reglelangue \
+reglelegende reglelignes reglelignesnoires reglelignesreglestexte regleliste \
+reglelisteimbriquee reglelistereference reglemakeup reglemargereglee reglemarquage \
+reglemarquagehyphenation reglemenuinteraction reglenotepdp reglenumero reglenumeropage \
+reglenumerotation reglenumerotationligne reglenumerotationpage reglenumerotationparagraphe reglenumerotete \
+regleoriente reglepalette reglepapier regleparagraphes reglepdp \
+regleplacementopposition reglepolicecorps reglepositionnement reglepositiontexte regleprofils \
+regleprogrammes reglepublications reglereferencage regleregistre regleregle \
+regleremplitligne regleremplitlignesreglees reglesection regleseparationflottant reglesortie \
+reglesouslignage reglesousnumeropage reglestrut reglesup reglesynchronisation \
+reglesynonymes reglesysteme regletab regletableaux regletabulation \
+regletaillepapier regletete regletetes regletexte regletextesentete \
+regletextesinf regletextespdp regletextessup regletextestexte regletextetete \
+regletolerance regletraitsfins regletransitionspage regletri regletype \
+regleurl reglevariabletexte regleversions remplitchamp remplitligne \
+remplitlignesreglees remplittexte reservefloat resettextcontent retourarriere \
+sansalinea sansdimension sansespace sansespaceblanc sanslignesenteteetpdp \
+sanslignessupetinf sansliste sansmarquage sanstest sauteblocs \
+section seeregister selectionneblocs selectionnepapier selectionneversion \
+sensunite separeflottant settext setupanswerarea setupcolumnsetlines \
+setupcolumnsetstart setupfonthandling setupfontsynonym setupframedtexts setupindentedtext \
+setupinterlinespace2 setupitemgroup setuplistalternative setupmathalignment setupplacement \
+sort sousnumeropage startalignment startarriereplan startbuffer \
+startcitation startcolumnmakeup startcolumns startcombination startcomment \
+startcomposant startcouleur startdescription startdocument startenumeration \
+startenvironement startfait startfigure startfloattext startformula \
+startframedtext startgroupe starthiding startitemgroup startlegend \
+startligneregleetexte startline startlinecorrection startlinenumbering startlines \
+startlocal startlocalenvironment startlocalfootnotes startmakeup startmargereglee \
+startmarginblock startmenuinteraction startnamemakeup startnarrower startopposite \
+startoverlay startoverview startparagraph startpositioning startpostponing \
+startproduit startprofile startprojet startregister startsymbolset \
+startsynchronization starttable starttables starttabulate starttyping \
+startunpacked startversion stopalignment stoparriereplan stopbuffer \
+stopcitation stopcolumnmakeup stopcolumns stopcombination stopcomment \
+stopcompoetroite stopcomposant stopcouleur stopdescription stopdocument \
+stopenumeration stopenvironement stopfait stopfigure stopfloattext \
+stopformula stopframedtext stopgroupe stophiding stopitemgroup \
+stoplegend stopligneregleetexte stopline stoplinecorrection stoplinenumbering \
+stoplines stoplocal stoplocalenvironment stoplocalfootnotes stopmakeup \
+stopmargereglee stopmarginblock stopmenuinteraction stopnamemakeup stopnarrower \
+stopopposite stopoverlay stopoverview stopparagraph stoppealignement \
+stoppearriereplan stoppeblocmarge stoppecitation stoppecodage stoppecolonnes \
+stoppecombinaison stoppecomposant stoppecorrectionligne stoppecouleur stoppedegroupe \
+stoppedocument stoppeenvironement stoppeglobal stoppegroupe stoppejeucolonne \
+stoppeligne stoppeligneregleetexte stoppelignes stoppelocal stoppemakeup \
+stoppemargereglee stoppenotespdplocales stoppenumerotationligne stoppeopposition stoppepositionnement \
+stoppeproduit stoppeprofil stoppeprojet stopperaster stopperevetement \
+stoppesynchronisation stoppetableau stoppetableaux stoppetexte stoppeversion \
+stoppevuedensemble stoppositioning stoppostponing stopproduit stopprofile \
+stopprojet stopsymbolset stopsynchronization stoptable stoptables \
+stoptabulate stoptyping stopunpacked stopversion sub \
+subject subsection subsubject subsubsection subsubsubject \
+suggestion suivantprofil suivantversion suivantversionprofil sym \
+symbole synchronise synonym tab tapebuffer \
+testcolumn testpage tete tex textemarge \
+textenotepdp textetete title titremarge traduire \
+traiteblocs traitepage traitfin traitsfins txt \
+typ underbar underbars uneligne useXMLfilter \
+usedirectory usetypescript usetypescriptfile utiliseJSscripts utiliseURL \
+utiliseblocs utilisechemin utilisecommandes utilisedocumentexterne utiliseencodage \
+utilisefichierexterne utilisefichiersexternes utilisefigureexterne utilisemodule utilisemodules \
+utilisepsiteaudioexterne utilisereferences utilisespecialites utilisesymboles utiliseurl \
+va vaalaboite vaalapage vaenbas valeurcouleur \
+valeurgris variabletexte version vide vl
-keywordclass.context.pe=\
-CAP Cap Caps Character \
-Characters MONTH Numbers Romannumerals WEEKDAY \
-WORD WORDS Word Words appendix \
-cap chapter chem comment completecombinedlist \
-completelistoffloats completelistofsorts completelistofsynonyms coupledregister crlf \
-definebodyfontDEF definebodyfontREF definedfont definefontfeature definefonthandling \
-defineindentedtext definetypeface description enumeration framedtext \
-indentation inmframed its labeling loadsorts \
-loadsynonyms mapfontsize mediaeval mframed name \
-nextsection nocap overbar overbars overstrike \
-overstrikes paragraph part placelistoffloats placelistofsorts \
-placelistofsynonyms ran register reservefloat resettextcontent \
-section seeregister setupanswerarea setupcapitals setupfonthandling \
-setupfontsynonym setupindentedtext setupinterlinespace2 setuplistalternative setupurl \
-sort startalignment startbuffer startcolumns startcombination \
-startcomment startdescription startdocument startenumeration startfigure \
-startfloattext startformula startframedtext starthiding startitemgroup \
-startlegend startline startlinecorrection startlinenumbering startlines \
+keywordclass.context.it=\
+CAP Cap Caps GIORNOSETTIMANA \
+Lettera Lettere MESE Numeri Numeriromani \
+PAROLA PAROLE Parola Parole accoppiacarta \
+accoppiadocumento accoppiamarcatura accoppiapagina accoppiaregistro adattacampo \
+adattalayout al allineacentro allineadestra allineasinistra \
+altezzacarta altezzacartastampa altezzacima altezzaelenco altezzafondo \
+altezzaintestazione altezzamakeup altezzapdp altezzatesto ambiente \
+ampiezzabordo ampiezzabordodestro ampiezzabordosinistro ampiezzacarta ampiezzacartastampa \
+ampiezzaelenco ampiezzamakeup ampiezzamargine ampiezzamarginedestro ampiezzamarginesinistro \
+ampiezzatesto ap apagina appendix arg \
+atleftmargin atrightmargin barracolori barrainterazione barrasincronizzazione \
+bastablocchi bastafile cambiaafontdeltesto campi camporiempimento \
+cap capello chapter chim circondato \
+citazione clip clonacampo colonna colore \
+coloregrigio comment commento completecombinedlist completelistoffloats \
+completelistofsorts completelistofsynonyms completeregister componenet confrontagruppocolori \
+confrontatavolozza convertinumero copiacampo correggispaziobianco coupledregister \
+crlf cutspace da daqualcheparte data \
+datadioggi datareferral decrementnumber definebodyfontDEF definebodyfontREF \
+definecolumnbreak definecombination definedfont definefontfeature definefonthandling \
+defineindentedtext defineinmargin defineitemgroup definelayer definemathalignment \
+definepagebreak defineplacement definetypeface definisci definisciaccento \
+definisciambientefontdeltesto definisciblocco definiscibloccosezione definiscibuffer definiscicampo \
+definiscicampoprincipale definiscicapoversi definiscicarattere definiscicolore definiscicomando \
+definisciconversione definiscidescrizione definiscidimensionicarta definiscielenco definiscielencocombinato \
+definiscienumerazione definiscietichetta definiscifigurasimbolo definiscifont definiscifontdeltesto \
+definiscifontgrezzo definisciformatoriferimento definiscigruppocolonne definiscigruppocolori definiscihbox \
+definisciincorniciato definisciiniziatermina definiscilayout definiscilinea definiscilistariferimenti \
+definiscilogo definiscimakeup definiscimarcatura definiscimenuinterazione definiscimodellotabella \
+definiscioggettomobile definisciordinamento definiscioutput definisciposizionetesto definisciprofilo \
+definisciprogramma definisciregistro definisciriferimento definiscirigovuoto definiscisezione \
+definiscisimbolo definiscisinonimi definiscisinonimofont definiscisottocampo definiscisovrapposizione \
+definiscistackcampi definiscistile definiscistilefont definiscitabulato definiscitavolozza \
+definiscitesta definiscitesto definiscitestoincorniciato definiscitype definiscityping \
+definiscivariabiletesto definisciversion description determinacaratteristicheregistro determinacarattersticheelenco \
+determinanumerotesta dimensione disabilitamenuinterazione distanzabordo distanzabordodestro \
+distanzabordosinistro distanzacima distanzafondo distanzaintestazione distanzamargine \
+distanzamarginedestro distanzamarginesinistro distanzapdp domicilio el \
+elaborablocchi elaborapagina elementi elemento emptylines \
+enumeration etichetta etichette fatto figuraesterna \
+fondo forzablocchi framedtext frazione getnumber \
+giornosettimana griglia headsym hl ignoto \
+immediatebetweenlist immediatetolist impaccato impostaallineamento impostaambientefontdeltesto \
+impostaampiezzariga impostabarrainterazione impostabarrasincronizzazione impostablocchimargine impostablocco \
+impostabloccosezione impostabuffer impostacampi impostacampo impostacapoversi \
+impostacaption impostacaptions impostacima impostaclippling impostacolonne \
+impostacolore impostacolori impostacombinazioni impostacommento impostacommentopagina \
+impostadefinizionenotepdp impostadescrizioni impostadimensionicarta impostaelementi impostaelencazioni \
+impostaelenco impostaelencocombinato impostaenumerazioni impostafigureesterne impostafondo \
+impostafontdeltesto impostaforms impostaformule impostagruppocolonne impostaincorniciato \
+impostainiziatermina impostainmargine impostainstestazione impostainterazione impostainterlinea \
+impostalayout impostalegenda impostalinea impostalineemargine impostalineenere \
+impostalineeriempimento impostalineesottili impostalineetesto impostalingua impostalistariferimenti \
+impostamaiuscole impostamakeup impostamarcatura impostamenuinterazione impostamenzione \
+impostanotepdp impostanumerazione impostanumerazionecapoversi impostanumerazionepagina impostanumerazionerighe \
+impostanumeropagina impostanumerosottopagina impostanumerotesta impostaoggettimobili impostaoggettomobile \
+impostaordinamento impostaoutput impostaparranging impostapdp impostapiustretto \
+impostaposizionamento impostaposizionamentoopposti impostaposizionetesto impostaprofili impostaprogrammi \
+impostapubblicazioni impostapulsanti impostaregistro impostarientro impostariferimento \
+impostarighe impostarigheriempimento impostarigovuoto impostarotazione impostaschermi \
+impostaschermointerazione impostasegnosillabazione impostasetsimboli impostasezione impostasfondi \
+impostasfondo impostasincronizzazione impostasinonimi impostasistema impostasottolinea \
+impostaspaziatura impostaspaziobianco impostaspezzamentooggettomobile impostastrut impostatab \
+impostatabelle impostatabulato impostatavolozza impostatesta impostateste \
+impostatesticima impostatestifondo impostatestiincorniciati impostatestiintestazioni impostatestipdp \
+impostatesto impostatestoetichette impostatestointestazioni impostatestotesti impostatolleranza \
+impostatransizionepagina impostatype impostatyping impostaurl impostavariabiletesto \
+impostaversioni impostazioni in inaltromargine incorniciato \
+incrementanumero indentation indestra ininner iniziaallineamento \
+iniziaambiente iniziabloccomargine iniziacitazione iniziacodifica iniziacolonne \
+iniziacolore iniziacombinazione iniziacomponente iniziacorrezioneriga iniziadocumento \
+iniziafigura iniziaglobale iniziagruppocolonne iniziaimpaccato inizialineamargine \
+inizialineatesto inizialocale iniziamakeup inizianotepdplocali inizianumerazionerighe \
+iniziaopposto iniziaoverview iniziapiustretto iniziaposizionamento iniziaprodotto \
+iniziaprofilo iniziaprogetto iniziaraster iniziariga iniziarighe \
+iniziasetsimboli iniziasfondo iniziasincronizzazione iniziasovrapposizione iniziatabella \
+iniziatabelle iniziatesto iniziaunpacked iniziaversione inlatodestro \
+inlatosinistro inmaframed inmargine inmarginedestro inmarginesinistro \
+inneredgedistance inneredgewidth innermargindistance innermarginwidth inouter \
+inriga insinistra installalingua intorno labeling \
+leg lettera lettere lineamargine lineanera \
+lineasottile lineatesto lineenere lineeriempimento lineesottili \
+lingua linguaprincipale listsymbol livellotesta loadsorts \
+loadsynonyms logcampi lunghezzaelenco maframed mapfontsize \
+mar marcatura marcaversione matematica mediaeval \
+menuinterattivo menzione mese mettielenco mettielencocombinato \
+mettifiancoafianco mettiformula mettiingriglia mettilegenda mettilinea \
+mettiloghi mettinotepdp mettinotepdplocali mettinumeropagina mettiregistro \
+mettisegnalibro mettisottoformula mettiunosullaltro mettivariabiletesto mostraambientefontdeltesto \
+mostracampi mostracolore mostracornice mostrafiguresterne mostrafontdeltesto \
+mostragriglia mostragruppocolori mostraimpostazioni mostralyout mostramakeup \
+mostrasetsimboli mostrastampa mostrastruts mostratavolozza movesidefloat \
+name nascondiblocchi navigating nextsection nientedimensioni \
+nienteelenco nientelineecimafondo nientelineintestazionepdp nientemarcatura nienterientro \
+nientespazio nientespaziobianco nocap nome nomeunita \
+nop nota notapdp notest numberofsubpages \
+numeri numeriromani numeroformula numeropagina numeropaginacompleto \
+numerosottoformula numerotesta numerotestacorrente numerototaledipagine outeredgedistance \
+outeredgewidth outermargindistance outermarginwidth overbar overbars \
+overstrike overstrikes pagedepth pageoffset pagina \
+paragraph paroladestra parolainmargine part passaafontgrezzo \
+ped pedap perlungo placefloat placelistoffloats \
+placelistofsorts placelistofsynonyms placerawlist placereferencelist posizionanumerotesta \
+posizionatesto posizionatestotesta posizione prendibuffer prendimarcatura \
+prodotto progetto programma pubblicazione pulsante \
+pulsantemenu pulsantinterazione punti qualcheriga ran \
+referral referring register reimposta reimpostamarcatura \
+reservefloat resetnumber resettextcontent rientro rif \
+rifai riferimento riferimentopagina riferimentotesto riflessione \
+rigariempimento rigovuoto ruota saltablocchi scala \
+schermo scrividentroelenco scriviinelenco scriviinlistariferimenti scriviinregistro \
+section seeregister segnalibro seguiprofilo seguiversione \
+seguiversioneprofilo selezionablocchi selezionacarta selezionaversione separamarcatura \
+setnumber settext setupanswerarea setupcolumnsetlines setupcolumnsetstart \
+setupfonthandling setupfontsynonym setupindentedtext setupinterlinespace2 setupitemgroup \
+setuplistalternative setupmathalignment setuppaper setupplacement setvariabiletesto \
+sfondo sim simbolo sincronizza sort \
+spazifissi spazio spaziobianco spaziocima spaziodietro \
+spaziofisso spaziofondo spessoreriga spezzaoggettomobile spostaagriglia \
+spostaformula stackcampi startalignment startambiente startbuffer \
+startcitazione startcolore startcolumnmakeup startcolumns startcombination \
+startcomment startcomponenet startdescription startdocument startenumeration \
+startfatto startfigure startfloattext startformula startframedtext \
+starthiding startimpaccato startitemgroup startlegend startline \
+startlineamargine startlineatesto startlinecorrection startlinenumbering startlines \
startlocal startlocalenvironment startlocalfootnotes startmakeup startmarginblock \
-startnamemakeup startnarrower startopposite startoverlay startoverview \
-startparagraph startpositioning startpostponing startprofile startraster \
-startregister startsymbolset startsynchronization starttable starttables \
-starttabulate starttyping startunpacked startتولید startحقیقت \
-startخطحاشیه startخطمتن startرنگ startفشرده startمحیط \
-startمنویپانل startمولفه startنسخه startنقلقول startپروژه \
-startپسزمینه stopalignment stopbuffer stopcolumns stopcombination \
-stopcomment stopdescription stopdocument stopenumeration stopfigure \
-stopfloattext stopformula stopframedtext stophiding stopitemgroup \
-stoplegend stopline stoplinecorrection stoplinenumbering stoplines \
-stoplocal stoplocalenvironment stoplocalfootnotes stopmakeup stopmarginblock \
-stopnamemakeup stopnarrower stopopposite stopoverlay stopoverview \
-stopparagraph stoppositioning stoppostponing stopprofile stopraster \
-stopsymbolset stopsynchronization stoptable stoptables stoptabulate \
-stoptyping stopunpacked stopتولید stopحقیقت stopخطحاشیه \
-stopخطمتن stopرنگ stopفشرده stopمحیط stopمنویپانل \
-stopمولفه stopنسخه stopنقلقول stopپروژه stopپسزمینه \
-sub subject subsection subsubject subsubsection \
-subsubsubject synonym title tooltip txt \
-typ underbar underbars useJSscripts useURL \
-useXMLfilter usedirectory useurl آفستصفحه آیتم \
-آیتمها آینه اجباربلوکها ارتفاعآرایش ارتفاعبالا \
-ارتفاعبرگ ارتفاعتهبرگ ارتفاعخط ارتفاعسربرگ ارتفاعمتن \
-ارتفاعپایین از ازکارانداختنمنویپانل استفادهبلوکها استفادهدستخطتایپ \
-استفادهرمزینه استفادهشکلخارجی استفادهفرمانها استفادهقطعهموزیکخارجی استفادهمدول \
-استفادهمدولها استفادهمرجعها استفادهمسیر استفادهنمادها استفادهنوشتارخارجی \
-استفادهویژگیها استفادهپروندهخارجی استفادهپروندهدستخطتایپ استفادهپروندههایخارجی اعدادلاتین \
-افزودن اما امتحاننکن انتخاببرگ انتخاببلوکها \
-انتخابنسخه انتقالبهتوری انتقالفرمول انتقالکنارشناور انجامدوباره \
-بارگذاریها بارگذاریآرایش بارگذاریآیتمها بارگذاریارجاع بارگذاریاندازهبرگ \
-بارگذاریباریکتر بارگذاریبافر بارگذاریبالا بارگذاریبخش بارگذاریبردباری \
-بارگذاریبرنامهها بارگذاریبرگ بارگذاریبست بارگذاریبلوک بارگذاریبلوکهایحاشیه \
-بارگذاریبلوکبخش بارگذاریتایپ بارگذاریتایپکردن بارگذاریتب بارگذاریترتیب \
-بارگذاریترکیبها بارگذاریتطابق بارگذاریتعریفپانوشت بارگذاریتنظیم بارگذاریتنظیمریاضی \
-بارگذاریتهبرگ بارگذاریتورفتگی بارگذاریتوضیح بارگذاریتوضیحصفحه بارگذاریثبت \
-بارگذاریجانشانی بارگذاریجدولها بارگذاریجدولبندی بارگذاریخالی بارگذاریخروجی \
-بارگذاریخط بارگذاریخطها بارگذاریخطهایحاشیه بارگذاریخطهایسیاه بارگذاریخطهایمتن \
-بارگذاریخطهایمجموعهستون بارگذاریخطهاینازک بارگذاریدرجدرخطها بارگذاریدرجمخالف بارگذاریدرونحاشیه \
-بارگذاریدوران بارگذاریدکمهها بارگذاریراهنما بارگذاریرنگ بارگذاریرنگها \
-بارگذاریزبان بارگذاریستونها بارگذاریسر بارگذاریسربرگ بارگذاریسرها \
-بارگذاریسیستم بارگذاریشرح بارگذاریشرحها بارگذاریشروعمجموعهستون بارگذاریشروعپایان \
-بارگذاریشماره بارگذاریشمارهزیرصفحه بارگذاریشمارهسر بارگذاریشمارهصفحه بارگذاریشمارهگذاری \
-بارگذاریشمارهگذاریها بارگذاریشمارهگذاریصفحه بارگذاریشمارهگذاریپاراگراف بارگذاریشمارهگذاریخط بارگذاریشناور \
-بارگذاریشناورها بارگذاریشکافتنشناورها بارگذاریشکلهایخارجی بارگذاریطرح بارگذاریطرحبندی \
-بارگذاریعرضخط بارگذاریفاصلهبینخط بارگذاریفرمولها بارگذاریفضایسفید بارگذاریفضاگذاری \
-بارگذاریقالبی بارگذاریقلممتن بارگذاریلوح بارگذاریلیست بارگذاریلیستترکیبی \
-بارگذاریلیستمرجع بارگذاریمترادفها بارگذاریمتغیرمتن بارگذاریمتن بارگذاریمتنهایبالا \
-بارگذاریمتنسر بارگذاریمتنسربرگ بارگذاریمتنقالبی بارگذاریمتنمتنها بارگذاریمتنپانوشت \
-بارگذاریمتنپایین بارگذاریمجموعهستون بارگذاریمجموعهنماد بارگذاریمحیطقلممتن بارگذاریمنویپانل \
-بارگذاریمکانمتن بارگذاریمکانگذاری بارگذاریمیدان بارگذاریمیدانها بارگذاریمیلهتطابق \
-بارگذاریمیلهزیر بارگذاریمیلهپانل بارگذارینسخهها بارگذارینشانهشکستن بارگذارینشانهگذاری \
-بارگذارینشرها بارگذارینقل بارگذاریپاراگرافها بارگذاریپانل بارگذاریپانوشتها \
-بارگذاریپایین بارگذاریپردهها بارگذاریپردهپانل بارگذاریپروفایلها بارگذاریپرکردنخطها \
-بارگذاریپسزمینه بارگذاریپسزمینهها بارگذاریچیدن بارگذاریگذارصفحه بارگذاریگروههایآیتم \
-بارگذاریگروهآیتم بازنشانی بازنشانیشماره بازنشانیمتن بازنشانینشانهگذاری \
-باگذاریمتنبرچسب بدونبعد بدونبلوکهایبیشتر بدونتورفتگی بدونخطبالاوپایین \
-بدونخطسروتهبرگ بدونفایلهایبیشتر بدونفضا بدونفضایسفید بدونلیست \
-بدوننشانهگذاری برنامه بروبه بروبهجعبه بروبهصفحه \
-بروپایین برچسب برچسبها بعد بلند \
-بلوکهایپردازش بلوکهاپنهان بنویسبینلیست بنویسدرثبت بنویسدرلیستمرجع \
-بنویسدرلیست تاریخ تاریخجاری تاریخرجوع تایپ \
-تایپبافر تایپپرونده تب ترجمه تطابق \
-تعریف تعریفآرایش تعریفآرم تعریفالگویجدول تعریفاندازهبرگ \
-تعریفبافر تعریفبخش تعریفبرنامه تعریفبرچسب تعریفبلوک \
-تعریفبلوکبخش تعریفتایپ تعریفتایپکردن تعریفتبدیل تعریفترتیب \
-تعریفترکیب تعریفتنظیمریاضی تعریفتودهمیدان تعریفثبت تعریفجانشانی \
-تعریفجدولبندی تعریفجعبهافقی تعریفحرف تعریفخالی تعریفخروجی \
-تعریفخطحائل تعریفدرونحاشیه تعریفرنگ تعریفزیرمیدان تعریفسبک \
-تعریفسبکقلم تعریفسر تعریفشرح تعریفشروعپایان تعریفشمارهبندی \
-تعریفشمایلمرجع تعریفشناور تعریفشکستنستون تعریفشکستصفحه تعریفطرحبندی \
-تعریففرمان تعریفقالبی تعریفقلم تعریفقلمخام تعریفقلممتن \
-تعریفلایه تعریفلهجه تعریفلوح تعریفلیست تعریفلیستترکیبی \
-تعریفلیستمرجع تعریفمترادفها تعریفمترادفقلم تعریفمتغیرمتن تعریفمتن \
-تعریفمتنقالبی تعریفمجموعهستون تعریفمحیطقلمبدنه تعریفمرجع تعریفمنویپانل \
-تعریفمکانمتن تعریفمیدان تعریفمیداناصلی تعریفنسخه تعریفنشانهگذاری \
-تعریفنماد تعریفنمادشکل تعریفپاراگرافها تعریفپروفایل تعریفپوشش \
-تعریفگروهآیتم تعریفگروهرنگ تعیینشماره تعیینشمارهسر تعیینمتغیرمتن \
-تعیینمحتوایمتن تعیینمشخصاتثبت تعیینمشخصاتلیست تغییربهقلمبدنه تغییربهقلمخام \
-تنظیمراست تنظیمطرحبندی تنظیموسط توجه تورفتگی \
-توری تولید تک ثبتزوج ثبتکامل \
-جداسازینشانهگذاری حاش حرف حرفها حفظبلوکها \
-حقیقت خالی خطهایسیاه خطهاینازک خطهاخالی \
-خطحاشیه خطسیاه خطمتن خطمو خطنازک \
-خا خع در درجآرمها درجثبت \
-درجخط درجدرخط درجدرخطها درجدرمتن درجدرمیدان \
-درجدربالاییکدیگر درجدرتوری درجراهنما درجزیرفرمول درجشمارهسر \
-درجشمارهصفحه درجشناور درجفرمول درجلیست درجلیستخام \
-درجلیستمختلط درجلیستمرجع درجمتغیرمتن درجمتنسر درجپانوشتها \
-درجپانوشتهایموضعی درجچوبخط درجکناربهکنار درحاشیه درحاشیهدیگر \
-درحاشیهراست درحاشیهچپ درخارجی درخط درداخلی \
-درراست درصفحه درقالبی درلبهراست درلبهچپ \
-درمورد درون درپر درچپ دریافتبافر \
-دریافتشماره دریافتنشانه دوران دکمه دکمهمنو \
-دکمهپانل رج رجوع رنگ رنگخاکستری \
-روزهفته ریاضی زبان زباناصلی ستون \
-ستونامتحان سر سرپوشکوچکنه شروعآرایش شروعآرایشستون \
-شروعباریکتر شروعبازبینی شروعبلوکحاشیه شروعترکیب شروعتصحیحخط \
-شروعتطابق شروعتنظیم شروعتولید شروعجدول شروعجدولها \
-شروعخط شروعخطها شروعخطحاشیه شروعخطمتن شروعرنگ \
-شروعستونها شروعسراسری شروعشمارهگذاریخط شروعشکل شروعغیرفشرده \
-شروعفشرده شروعمتن شروعمجموعهستون شروعمجموعهنماد شروعمحیط \
-شروعمخالف شروعموضعی شروعمولفه شروعمکانگذاری شروعنسخه \
-شروعنقلقول شروعنوشتار شروعپانوشتهایموضعی شروعپروفایل شروعپروژه \
-شروعپسزمینه شروعپوشش شروعکد شمارهافزایش شمارهزیرصفحه \
-شمارهزیرفرمول شمارهسر شمارهسرجاری شمارهصفحه شمارهصفحهکامل \
-شمارهفرمول شمارهمبدل شمارهها شمارهکاهش شمارهکلصفحهها \
-شکافتنشناور شکلخارجی صفحه صفحهتست صفحهزوج \
-صفحهپردازش طوللیست عبوربلوکها عرضآرایش عرضبرگ \
-عرضحاشیه عرضحاشیهخارجی عرضحاشیهداخلی عرضحاشیهراست عرضحاشیهچپ \
-عرضخط عرضلبه عرضلبهخارجی عرضلبهداخلی عرضلبهراست \
-عرضلبهچپ عرضلیست عرضمتن عمقصفحه عنوانحاشیه \
-فاصلهبالا فاصلهتهبرگ فاصلهحاشیه فاصلهحاشیهخارجی فاصلهحاشیهداخلی \
-فاصلهحاشیهراست فاصلهحاشیهچپ فاصلهسربرگ فاصلهلبه فاصلهلبهخارجی \
-فاصلهلبهداخلی فاصلهلبهراست فاصلهلبهچپ فاصلهپایین فاصلهپشت \
-فشرده فضا فضاهایثابت فضایبالا فضایبرش \
-فضایثابت فضایسفید فضایسفیدصحیح فضایپایین فوریبهلیست \
-فوریبینلیست قالبی لوحمقایسه ماه متغیر متن \
-متنبرچسب متنحاشیه متنسر متنپانوشت محیط \
-مراجعه مرجع مرجعصفحه مرجعمتن مرحلهسر \
-مسکن معنیواحد مقایسهگروهرنگ مقدارخاکستری مقداررنگ \
-مقیاس منفی منویپانل مولفه مکان \
-مکانمتن میدان میدانهایگزارش میدانشبیهسازی میدانپشته \
-میدانکپی میلهتطابق میلهرنگ میلهپانل ناشناس \
-نامماکرو نسخه نسخهنشانه نشانهگذاری نشانهگذاریزوج \
-نشر نصبزبان نقطهها نقل نقلقول \
-نم نماد نمادسر نمادلیست نمایشآرایش \
-نمایشبارگذاریها نمایشبستها نمایشتوری نمایشرنگ نمایششکلهایخارجی \
-نمایشطرحبندی نمایشقالب نمایشقلمبدنه نمایشلوح نمایشمجموعهعلامت \
-نمایشمحیطقلمبدنه نمایشمیدانها نمایشچاپ نمایشگروهرنگ نوشتارزوج \
-هدایت پا پابا پانوشت پایانآرایش \
-پایانآرایشستون پایانبازبینی پایانبلوکحاشیه پایانترکیب پایانتصحیحخط \
-پایانتطابق پایانتنظیم پایانتولید پایانجدول پایانجدولها \
-پایانخط پایانخطها پایانخطحاشیه پایانخطمتن پایانرنگ \
-پایانستونها پایانسراسری پایانشمارهگذاریخط پایانغیرفشرده پایانفشرده \
-پایانمتن پایانمجموعهستون پایانمحیط پایانمخالف پایانموضعی \
-پایانمولفه پایانمکانگذاری پایاننازکتر پایاننسخه پایاننقلقول \
-پایاننوشتار پایانپانوشتهایموضعی پایانپروفایل پایانپروژه پایانپسزمینه \
-پایانپوشش پایانکد پایین پرده پروژه \
-پرکردنمیدان پسزمینه پیروینسخه پیروینسخهپروفایل پیرویپروفایل \
-چاپارتفاعبرگ چاپعرضبرگ چوبخط چپچین کاغذزوج \
-کسر کشیده کلمهحاشیه کلمهراست گیره \
-یادداشت یکجا یکخط
+startmenuinterattivo startnamemakeup startnarrower startopposite startoverlay \
+startoverview startparagraph startpositioning startpostponing startprodotto \
+startprofile startprogetto startregister startsfondo startsymbolset \
+startsynchronization starttable starttables starttabulate starttyping \
+startunpacked startversione stirato stopalignment stopambiente \
+stopbuffer stopcitazione stopcolore stopcolumnmakeup stopcolumns \
+stopcombination stopcomment stopcomponenet stopdescription stopdocument \
+stopenumeration stopfatto stopfigure stopfloattext stopformula \
+stopframedtext stophiding stopimpaccato stopitemgroup stoplegend \
+stopline stoplineamargine stoplineatesto stoplinecorrection stoplinenumbering \
+stoplines stoplocal stoplocalenvironment stoplocalfootnotes stopmakeup \
+stopmarginblock stopmenuinterattivo stopnamemakeup stopnarrower stopopposite \
+stopoverlay stopoverview stopparagraph stoppositioning stoppostponing \
+stopprodotto stopprofile stopprogetto stopsfondo stopsymbolset \
+stopsynchronization stoptable stoptables stoptabulate stoptyping \
+stopunpacked stopversione sub subject subpagenumber \
+subsection subsubject subsubsection subsubsubject synonym \
+tab terminaallineamento terminaambiente terminabloccomargine terminacitazione \
+terminacodifica terminacolonne terminacolore terminacombinazione terminacomponente \
+terminacorrezioneriga terminadocumento terminaglobale terminagruppocolonne terminaimpaccato \
+terminalineamargine terminalineatesto terminalocale terminamakeup terminanotepdplocali \
+terminanumerazionerighe terminaopposto terminaoverview terminapiustretto terminaposizionamento \
+terminaprodotto terminaprofili terminaprogetto terminaraster terminariga \
+terminarighe terminasfondo terminasincronizzazione terminasovrapposizione terminatabella \
+terminatabelle terminatesto terminaunpacked terminaversioni testa \
+testcolumn testoetichetta testoinmargine testoinstestazioni testonotapdp \
+testoriempimento testpage tex tieniblocchi title \
+titoloinmargine tooltip traduci txt typ \
+type typebuffer typefile underbar underbars \
+usaJSscripts usaURL usablocco usacartella usacodifica \
+usacolonnasonoraesterna usacomandi usadocumentoesterno usafiguraesterna usafileesterni \
+usafileesterno usamoduli usamodulo usariferimenti usasimboli \
+usaspecialita usaurl useXMLfilter usedirectory usetypescript \
+usetypescriptfile vaia vaiabox vaiapagina vaigiu \
+valorecolore valoregrigio variabiletesto versione vl
keywordclass.context.nl=\
CAP Cap Caps Cijfers \
@@ -1256,21 +935,342 @@ stoptabellen stoptable stoptables stoptabulate stoptekst \
stoptekstlijn stoptyping stopuitlijnen stopunpacked stopvanelkaar \
stopversie sub subformulenummer subject subpaginanummer \
subsection subsubject subsubsection subsubsubject suggestie \
-switchnaarkorps switchtorawfont sym symbool synchronisatiebalk \
-synchroniseer synonym taal tab tekstbreedte \
-teksthoogte tekstlijn tekstreferentie tekstvariabele testkolom \
-testpagina tex title toelichting toonexternefiguren \
-toongrid tooninstellingen toonkader toonkleur toonkleurgroep \
-toonkorps toonkorpsomgeving toonlayout toonopmaak toonpalet \
-toonprint toonstruts toonsymboolset toonvelden totaalaantalpaginas \
-txt typ type typebuffer typefile \
-uit uitgerekt underbar underbars usecodering \
-usedirectory vastespatie vastespaties veld veldstapel \
-verbergblokken vergelijkkleurgroep vergelijkpalet verhoognummer verlaagnummer \
-verplaatsformule verplaatsopgrid verplaatszijblok versie vertaal \
-verwerkblokken verwerkpagina vl voetafstand voethoogte \
-voetnoot voetnoottekst volgprofiel volgprofielversie volgversie \
-volledigepaginanummer volledigregister voluit weekdag wilijnd \
-wiskunde witruimte woonplaats woordrechts zetbreedte \
-zethoogte
+switchnaarkorps switchtorawfont sym symbool symoffset \
+synchronisatiebalk synchroniseer synonym taal tab \
+tekstbreedte teksthoogte tekstlijn tekstreferentie tekstvariabele \
+testkolom testpagina tex title toelichting \
+toonexternefiguren toongrid tooninstellingen toonkader toonkleur \
+toonkleurgroep toonkorps toonkorpsomgeving toonlayout toonopmaak \
+toonpalet toonprint toonstruts toonsymboolset toonvelden \
+totaalaantalpaginas txt typ type typebuffer \
+typefile uit uitgerekt underbar underbars \
+usecodering usedirectory vastespatie vastespaties veld \
+veldstapel verbergblokken vergelijkkleurgroep vergelijkpalet verhoognummer \
+verlaagnummer verplaatsformule verplaatsopgrid verplaatszijblok versie \
+vertaal verwerkblokken verwerkpagina vl voetafstand \
+voethoogte voetnoot voetnoottekst volgprofiel volgprofielversie \
+volgversie volledigepaginanummer volledigregister voluit weekdag \
+wilijnd wiskunde witruimte woonplaats woordrechts \
+zetbreedte zethoogte
+
+keywordclass.context.pe=\
+CAP Cap Caps Character \
+Characters MONTH Numbers Romannumerals WEEKDAY \
+WORD WORDS Word Words appendix \
+cap chapter chem comment completecombinedlist \
+completelistoffloats completelistofsorts completelistofsynonyms coupledregister crlf \
+definebodyfontDEF definebodyfontREF definedfont definefontfeature definefonthandling \
+defineindentedtext definetypeface description enumeration framedtext \
+indentation inmframed its labeling loadsorts \
+loadsynonyms mapfontsize mediaeval mframed name \
+nextsection nocap overbar overbars overstrike \
+overstrikes paragraph part placelistoffloats placelistofsorts \
+placelistofsynonyms ran register reservefloat resettextcontent \
+section seeregister setupanswerarea setupcapitals setupfonthandling \
+setupfontsynonym setupindentedtext setupinterlinespace2 setuplistalternative setupurl \
+sort startalignment startbuffer startcolumns startcombination \
+startcomment startdescription startdocument startenumeration startfigure \
+startfloattext startformula startframedtext starthiding startitemgroup \
+startlegend startline startlinecorrection startlinenumbering startlines \
+startlocal startlocalenvironment startlocalfootnotes startmakeup startmarginblock \
+startnamemakeup startnarrower startopposite startoverlay startoverview \
+startparagraph startpositioning startpostponing startprofile startraster \
+startregister startsymbolset startsynchronization starttable starttables \
+starttabulate starttyping startunpacked startتولید startحقیقت \
+startخطحاشیه startخطمتن startرنگ startفشرده startمحیط \
+startمنویپانل startمولفه startنسخه startنقلقول startپروژه \
+startپسزمینه stopalignment stopbuffer stopcolumns stopcombination \
+stopcomment stopdescription stopdocument stopenumeration stopfigure \
+stopfloattext stopformula stopframedtext stophiding stopitemgroup \
+stoplegend stopline stoplinecorrection stoplinenumbering stoplines \
+stoplocal stoplocalenvironment stoplocalfootnotes stopmakeup stopmarginblock \
+stopnamemakeup stopnarrower stopopposite stopoverlay stopoverview \
+stopparagraph stoppositioning stoppostponing stopprofile stopraster \
+stopsymbolset stopsynchronization stoptable stoptables stoptabulate \
+stoptyping stopunpacked stopتولید stopحقیقت stopخطحاشیه \
+stopخطمتن stopرنگ stopفشرده stopمحیط stopمنویپانل \
+stopمولفه stopنسخه stopنقلقول stopپروژه stopپسزمینه \
+sub subject subsection subsubject subsubsection \
+subsubsubject synonym title tooltip txt \
+typ underbar underbars useJSscripts useURL \
+useXMLfilter usedirectory useurl آفستصفحه آیتم \
+آیتمها آینه اجباربلوکها ارتفاعآرایش ارتفاعبالا \
+ارتفاعبرگ ارتفاعتهبرگ ارتفاعخط ارتفاعسربرگ ارتفاعمتن \
+ارتفاعپایین از ازکارانداختنمنویپانل استفادهبلوکها استفادهدستخطتایپ \
+استفادهرمزینه استفادهشکلخارجی استفادهفرمانها استفادهقطعهموزیکخارجی استفادهمدول \
+استفادهمدولها استفادهمرجعها استفادهمسیر استفادهنمادها استفادهنوشتارخارجی \
+استفادهویژگیها استفادهپروندهخارجی استفادهپروندهدستخطتایپ استفادهپروندههایخارجی اعدادلاتین \
+افزودن اما امتحاننکن انتخاببرگ انتخاببلوکها \
+انتخابنسخه انتقالبهتوری انتقالفرمول انتقالکنارشناور انجامدوباره \
+بارگذاریها بارگذاریآرایش بارگذاریآیتمها بارگذاریارجاع بارگذاریاندازهبرگ \
+بارگذاریباریکتر بارگذاریبافر بارگذاریبالا بارگذاریبخش بارگذاریبردباری \
+بارگذاریبرنامهها بارگذاریبرگ بارگذاریبست بارگذاریبلوک بارگذاریبلوکهایحاشیه \
+بارگذاریبلوکبخش بارگذاریتایپ بارگذاریتایپکردن بارگذاریتب بارگذاریترتیب \
+بارگذاریترکیبها بارگذاریتطابق بارگذاریتعریفپانوشت بارگذاریتنظیم بارگذاریتنظیمریاضی \
+بارگذاریتهبرگ بارگذاریتورفتگی بارگذاریتوضیح بارگذاریتوضیحصفحه بارگذاریثبت \
+بارگذاریجانشانی بارگذاریجدولها بارگذاریجدولبندی بارگذاریخالی بارگذاریخروجی \
+بارگذاریخط بارگذاریخطها بارگذاریخطهایحاشیه بارگذاریخطهایسیاه بارگذاریخطهایمتن \
+بارگذاریخطهایمجموعهستون بارگذاریخطهاینازک بارگذاریدرجدرخطها بارگذاریدرجمخالف بارگذاریدرونحاشیه \
+بارگذاریدوران بارگذاریدکمهها بارگذاریراهنما بارگذاریرنگ بارگذاریرنگها \
+بارگذاریزبان بارگذاریستونها بارگذاریسر بارگذاریسربرگ بارگذاریسرها \
+بارگذاریسیستم بارگذاریشرح بارگذاریشرحها بارگذاریشروعمجموعهستون بارگذاریشروعپایان \
+بارگذاریشماره بارگذاریشمارهزیرصفحه بارگذاریشمارهسر بارگذاریشمارهصفحه بارگذاریشمارهگذاری \
+بارگذاریشمارهگذاریها بارگذاریشمارهگذاریصفحه بارگذاریشمارهگذاریپاراگراف بارگذاریشمارهگذاریخط بارگذاریشناور \
+بارگذاریشناورها بارگذاریشکافتنشناورها بارگذاریشکلهایخارجی بارگذاریطرح بارگذاریطرحبندی \
+بارگذاریعرضخط بارگذاریفاصلهبینخط بارگذاریفرمولها بارگذاریفضایسفید بارگذاریفضاگذاری \
+بارگذاریقالبی بارگذاریقلممتن بارگذاریلوح بارگذاریلیست بارگذاریلیستترکیبی \
+بارگذاریلیستمرجع بارگذاریمترادفها بارگذاریمتغیرمتن بارگذاریمتن بارگذاریمتنهایبالا \
+بارگذاریمتنسر بارگذاریمتنسربرگ بارگذاریمتنقالبی بارگذاریمتنمتنها بارگذاریمتنپانوشت \
+بارگذاریمتنپایین بارگذاریمجموعهستون بارگذاریمجموعهنماد بارگذاریمحیطقلممتن بارگذاریمنویپانل \
+بارگذاریمکانمتن بارگذاریمکانگذاری بارگذاریمیدان بارگذاریمیدانها بارگذاریمیلهتطابق \
+بارگذاریمیلهزیر بارگذاریمیلهپانل بارگذارینسخهها بارگذارینشانهشکستن بارگذارینشانهگذاری \
+بارگذارینشرها بارگذارینقل بارگذاریپاراگرافها بارگذاریپانل بارگذاریپانوشتها \
+بارگذاریپایین بارگذاریپردهها بارگذاریپردهپانل بارگذاریپروفایلها بارگذاریپرکردنخطها \
+بارگذاریپسزمینه بارگذاریپسزمینهها بارگذاریچیدن بارگذاریگذارصفحه بارگذاریگروههایآیتم \
+بارگذاریگروهآیتم بازنشانی بازنشانیشماره بازنشانیمتن بازنشانینشانهگذاری \
+باگذاریمتنبرچسب بدونبعد بدونبلوکهایبیشتر بدونتورفتگی بدونخطبالاوپایین \
+بدونخطسروتهبرگ بدونفایلهایبیشتر بدونفضا بدونفضایسفید بدونلیست \
+بدوننشانهگذاری برنامه بروبه بروبهجعبه بروبهصفحه \
+بروپایین برچسب برچسبها بعد بلند \
+بلوکهایپردازش بلوکهاپنهان بنویسبینلیست بنویسدرثبت بنویسدرلیستمرجع \
+بنویسدرلیست تاریخ تاریخجاری تاریخرجوع تایپ \
+تایپبافر تایپپرونده تب ترجمه تطابق \
+تعریف تعریفآرایش تعریفآرم تعریفالگویجدول تعریفاندازهبرگ \
+تعریفبافر تعریفبخش تعریفبرنامه تعریفبرچسب تعریفبلوک \
+تعریفبلوکبخش تعریفتایپ تعریفتایپکردن تعریفتبدیل تعریفترتیب \
+تعریفترکیب تعریفتنظیمریاضی تعریفتودهمیدان تعریفثبت تعریفجانشانی \
+تعریفجدولبندی تعریفجعبهافقی تعریفحرف تعریفخالی تعریفخروجی \
+تعریفخطحائل تعریفدرونحاشیه تعریفرنگ تعریفزیرمیدان تعریفسبک \
+تعریفسبکقلم تعریفسر تعریفشرح تعریفشروعپایان تعریفشمارهبندی \
+تعریفشمایلمرجع تعریفشناور تعریفشکستنستون تعریفشکستصفحه تعریفطرحبندی \
+تعریففرمان تعریفقالبی تعریفقلم تعریفقلمخام تعریفقلممتن \
+تعریفلایه تعریفلهجه تعریفلوح تعریفلیست تعریفلیستترکیبی \
+تعریفلیستمرجع تعریفمترادفها تعریفمترادفقلم تعریفمتغیرمتن تعریفمتن \
+تعریفمتنقالبی تعریفمجموعهستون تعریفمحیطقلمبدنه تعریفمرجع تعریفمنویپانل \
+تعریفمکانمتن تعریفمیدان تعریفمیداناصلی تعریفنسخه تعریفنشانهگذاری \
+تعریفنماد تعریفنمادشکل تعریفپاراگرافها تعریفپروفایل تعریفپوشش \
+تعریفگروهآیتم تعریفگروهرنگ تعیینشماره تعیینشمارهسر تعیینمتغیرمتن \
+تعیینمحتوایمتن تعیینمشخصاتثبت تعیینمشخصاتلیست تغییربهقلمبدنه تغییربهقلمخام \
+تنظیمراست تنظیمطرحبندی تنظیموسط توجه تورفتگی \
+توری تولید تک ثبتزوج ثبتکامل \
+جداسازینشانهگذاری حاش حرف حرفها حفظبلوکها \
+حقیقت خالی خطهایسیاه خطهاینازک خطهاخالی \
+خطحاشیه خطسیاه خطمتن خطمو خطنازک \
+خا خع در درجآرمها درجثبت \
+درجخط درجدرخط درجدرخطها درجدرمتن درجدرمیدان \
+درجدربالاییکدیگر درجدرتوری درجراهنما درجزیرفرمول درجشمارهسر \
+درجشمارهصفحه درجشناور درجفرمول درجلیست درجلیستخام \
+درجلیستمختلط درجلیستمرجع درجمتغیرمتن درجمتنسر درجپانوشتها \
+درجپانوشتهایموضعی درجچوبخط درجکناربهکنار درحاشیه درحاشیهدیگر \
+درحاشیهراست درحاشیهچپ درخارجی درخط درداخلی \
+درراست درصفحه درقالبی درلبهراست درلبهچپ \
+درمورد درون درپر درچپ دریافتبافر \
+دریافتشماره دریافتنشانه دوران دکمه دکمهمنو \
+دکمهپانل رج رجوع رنگ رنگخاکستری \
+روزهفته ریاضی زبان زباناصلی ستون \
+ستونامتحان سر سرپوشکوچکنه شروعآرایش شروعآرایشستون \
+شروعباریکتر شروعبازبینی شروعبلوکحاشیه شروعترکیب شروعتصحیحخط \
+شروعتطابق شروعتنظیم شروعتولید شروعجدول شروعجدولها \
+شروعخط شروعخطها شروعخطحاشیه شروعخطمتن شروعرنگ \
+شروعستونها شروعسراسری شروعشمارهگذاریخط شروعشکل شروعغیرفشرده \
+شروعفشرده شروعمتن شروعمجموعهستون شروعمجموعهنماد شروعمحیط \
+شروعمخالف شروعموضعی شروعمولفه شروعمکانگذاری شروعنسخه \
+شروعنقلقول شروعنوشتار شروعپانوشتهایموضعی شروعپروفایل شروعپروژه \
+شروعپسزمینه شروعپوشش شروعکد شمارهافزایش شمارهزیرصفحه \
+شمارهزیرفرمول شمارهسر شمارهسرجاری شمارهصفحه شمارهصفحهکامل \
+شمارهفرمول شمارهمبدل شمارهها شمارهکاهش شمارهکلصفحهها \
+شکافتنشناور شکلخارجی صفحه صفحهتست صفحهزوج \
+صفحهپردازش طوللیست عبوربلوکها عرضآرایش عرضبرگ \
+عرضحاشیه عرضحاشیهخارجی عرضحاشیهداخلی عرضحاشیهراست عرضحاشیهچپ \
+عرضخط عرضلبه عرضلبهخارجی عرضلبهداخلی عرضلبهراست \
+عرضلبهچپ عرضلیست عرضمتن عمقصفحه عنوانحاشیه \
+فاصلهبالا فاصلهتهبرگ فاصلهحاشیه فاصلهحاشیهخارجی فاصلهحاشیهداخلی \
+فاصلهحاشیهراست فاصلهحاشیهچپ فاصلهسربرگ فاصلهلبه فاصلهلبهخارجی \
+فاصلهلبهداخلی فاصلهلبهراست فاصلهلبهچپ فاصلهپایین فاصلهپشت \
+فشرده فضا فضاهایثابت فضایبالا فضایبرش \
+فضایثابت فضایسفید فضایسفیدصحیح فضایپایین فوریبهلیست \
+فوریبینلیست قالبی لوحمقایسه ماه متغیر متن \
+متنبرچسب متنحاشیه متنسر متنپانوشت محیط \
+مراجعه مرجع مرجعصفحه مرجعمتن مرحلهسر \
+مسکن معنیواحد مقایسهگروهرنگ مقدارخاکستری مقداررنگ \
+مقیاس منفی منویپانل مولفه مکان \
+مکانمتن میدان میدانهایگزارش میدانشبیهسازی میدانپشته \
+میدانکپی میلهتطابق میلهرنگ میلهپانل ناشناس \
+نامماکرو نسخه نسخهنشانه نشانهگذاری نشانهگذاریزوج \
+نشر نصبزبان نقطهها نقل نقلقول \
+نم نماد نمادسر نمادلیست نمایشآرایش \
+نمایشبارگذاریها نمایشبستها نمایشتوری نمایشرنگ نمایششکلهایخارجی \
+نمایشطرحبندی نمایشقالب نمایشقلمبدنه نمایشلوح نمایشمجموعهعلامت \
+نمایشمحیطقلمبدنه نمایشمیدانها نمایشچاپ نمایشگروهرنگ نوشتارزوج \
+هدایت پا پابا پانوشت پایانآرایش \
+پایانآرایشستون پایانبازبینی پایانبلوکحاشیه پایانترکیب پایانتصحیحخط \
+پایانتطابق پایانتنظیم پایانتولید پایانجدول پایانجدولها \
+پایانخط پایانخطها پایانخطحاشیه پایانخطمتن پایانرنگ \
+پایانستونها پایانسراسری پایانشمارهگذاریخط پایانغیرفشرده پایانفشرده \
+پایانمتن پایانمجموعهستون پایانمحیط پایانمخالف پایانموضعی \
+پایانمولفه پایانمکانگذاری پایاننازکتر پایاننسخه پایاننقلقول \
+پایاننوشتار پایانپانوشتهایموضعی پایانپروفایل پایانپروژه پایانپسزمینه \
+پایانپوشش پایانکد پایین پرده پروژه \
+پرکردنمیدان پسزمینه پیروینسخه پیروینسخهپروفایل پیرویپروفایل \
+چاپارتفاعبرگ چاپعرضبرگ چوبخط چپچین کاغذزوج \
+کسر کشیده کلمهحاشیه کلمهراست گیره \
+یادداشت یکجا یکخط
+
+keywordclass.context.ro=\
+CAP CUVANT CUVINTE Cap \
+Caps Cuvant Cuvinte KAP Kap \
+Kaps LUNA Litera Litere Numere \
+Numereromane ZIDINSAPTAMANA adapteazaaspect adubuffer adumarcaje \
+afiseazaaspect afiseazacampuri afiseazaculoare afiseazafiguriexterne afiseazafonttext \
+afiseazagrid afiseazagrupculoare afiseazamakeup afiseazamediufonttext afiseazapaleta \
+afiseazarama afiseazasetari afiseazasetsimboluri afiseazastruts afiseazatiparire \
+aliniat aliniatcentru aliniatdreapta aliniatstanga appendix \
+arg ascundeblocuri atleftmargin atrightmargin baraculoare \
+barainteractiune barasincronizare blanc but butoaneinteractiune \
+buton butonmeniu camp campumplere cap \
+chapter chem citat clip cloneazacamp \
+coloana comment comparagrupculoare comparapaleta completeazanumarpagina \
+completecombinedlist completelistoffloats completelistofsorts completelistofsynonyms completeregister \
+componenta convertestenumar copiazacamp corecteazaspatiualb coupledregister \
+crlf culoare culoaregri cupleazadocument cupleazamarcaje \
+cupleazaregistru cutspace cuvantdreapta cuvantmarginal data \
+datacurenta datareferit decrementnumber decupleazamarcaje definebodyfontDEF \
+definebodyfontREF definecolumnbreak definecolumnset definecombination definedfont \
+definefontfeature definefonthandling defineindentedtext defineinmargin defineitemgroup \
+definelayer definelayout definemathalignment definepagebreak defineplacement \
+defineste definesteaccent definesteantet definesteblanc definestebloc \
+definesteblocsectiune definestebuffer definestecamp definestecampprincipal definestecaracter \
+definestecomanda definesteconversie definesteculoare definestedescriere definestedimensiunehartie \
+definesteenumerare definesteeticheta definestefloat definestefont definestefontraw \
+definestefonttext definesteformatreferinte definestegrupculori definestehbox definesteinconjurare \
+definestelista definestelistacombinata definestelistareferinte definestelogo definestemakeup \
+definestemarcaje definestemediulfonttext definestemeniuinteractiune definesteoutput definesteoverlay \
+definestepaleta definesteparagraf definestepozitietext definesteprofil definesteprogram \
+definestereferinte definesteregistru definesterigla definestesablontabel definestesectiune \
+definestesimbol definestesimbolfigura definestesinonim definestesinonimfont definestesortare \
+definestestartstop definestestil definestestilfont definestestivacampuri definestesubcamp \
+definestetabulatori definestetext definestetexteinconjurate definestetextinconjurat definestetyping \
+definestevariabilatext definesteversiune definetype definetypeface description \
+despre determinacaracteristicilelistei determinacaracteristiciregistru determinanumartitlu dezactiveazameniuinteractiune \
+dimensiune din distantaantet distantacolt distantacoltdreapta \
+distantacoltstanga distantajos distantamargine distantamarginedreapta distantamarginestanga \
+distantasubsol distantasus domiciliu dute dutebox \
+dutepagina ecran el element emptylines \
+enumeration eticheta etichete fact faraaliniat \
+faradimensiune farafisiere faraliniiantetsisubsol faraliniisussijos faralista \
+faramarcaje faraspatiu faraspatiualb figuraexterna firdepar \
+folosesteURL folosestebloc folosestecodificarea folosestecomenzi folosestedirector \
+folosestedocumentextern folosestefiguraexterna folosestefisiereexterne folosestefisierextern folosestemodul \
+folosestemodule folosestemuzicaexterna folosestereferinte folosestescriptJS folosestesimboluri \
+folosestespeciale folosesteurl footnotetext forteazablocuri fractie \
+framed framedtext fundal gatablocuri getnumber \
+grid grosimelinie hartiedubla headsym hl \
+immediatebetweenlist immediatetolist impachetat impartefloat in \
+inalt inaltamargine inaltimeantet inaltimehartie inaltimehartieimprimanta \
+inaltimejos inaltimelista inaltimemakeup inaltimesubsol inaltimesus \
+inaltimetext indentation indreapta inframed ininner \
+injos inlinie inmaframed inmargineadreapta inmargineastanga \
+inneredgedistance inneredgewidth innermargindistance innermarginwidth inouter \
+inparteadreapta inparteastanga instalarelimba instanga intins \
+jos jossus kap la labeling \
+lapagina latimecoltdreapta latimecoltstanga latimecolturi latimehartie \
+latimehartieimprimanta latimelista latimemakeup latimemargine latimemarginedreapta \
+latimemarginestanga latimetext leg limba limbaprincipala \
+liniemargine linieneagra liniesubtire linieumplere liniinegre \
+liniisubtiri listsymbol litera litere loadsorts \
+loadsynonyms logcampuri luna lungimelista maframed \
+mapfontsize mar marcaje marcheazaversiune marginal \
+matematica mediaeval mediu meniuinteractiune minicitat \
+moveformula movesidefloat mutapegrid name navigating \
+necunoscut nextsection niveltitlu nocap nokap \
+nop nota notasubsol numarformula numarincrement \
+numarpagina numarsubformula numartitlu numartitlucurent numartotalpagini \
+numberofsubpages nume numere numereromane numeunitate \
+nutesta olinie outeredgedistance outeredgewidth outermargindistance \
+outermarginwidth overbar overbars overstrike overstrikes \
+pagedepth pageoffset pagina paginadubla paragraph \
+part pastreazablocuri pelung placefloat placeheadnumber \
+placeheadtext placelistoffloats placelistofsorts placelistofsynonyms placerawlist \
+placereferencelist plaseazapegrid plaseazasemnecarte potrivestecamp pozitie \
+pozitietext proceseazabloc proceseazapagina produs program \
+proiect publicatie puncte punedeasuprafiecareia punefatainfata \
+puneformula punelegenda punelista punelistacombinata punelogouri \
+punenotesubsol punenotesubsollocale punenumarpagina puneregistru punerigla \
+punesubformula punevariabilatext ran ref refa \
+referinta referintapagina referintatext referit referring \
+reflexie register remarca reservefloat reset \
+reseteazamarcaje resetnumber resettextcontent riglatext rigleumplere \
+roteste saripesteblocuri scala scriebuffer scrieinlista \
+scrieinlistareferinte scrieinregistru scrieintreliste section seeregister \
+selecteazablocuri selecteazahartie selecteazaversiune semncarte setarebarasincronizare \
+setareitemization setarelimba setareoutput setarepozitie setaresincronizare \
+setari seteazaaliniat seteazaalinierea seteazaantet seteazaaranjareapag \
+seteazaaspect seteazabarainteractiune seteazablanc seteazabloc seteazablocsectiune \
+seteazablocurimarginale seteazabuffer seteazabutoane seteazacamp seteazacampuri \
+seteazaclipping seteazacoloane seteazacombinari seteazacomentariu seteazacomentariupagina \
+seteazaculoare seteazaculori seteazadefinireanotasubsol seteazadescriere seteazadimensiunihartie \
+seteazaecrane seteazaecraninteractiune seteazaelemente seteazaenumerare seteazafiguriexterne \
+seteazafloat seteazafloats seteazafonttext seteazaformulare seteazaformule \
+seteazafundal seteazafundaluri seteazagrosimelinie seteazaimpartireafloat seteazainconjurat \
+seteazaingust seteazainteractiunea seteazajos seteazalegenda seteazalegendele \
+seteazaliniesilabe seteazaliniesubtire seteazalinii seteazaliniimargine seteazaliniinegre \
+seteazaliniiumplere seteazalista seteazalistacombinata seteazalistareferinte seteazamajuscule \
+seteazamakeup seteazamarcaje seteazamarginal seteazamediulfonttext seteazameniuinteractiune \
+seteazaminicitat seteazanotasubsol seteazanumarpagina seteazanumarsubpagina seteazanumartitlu \
+seteazanumerotare seteazanumerotarelinii seteazanumerotarepagina seteazanumerotareparagrafe seteazapaleta \
+seteazaparagrafe seteazaplasareaopozita seteazapozitietext seteazaprofile seteazaprograme \
+seteazapublicatii seteazareferinte seteazaregistru seteazarigla seteazarigletext \
+seteazarigleumplere seteazarotare seteazasectiune seteazasimbol seteazasinonime \
+seteazasistem seteazasortare seteazaspatiu seteazaspatiualb seteazaspatiuinterliniar \
+seteazastrut seteazasublinie seteazasubsol seteazasus seteazatab \
+seteazatabele seteazatabulatori seteazatext seteazatexteantet seteazatextejos \
+seteazatextesubsol seteazatextesus seteazatextetext seteazatexteticheta seteazatexttitlu \
+seteazatitlu seteazatitluri seteazatoleranta seteazatranzitiepagina seteazatype \
+seteazatyping seteazaurl seteazavariabilatext seteazaversiuni setnumber \
+settextcontent setupanswerarea setupcolumnset setupcolumnsetlines setupcolumnsetstart \
+setupfonthandling setupfontsynonym setupindentedtext setupinterlinespace2 setupitemgroup \
+setuplistalternative setupmathalignment setupnumber setuppaper setupplacement \
+setupstartstop setvariabilatext sim simbol sincronizeaza \
+sort spatiifixate spatiu spatiualb spatiufixat \
+spatiujos spatiuspate spatiusus startalignment startaliniere \
+startblocmarginal startbuffer startcitat startcodificare startcoloane \
+startcolumnmakeup startcolumns startcolumnset startcombinare startcombination \
+startcomment startcomponenta startcorectielinie startculoare startdescription \
+startdocument startenumeration startfact startfigura startfigure \
+startfloattext startformula startframedtext startfundal startglobal \
+starthiding startimpachetat startingust startitemgroup startlegend \
+startline startlinecorrection startlinenumbering startlines startlinie \
+startliniemargine startlinii startlocal startlocalenvironment startlocalfootnotes \
+startmakeup startmarginblock startmediu startmeniuinteractiune startnamemakeup \
+startnarrower startneimpachetat startnotesubsollocale startnumerotarelinii startopozit \
+startopposite startoverlay startoverview startparagraph startpositioning \
+startpostponing startpozitionare startprodus startprofil startprofile \
+startproiect startraster startregister startriglatext startsetsimboluri \
+startsincronizare startsymbolset startsynchronization starttabel starttabele \
+starttable starttables starttabulate starttext starttyping \
+startunpacked startversiune stivacampuri stopalignment stopaliniere \
+stopblobal stopblocmarginal stopbuffer stopcitat stopcodificare \
+stopcoloane stopcolumnmakeup stopcolumns stopcolumnset stopcombinare \
+stopcombination stopcomment stopcomponenta stopcorectielinie stopculoare \
+stopdescription stopdocument stopenumeration stopfact stopfigure \
+stopfloattext stopformula stopframedtext stopfundal stophiding \
+stopimpachetat stopingust stopitemgroup stoplegend stopline \
+stoplinecorrection stoplinenumbering stoplines stoplinie stopliniemargine \
+stoplinii stoplocal stoplocalenvironment stoplocalfootnotes stopmakeup \
+stopmarginblock stopmediu stopmeniuinteractiune stopnamemakeup stopnarrower \
+stopneimpachetat stopnotesubsollocale stopnumerotarelinii stopopozit stopopposite \
+stopoverlay stopoverview stopparagraph stoppositioning stoppostponing \
+stoppozitionare stopprodus stopprofil stopprofile stopproiect \
+stopraster stopriglatext stopsincronizare stopsymbolset stopsynchronization \
+stoptabel stoptabele stoptable stoptables stoptabulate \
+stoptext stoptyping stopunpacked stopversiune sub \
+subject subpagenumber subsection subsubject subsubsection \
+subsubsubject synonym tab testcolumn testpage \
+tex texteticheta textmarginal texttitlu textumplere \
+title titlu titlumarginal tooltip traduce \
+trecilafontraw trecilafonttext txt typ type \
+typefile underbar underbars undeva urmeazaprofil \
+urmeazaversiune urmeazaversiuneprofil useXMLfilter usedirectory usetypescript \
+usetypescriptfile valoareculoare valoaregri variabilatext versiune \
+vl zidinsaptamana
diff --git a/Master/texmf-dist/context/data/scite/scite-context-data-metafun.properties b/Master/texmf-dist/context/data/scite/scite-context-data-metafun.properties
index e0413b2dd75..b20b3e856e8 100644
--- a/Master/texmf-dist/context/data/scite/scite-context-data-metafun.properties
+++ b/Master/texmf-dist/context/data/scite/scite-context-data-metafun.properties
@@ -1,10 +1,3 @@
-keywordclass.metafun.internals=\
-nocolormodel greycolormodel graycolormodel rgbcolormodel \
-cmykcolormodel shadefactor textextoffset normaltransparent multiplytransparent \
-screentransparent overlaytransparent softlighttransparent hardlighttransparent colordodgetransparent \
-colorburntransparent darkentransparent lightentransparent differencetransparent exclusiontransparent \
-huetransparent saturationtransparent colortransparent luminositytransparent
-
keywordclass.metafun.commands=\
sqr log ln exp \
inv pow pi radian tand \
@@ -33,21 +26,30 @@ grayed greyed onlayer along graphictext \
loadfigure externalfigure withmask figure register \
bitmapimage colordecimals ddecimal dddecimal ddddecimal \
textext thetextext rawtextext textextoffset verbatim \
-thelabel label transparent withtransparency asgroup \
-infont set_linear_vector linear_shade define_linear_shade define_circular_linear_shade \
-define_sampled_linear_shade set_circular_vector circular_shade define_circular_shade define_circular_linear_shade \
-define_sampled_circular_shade space CRLF grayscale greyscale \
-withgray withgrey colorpart readfile clearxy \
-unitvector center epsed anchored originpath \
-infinite break xstretched ystretched snapped \
-pathconnectors function constructedpath constructedpairs punkedfunction \
-curvedfunction tightfunction punkedpath curvedpath tightpath \
-punkedpairs curvedpairs tightpairs evenly oddly \
-condition pushcurrentpicture popcurrentpicture arrowpath tensecircle \
-roundedsquare colortype whitecolor blackcolor normalfill \
-normaldraw visualizepaths naturalizepaths drawboundary drawwholepath \
-visualizeddraw visualizedfill draworigin drawboundingbox drawpath \
-drawpoint drawpoints drawcontrolpoints drawcontrollines drawpointlabels \
-drawlineoptions drawpointoptions drawcontroloptions drawlabeloptions draworiginoptions \
-drawboundoptions drawpathoptions resetdrawoptions
+thelabel label autoalign transparent withtransparency \
+property properties withproperties asgroup infont \
+set_linear_vector linear_shade define_linear_shade define_circular_linear_shade define_sampled_linear_shade \
+set_circular_vector circular_shade define_circular_shade define_circular_linear_shade define_sampled_circular_shade \
+space CRLF grayscale greyscale withgray \
+withgrey colorpart readfile clearxy unitvector \
+center epsed anchored originpath infinite \
+break xstretched ystretched snapped pathconnectors \
+function constructedpath constructedpairs punkedfunction curvedfunction \
+tightfunction punkedpath curvedpath tightpath punkedpairs \
+curvedpairs tightpairs evenly oddly condition \
+pushcurrentpicture popcurrentpicture arrowpath tensecircle roundedsquare \
+colortype whitecolor blackcolor normalfill normaldraw \
+visualizepaths naturalizepaths drawboundary drawwholepath visualizeddraw \
+visualizedfill draworigin drawboundingbox drawpath drawpoint \
+drawpoints drawcontrolpoints drawcontrollines drawpointlabels drawlineoptions \
+drawpointoptions drawcontroloptions drawlabeloptions draworiginoptions drawboundoptions \
+drawpathoptions resetdrawoptions decorated redecorated undecorated
+
+keywordclass.metafun.internals=\
+nocolormodel greycolormodel graycolormodel rgbcolormodel \
+cmykcolormodel shadefactor textextoffset normaltransparent multiplytransparent \
+screentransparent overlaytransparent softlighttransparent hardlighttransparent colordodgetransparent \
+colorburntransparent darkentransparent lightentransparent differencetransparent exclusiontransparent \
+huetransparent saturationtransparent colortransparent luminositytransparent metapostversion \
+maxdimensions
diff --git a/Master/texmf-dist/context/data/scite/scite-context-data-metapost.properties b/Master/texmf-dist/context/data/scite/scite-context-data-metapost.properties
index d2027c9564e..5566a3865ea 100644
--- a/Master/texmf-dist/context/data/scite/scite-context-data-metapost.properties
+++ b/Master/texmf-dist/context/data/scite/scite-context-data-metapost.properties
@@ -1,54 +1,3 @@
-keywordclass.metapost.primitives=\
-charcode day linecap linejoin \
-miterlimit month pausing prologues showstopping \
-time tracingcapsules tracingchoices mpprocset tracingcommands \
-tracingequations tracinglostchars tracingmacros tracingonline tracingoutput \
-tracingrestores tracingspecs tracingstats tracingtitles truecorners \
-warningcheck year false nullpicture pencircle \
-true and angle arclength arctime \
-ASCII boolean bot char color \
-cosd cycle decimal directiontime floor \
-fontsize hex infont intersectiontimes known \
-length llcorner lrcorner makepath makepen \
-mexp mlog normaldeviate not numeric \
-oct odd or path pair \
-pen penoffset picture point postcontrol \
-precontrol reverse rotated scaled shifted \
-sind slanted sqrt str string \
-subpath substring transform transformed ulcorner \
-uniformdeviate unknown urcorner xpart xscaled \
-xxpart xypart ypart yscaled yxpart \
-yypart zscaled addto clip input \
-interim let newinternal save setbounds \
-shipout show showdependencies showtoken showvariable \
-special begingroup endgroup of curl \
-tension and controls interpath on \
-off def vardef enddef expr \
-suffix text primary secondary tertiary \
-primarydef secondarydef tertiarydef randomseed also \
-contour doublepath withcolor withpen dashed \
-if else elseif fi for \
-endfor forever exitif forsuffixes downto \
-upto step until charlist extensible \
-fontdimen headerbyte kern ligtable boundarychar \
-chardp charext charht charic charwd \
-designsize fontmaking charexists cullit currenttransform \
-gfcorners grayfont hround imagerules lowres_fix \
-nodisplays notransforms openit displaying currentwindow \
-screen_rows screen_cols pixels_per_inch cull display \
-openwindow numspecial totalweight autorounding fillin \
-proofing tracingpens xoffset chardx granularity \
-smoothing turningcheck yoffset chardy hppp \
-tracingedges vppp extra_beginfig extra_endfig mpxbreak \
-endinput message delimiters turningnumber errmessage \
-readstring scantokens end outer inner \
-write to readfrom withprescript withpostscript \
-top bot lft rt ulft \
-urt llft lrt redpart greenpart \
-bluepart cyanpart magentapart yellowpart blackpart \
-greypart rgbcolor cmykcolor greycolor graycolor \
-colormodel graypart expandafter
-
keywordclass.metapost.commands=\
beginfig endfig rotatedaround reflectedabout \
arrowhead currentpen currentpicture cuttings defaultfont \
@@ -80,9 +29,6 @@ yellow black white background graypart \
graycolor mm pt dd bp \
cm pc cc in
-keywordclass.metapost.tex=\
-btex etex verbatimtex
-
keywordclass.metapost.internals=\
mitered rounded beveled butt \
squared eps epsilon infinity bboxmargin \
@@ -90,7 +36,63 @@ ahlength ahangle labeloffset dotlabeldiam defaultpen \
defaultscale join_radius pen_lft pen_rt pen_top \
pen_bot
+keywordclass.metapost.primitives=\
+charcode day linecap linejoin \
+miterlimit month pausing prologues showstopping \
+time tracingcapsules tracingchoices mpprocset tracingcommands \
+tracingequations tracinglostchars tracingmacros tracingonline tracingoutput \
+tracingrestores tracingspecs tracingstats tracingtitles truecorners \
+warningcheck year false nullpicture pencircle \
+true and angle arclength arctime \
+ASCII boolean bot char color \
+cosd cycle decimal directiontime floor \
+fontsize hex infont intersectiontimes known \
+length llcorner lrcorner makepath makepen \
+mexp mlog normaldeviate not numeric \
+oct odd or path pair \
+pen penoffset picture point postcontrol \
+precontrol reverse rotated scaled shifted \
+sind slanted sqrt str string \
+subpath substring transform transformed ulcorner \
+uniformdeviate unknown urcorner xpart xscaled \
+xxpart xypart ypart yscaled yxpart \
+yypart zscaled addto clip input \
+interim let newinternal save setbounds \
+shipout show showdependencies showtoken showvariable \
+special begingroup endgroup of curl \
+tension and controls interpath on \
+off def vardef enddef expr \
+suffix text primary secondary tertiary \
+primarydef secondarydef tertiarydef randomseed also \
+contour doublepath withcolor withpen dashed \
+if else elseif fi for \
+endfor forever exitif within forsuffixes \
+downto upto step until charlist \
+extensible fontdimen headerbyte kern ligtable \
+boundarychar chardp charext charht charic \
+charwd designsize fontmaking charexists cullit \
+currenttransform gfcorners grayfont hround imagerules \
+lowres_fix nodisplays notransforms openit displaying \
+currentwindow screen_rows screen_cols pixels_per_inch cull \
+display openwindow numspecial totalweight autorounding \
+fillin proofing tracingpens xoffset chardx \
+granularity smoothing turningcheck yoffset chardy \
+hppp tracingedges vppp extra_beginfig extra_endfig \
+mpxbreak endinput message delimiters turningnumber \
+errmessage readstring scantokens end outer \
+inner write to readfrom withprescript \
+withpostscript top bot lft rt \
+ulft urt llft lrt redpart \
+greenpart bluepart cyanpart magentapart yellowpart \
+blackpart greypart rgbcolor cmykcolor greycolor \
+graycolor colormodel graypart dashpart penpart \
+stroked filled textual clipped bounded \
+expandafter
+
keywordclass.metapost.shortcuts=\
.. ... -- --- \
&
+keywordclass.metapost.tex=\
+btex etex verbatimtex
+
diff --git a/Master/texmf-dist/context/data/scite/scite-context-data-tex.properties b/Master/texmf-dist/context/data/scite/scite-context-data-tex.properties
index 0f63b994dee..195125433e1 100644
--- a/Master/texmf-dist/context/data/scite/scite-context-data-tex.properties
+++ b/Master/texmf-dist/context/data/scite/scite-context-data-tex.properties
@@ -1,3 +1,8 @@
+keywordclass.tex.aleph=\
+AlephVersion Alephminorversion Alephrevision Alephversion \
+Omegaminorversion Omegarevision Omegaversion boxdir pagebottomoffset \
+pagerightoffset
+
keywordclass.tex.etex=\
botmarks clubpenalties currentgrouplevel currentgrouptype \
currentifbranch currentiflevel currentiftype detokenize dimexpr \
@@ -13,6 +18,51 @@ showtokens splitbotmarks splitdiscards splitfirstmarks topmarks \
tracingassigns tracinggroups tracingifs tracingnesting tracingscantokens \
unexpanded unless widowpenalties
+keywordclass.tex.luatex=\
+Uchar Udelcode Udelcodenum Udelimiter \
+Udelimiterover Udelimiterunder Umathaccent Umathaxis Umathbinbinspacing \
+Umathbinclosespacing Umathbininnerspacing Umathbinopenspacing Umathbinopspacing Umathbinordspacing \
+Umathbinpunctspacing Umathbinrelspacing Umathchar Umathchardef Umathcharnum \
+Umathclosebinspacing Umathcloseclosespacing Umathcloseinnerspacing Umathcloseopenspacing Umathcloseopspacing \
+Umathcloseordspacing Umathclosepunctspacing Umathcloserelspacing Umathcode Umathcodenum \
+Umathconnectoroverlapmin Umathfractiondelsize Umathfractiondenomdown Umathfractiondenomvgap Umathfractionnumup \
+Umathfractionnumvgap Umathfractionrule Umathinnerbinspacing Umathinnerclosespacing Umathinnerinnerspacing \
+Umathinneropenspacing Umathinneropspacing Umathinnerordspacing Umathinnerpunctspacing Umathinnerrelspacing \
+Umathlimitabovebgap Umathlimitabovekern Umathlimitabovevgap Umathlimitbelowbgap Umathlimitbelowkern \
+Umathlimitbelowvgap Umathopbinspacing Umathopclosespacing Umathopenbinspacing Umathopenclosespacing \
+Umathopeninnerspacing Umathopenopenspacing Umathopenopspacing Umathopenordspacing Umathopenpunctspacing \
+Umathopenrelspacing Umathoperatorsize Umathopinnerspacing Umathopopenspacing Umathopopspacing \
+Umathopordspacing Umathoppunctspacing Umathoprelspacing Umathordbinspacing Umathordclosespacing \
+Umathordinnerspacing Umathordopenspacing Umathordopspacing Umathordordspacing Umathordpunctspacing \
+Umathordrelspacing Umathoverbarkern Umathoverbarrule Umathoverbarvgap Umathoverdelimiterbgap \
+Umathoverdelimitervgap Umathpunctbinspacing Umathpunctclosespacing Umathpunctinnerspacing Umathpunctopenspacing \
+Umathpunctopspacing Umathpunctordspacing Umathpunctpunctspacing Umathpunctrelspacing Umathquad \
+Umathradicaldegreeafter Umathradicaldegreebefore Umathradicaldegreeraise Umathradicalkern Umathradicalrule \
+Umathradicalvgap Umathrelbinspacing Umathrelclosespacing Umathrelinnerspacing Umathrelopenspacing \
+Umathrelopspacing Umathrelordspacing Umathrelpunctspacing Umathrelrelspacing Umathspaceafterscript \
+Umathstackdenomdown Umathstacknumup Umathstackvgap Umathsubshiftdown Umathsubshiftdrop \
+Umathsubsupshiftdown Umathsubsupvgap Umathsubtopmax Umathsupbottommin Umathsupshiftdrop \
+Umathsupshiftup Umathsupsubbottommax Umathunderbarkern Umathunderbarrule Umathunderbarvgap \
+Umathunderdelimiterbgap Umathunderdelimitervgap Uoverdelimiter Uradical Uroot \
+Ustack Ustartdisplaymath Ustartmath Ustopdisplaymath Ustopmath \
+Usubscript Usuperscript Uunderdelimiter alignmark aligntab \
+attribute attributedef catcodetable clearmarks crampeddisplaystyle \
+crampedscriptscriptstyle crampedscriptstyle crampedtextstyle fontid formatname \
+gleaders ifabsdim ifabsnum ifprimitive initcatcodetable \
+latelua luaescapestring luastartup luatexdatestamp luatexrevision \
+luatexversion mathstyle nokerns noligs outputbox \
+pageleftoffset pagetopoffset postexhyphenchar posthyphenchar preexhyphenchar \
+prehyphenchar primitive savecatcodetable scantextokens suppressfontnotfounderror \
+suppressifcsnameerror suppresslongerror suppressoutererror synctex
+
+keywordclass.tex.omega=\
+OmegaVersion bodydir chardp charht \
+charit charwd leftghost localbrokenpenalty localinterlinepenalty \
+localleftbox localrightbox mathdir odelcode odelimiter \
+omathaccent omathchar omathchardef omathcode oradical \
+pagedir pageheight pagewidth pardir rightghost \
+textdir
+
keywordclass.tex.pdftex=\
efcode expanded ifincsname ifpdfabsdim \
ifpdfabsnum ifpdfprimitive leftmarginkern letterspacefont lpcode \
@@ -38,201 +88,151 @@ pdftrailer pdfuniformdeviate pdfuniqueresname pdfvorigin pdfxform \
pdfxformattr pdfxformname pdfxformresources pdfximage pdfximagebbox \
quitvmode rightmarginkern rpcode tagcode
-keywordclass.tex.xetex=\
-XeTeXversion
-
keywordclass.tex.tex=\
- / AlephVersion Alephminorversion \
Alephrevision Alephversion OmegaVersion Omegaminorversion Omegarevision \
Omegaversion Udelcode Udelcodenum Udelimiter Udelimiterover \
-Udelimiterunder Umathaccent Umathaccents Umathaxis Umathbinbinspacing \
-Umathbinclosespacing Umathbininnerspacing Umathbinopenspacing Umathbinopspacing Umathbinordspacing \
-Umathbinpunctspacing Umathbinrelspacing Umathbotaccent Umathchar Umathchardef \
-Umathcharnum Umathclosebinspacing Umathcloseclosespacing Umathcloseinnerspacing Umathcloseopenspacing \
-Umathcloseopspacing Umathcloseordspacing Umathclosepunctspacing Umathcloserelspacing Umathcode \
-Umathcodenum Umathconnectoroverlapmin Umathfractiondelsize Umathfractiondenomdown Umathfractiondenomvgap \
-Umathfractionnumup Umathfractionnumvgap Umathfractionrule Umathinnerbinspacing Umathinnerclosespacing \
-Umathinnerinnerspacing Umathinneropenspacing Umathinneropspacing Umathinnerordspacing Umathinnerpunctspacing \
-Umathinnerrelspacing Umathlimitabovebgap Umathlimitabovekern Umathlimitabovevgap Umathlimitbelowbgap \
-Umathlimitbelowkern Umathlimitbelowvgap Umathopbinspacing Umathopclosespacing Umathopenbinspacing \
-Umathopenclosespacing Umathopeninnerspacing Umathopenopenspacing Umathopenopspacing Umathopenordspacing \
-Umathopenpunctspacing Umathopenrelspacing Umathoperatorsize Umathopinnerspacing Umathopopenspacing \
-Umathopopspacing Umathopordspacing Umathoppunctspacing Umathoprelspacing Umathordbinspacing \
-Umathordclosespacing Umathordinnerspacing Umathordopenspacing Umathordopspacing Umathordordspacing \
-Umathordpunctspacing Umathordrelspacing Umathoverbarkern Umathoverbarrule Umathoverbarvgap \
-Umathoverdelimiterbgap Umathoverdelimitervgap Umathpunctbinspacing Umathpunctclosespacing Umathpunctinnerspacing \
-Umathpunctopenspacing Umathpunctopspacing Umathpunctordspacing Umathpunctpunctspacing Umathpunctrelspacing \
-Umathquad Umathradicaldegreeafter Umathradicaldegreebefore Umathradicaldegreeraise Umathradicalkern \
-Umathradicalrule Umathradicalvgap Umathrelbinspacing Umathrelclosespacing Umathrelinnerspacing \
-Umathrelopenspacing Umathrelopspacing Umathrelordspacing Umathrelpunctspacing Umathrelrelspacing \
-Umathspaceafterscript Umathstackdenomdown Umathstacknumup Umathstackvgap Umathsubshiftdown \
-Umathsubshiftdrop Umathsubsupshiftdown Umathsubsupvgap Umathsubtopmax Umathsupbottommin \
-Umathsupshiftdrop Umathsupshiftup Umathsupsubbottommax Umathunderbarkern Umathunderbarrule \
-Umathunderbarvgap Umathunderdelimiterbgap Umathunderdelimitervgap Uoverdelimiter Uradical \
-Uroot Ustack Ustartdisplaymath Ustartmath Ustopdisplaymath \
-Ustopmath Usubscript Usuperscript Uunderdelimiter above \
-abovedisplayshortskip abovedisplayskip abovewithdelims accent adjdemerits \
-advance afterassignment aftergroup alignmark aligntab \
-atop atopwithdelims attribute attributedef badness \
-baselineskip batchmode begingroup belowdisplayshortskip belowdisplayskip \
-binoppenalty bodydir botmark botmarks box \
-boxdir boxmaxdepth brokenpenalty catcode catcodetable \
-char chardef chardp charht charit \
-charwd cleaders clearmarks closein closeout \
-clubpenalties clubpenalty copy count countdef \
-cr crampeddisplaystyle crampedscriptscriptstyle crampedscriptstyle crampedtextstyle \
-crcr csname currentgrouplevel currentgrouptype currentifbranch \
-currentiflevel currentiftype day deadcycles def \
-defaulthyphenchar defaultskewchar delcode delimiter delimiterfactor \
-delimitershortfall detokenize dimen dimendef dimexpr \
-directlua discretionary displayindent displaylimits displaystyle \
-displaywidowpenalties displaywidowpenalty displaywidth divide doublehyphendemerits \
-dp dump eTeXVersion eTeXminorversion eTeXrevision \
-eTeXversion edef efcode else emergencystretch \
-end endcsname endgroup endinput endlinechar \
-eqno errhelp errmessage errorcontextlines errorstopmode \
-escapechar everycr everydisplay everyeof everyhbox \
-everyjob everymath everypar everyvbox exhyphenchar \
-exhyphenpenalty expandafter expanded fam fi \
-finalhyphendemerits firstmark firstmarks floatingpenalty font \
-fontchardp fontcharht fontcharic fontcharwd fontdimen \
-fontid fontname formatname futurelet gdef \
-gleaders global globaldefs glueexpr glueshrink \
-glueshrinkorder gluestretch gluestretchorder gluetomu halign \
-hangafter hangindent hbadness hbox hfil \
-hfill hfilneg hfuzz hoffset holdinginserts \
-hrule hsize hskip hss ht \
-hyphenation hyphenchar hyphenpenalty if ifabsdim \
-ifabsnum ifcase ifcat ifcsname ifdefined \
-ifdim ifeof iffalse iffontchar ifhbox \
-ifhmode ifincsname ifinner ifmmode ifnum \
-ifodd ifpdfabsdim ifpdfabsnum ifpdfprimitive ifprimitive \
-iftrue ifvbox ifvmode ifvoid ifx \
-ignorespaces immediate indent initcatcodetable input \
-inputlineno insert insertpenalties interactionmode interlinepenalties \
-interlinepenalty jobname kern language lastbox \
-lastkern lastlinefit lastnodetype lastpenalty lastskip \
-latelua lccode leaders left leftghost \
-lefthyphenmin leftmarginkern leftskip leqno let \
-letterspacefont limits linepenalty lineskip lineskiplimit \
-localbrokenpenalty localinterlinepenalty localleftbox localrightbox long \
-looseness lower lowercase lpcode luaescapestring \
-luastartup luatexdatestamp luatexrevision luatexversion mag \
-mark marks mathaccent mathbin mathchar \
-mathchardef mathchoice mathclose mathcode mathdir \
-mathinner mathop mathopen mathord mathpunct \
-mathrel mathstyle mathsurround maxdeadcycles maxdepth \
-meaning medmuskip message middle mkern \
-month moveleft moveright mskip muexpr \
-multiply muskip muskipdef mutoglue newlinechar \
-noalign noboundary noexpand noindent nokerns \
-noligs nolimits nolocaldirs nolocalwhatsits nonscript \
-nonstopmode nulldelimiterspace nullfont number numexpr \
-odelcode odelimiter omathaccent omathchar omathchardef \
-omathcode omit openin openout or \
-oradical outer output outputbox outputpenalty \
-over overfullrule overline overwithdelims pagebottomoffset \
-pagedepth pagedir pagediscards pagefilllstretch pagefillstretch \
-pagefilstretch pagegoal pageheight pageleftoffset pagerightoffset \
-pageshrink pagestretch pagetopoffset pagetotal pagewidth \
-par pardir parfillskip parindent parshape \
-parshapedimen parshapeindent parshapelength parskip patterns \
-pausing pdfadjustspacing pdfannot pdfcatalog pdfcolorstack \
-pdfcolorstackinit pdfcompresslevel pdfcopyfont pdfcreationdate pdfdecimaldigits \
-pdfdest pdfdestmargin pdfdraftmode pdfeachlinedepth pdfeachlineheight \
-pdfendlink pdfendthread pdffirstlineheight pdffontattr pdffontexpand \
-pdffontname pdffontobjnum pdffontsize pdfgamma pdfgentounicode \
-pdfglyphtounicode pdfhorigin pdfignoreddimen pdfimageapplygamma pdfimagegamma \
-pdfimagehicolor pdfimageresolution pdfincludechars pdfinclusioncopyfonts pdfinclusionerrorlevel \
-pdfinfo pdfinsertht pdflastannot pdflastlinedepth pdflastlink \
-pdflastobj pdflastxform pdflastximage pdflastximagecolordepth pdflastximagepages \
-pdflastxpos pdflastypos pdflinkmargin pdfliteral pdfmapfile \
-pdfmapline pdfminorversion pdfnames pdfnoligatures pdfnormaldeviate \
-pdfobj pdfobjcompresslevel pdfoptionpdfminorversion pdfoutline pdfoutput \
-pdfpageattr pdfpagebox pdfpageheight pdfpageref pdfpageresources \
-pdfpagesattr pdfpagewidth pdfpkmode pdfpkresolution pdfprimitive \
-pdfprotrudechars pdfpxdimen pdfrandomseed pdfrefobj pdfrefxform \
-pdfrefximage pdfreplacefont pdfrestore pdfretval pdfsave \
-pdfsavepos pdfsetmatrix pdfsetrandomseed pdfstartlink pdfstartthread \
-pdftexbanner pdftexrevision pdftexversion pdfthread pdfthreadmargin \
-pdftracingfonts pdftrailer pdfuniformdeviate pdfuniqueresname pdfvorigin \
-pdfxform pdfxformattr pdfxformname pdfxformresources pdfximage \
-pdfximagebbox penalty postdisplaypenalty postexhyphenchar posthyphenchar \
-predisplaydirection predisplaypenalty predisplaysize preexhyphenchar prehyphenchar \
-pretolerance prevdepth prevgraf primitive protected \
-quitvmode radical raise read readline \
-relax relpenalty right rightghost righthyphenmin \
-rightmarginkern rightskip romannumeral rpcode savecatcodetable \
-savinghyphcodes savingvdiscards scantextokens scantokens scriptfont \
-scriptscriptfont scriptscriptstyle scriptspace scriptstyle scrollmode \
-setbox setlanguage sfcode shipout show \
-showbox showboxbreadth showboxdepth showgroups showifs \
-showlists showthe showtokens skewchar skip \
-skipdef spacefactor spaceskip span special \
-splitbotmark splitbotmarks splitdiscards splitfirstmark splitfirstmarks \
-splitmaxdepth splittopskip string suppressfontnotfounderror suppressifcsnameerror \
-suppresslongerror suppressoutererror synctex tabskip tagcode \
-textdir textfont textstyle the thickmuskip \
-thinmuskip time toks toksdef tolerance \
-topmark topmarks topskip tracingassigns tracingcommands \
-tracinggroups tracingifs tracinglostchars tracingmacros tracingnesting \
-tracingonline tracingoutput tracingpages tracingparagraphs tracingrestores \
-tracingscantokens tracingstats uccode uchyph underline \
-unexpanded unhbox unhcopy unkern unless \
-unpenalty unskip unvbox unvcopy uppercase \
-vadjust valign vbadness vbox vcenter \
-vfil vfill vfilneg vfuzz voffset \
-vrule vsize vskip vsplit vss \
-vtop wd widowpenalties widowpenalty write \
-xdef xleaders xspaceskip year
-
-keywordclass.tex.aleph=\
-AlephVersion Alephminorversion Alephrevision Alephversion \
-Omegaminorversion Omegarevision Omegaversion boxdir pagebottomoffset \
-pagerightoffset
-
-keywordclass.tex.luatex=\
-Udelcode Udelcodenum Udelimiter Udelimiterover \
-Udelimiterunder Umathaccent Umathaccents Umathaxis Umathbinbinspacing \
-Umathbinclosespacing Umathbininnerspacing Umathbinopenspacing Umathbinopspacing Umathbinordspacing \
-Umathbinpunctspacing Umathbinrelspacing Umathbotaccent Umathchar Umathchardef \
-Umathcharnum Umathclosebinspacing Umathcloseclosespacing Umathcloseinnerspacing Umathcloseopenspacing \
-Umathcloseopspacing Umathcloseordspacing Umathclosepunctspacing Umathcloserelspacing Umathcode \
-Umathcodenum Umathconnectoroverlapmin Umathfractiondelsize Umathfractiondenomdown Umathfractiondenomvgap \
-Umathfractionnumup Umathfractionnumvgap Umathfractionrule Umathinnerbinspacing Umathinnerclosespacing \
-Umathinnerinnerspacing Umathinneropenspacing Umathinneropspacing Umathinnerordspacing Umathinnerpunctspacing \
-Umathinnerrelspacing Umathlimitabovebgap Umathlimitabovekern Umathlimitabovevgap Umathlimitbelowbgap \
-Umathlimitbelowkern Umathlimitbelowvgap Umathopbinspacing Umathopclosespacing Umathopenbinspacing \
-Umathopenclosespacing Umathopeninnerspacing Umathopenopenspacing Umathopenopspacing Umathopenordspacing \
-Umathopenpunctspacing Umathopenrelspacing Umathoperatorsize Umathopinnerspacing Umathopopenspacing \
-Umathopopspacing Umathopordspacing Umathoppunctspacing Umathoprelspacing Umathordbinspacing \
-Umathordclosespacing Umathordinnerspacing Umathordopenspacing Umathordopspacing Umathordordspacing \
-Umathordpunctspacing Umathordrelspacing Umathoverbarkern Umathoverbarrule Umathoverbarvgap \
-Umathoverdelimiterbgap Umathoverdelimitervgap Umathpunctbinspacing Umathpunctclosespacing Umathpunctinnerspacing \
-Umathpunctopenspacing Umathpunctopspacing Umathpunctordspacing Umathpunctpunctspacing Umathpunctrelspacing \
-Umathquad Umathradicaldegreeafter Umathradicaldegreebefore Umathradicaldegreeraise Umathradicalkern \
-Umathradicalrule Umathradicalvgap Umathrelbinspacing Umathrelclosespacing Umathrelinnerspacing \
-Umathrelopenspacing Umathrelopspacing Umathrelordspacing Umathrelpunctspacing Umathrelrelspacing \
-Umathspaceafterscript Umathstackdenomdown Umathstacknumup Umathstackvgap Umathsubshiftdown \
-Umathsubshiftdrop Umathsubsupshiftdown Umathsubsupvgap Umathsubtopmax Umathsupbottommin \
-Umathsupshiftdrop Umathsupshiftup Umathsupsubbottommax Umathunderbarkern Umathunderbarrule \
-Umathunderbarvgap Umathunderdelimiterbgap Umathunderdelimitervgap Uoverdelimiter Uradical \
-Uroot Ustack Ustartdisplaymath Ustartmath Ustopdisplaymath \
-Ustopmath Usubscript Usuperscript Uunderdelimiter alignmark \
-aligntab attribute attributedef catcodetable clearmarks \
-crampeddisplaystyle crampedscriptscriptstyle crampedscriptstyle crampedtextstyle fontid \
-formatname gleaders ifabsdim ifabsnum ifprimitive \
-initcatcodetable latelua luaescapestring luastartup luatexdatestamp \
-luatexrevision luatexversion mathstyle nokerns noligs \
-outputbox pageleftoffset pagetopoffset postexhyphenchar posthyphenchar \
-preexhyphenchar prehyphenchar primitive savecatcodetable scantextokens \
-suppressfontnotfounderror suppressifcsnameerror suppresslongerror suppressoutererror synctex
+Udelimiterunder Umathaccent Umathaxis Umathbinbinspacing Umathbinclosespacing \
+Umathbininnerspacing Umathbinopenspacing Umathbinopspacing Umathbinordspacing Umathbinpunctspacing \
+Umathbinrelspacing Umathchar Umathchardef Umathcharnum Umathclosebinspacing \
+Umathcloseclosespacing Umathcloseinnerspacing Umathcloseopenspacing Umathcloseopspacing Umathcloseordspacing \
+Umathclosepunctspacing Umathcloserelspacing Umathcode Umathcodenum Umathconnectoroverlapmin \
+Umathfractiondelsize Umathfractiondenomdown Umathfractiondenomvgap Umathfractionnumup Umathfractionnumvgap \
+Umathfractionrule Umathinnerbinspacing Umathinnerclosespacing Umathinnerinnerspacing Umathinneropenspacing \
+Umathinneropspacing Umathinnerordspacing Umathinnerpunctspacing Umathinnerrelspacing Umathlimitabovebgap \
+Umathlimitabovekern Umathlimitabovevgap Umathlimitbelowbgap Umathlimitbelowkern Umathlimitbelowvgap \
+Umathopbinspacing Umathopclosespacing Umathopenbinspacing Umathopenclosespacing Umathopeninnerspacing \
+Umathopenopenspacing Umathopenopspacing Umathopenordspacing Umathopenpunctspacing Umathopenrelspacing \
+Umathoperatorsize Umathopinnerspacing Umathopopenspacing Umathopopspacing Umathopordspacing \
+Umathoppunctspacing Umathoprelspacing Umathordbinspacing Umathordclosespacing Umathordinnerspacing \
+Umathordopenspacing Umathordopspacing Umathordordspacing Umathordpunctspacing Umathordrelspacing \
+Umathoverbarkern Umathoverbarrule Umathoverbarvgap Umathoverdelimiterbgap Umathoverdelimitervgap \
+Umathpunctbinspacing Umathpunctclosespacing Umathpunctinnerspacing Umathpunctopenspacing Umathpunctopspacing \
+Umathpunctordspacing Umathpunctpunctspacing Umathpunctrelspacing Umathquad Umathradicaldegreeafter \
+Umathradicaldegreebefore Umathradicaldegreeraise Umathradicalkern Umathradicalrule Umathradicalvgap \
+Umathrelbinspacing Umathrelclosespacing Umathrelinnerspacing Umathrelopenspacing Umathrelopspacing \
+Umathrelordspacing Umathrelpunctspacing Umathrelrelspacing Umathspaceafterscript Umathstackdenomdown \
+Umathstacknumup Umathstackvgap Umathsubshiftdown Umathsubshiftdrop Umathsubsupshiftdown \
+Umathsubsupvgap Umathsubtopmax Umathsupbottommin Umathsupshiftdrop Umathsupshiftup \
+Umathsupsubbottommax Umathunderbarkern Umathunderbarrule Umathunderbarvgap Umathunderdelimiterbgap \
+Umathunderdelimitervgap Uoverdelimiter Uradical Uroot Ustack \
+Ustartdisplaymath Ustartmath Ustopdisplaymath Ustopmath Usubscript \
+Usuperscript Uunderdelimiter above abovedisplayshortskip abovedisplayskip \
+abovewithdelims accent adjdemerits advance afterassignment \
+aftergroup alignmark aligntab atop atopwithdelims \
+attribute attributedef badness baselineskip batchmode \
+begingroup belowdisplayshortskip belowdisplayskip binoppenalty bodydir \
+botmark botmarks box boxdir boxmaxdepth \
+brokenpenalty catcode catcodetable char chardef \
+chardp charht charit charwd cleaders \
+clearmarks closein closeout clubpenalties clubpenalty \
+copy count countdef cr crampeddisplaystyle \
+crampedscriptscriptstyle crampedscriptstyle crampedtextstyle crcr csname \
+currentgrouplevel currentgrouptype currentifbranch currentiflevel currentiftype \
+day deadcycles def defaulthyphenchar defaultskewchar \
+delcode delimiter delimiterfactor delimitershortfall detokenize \
+dimen dimendef dimexpr directlua discretionary \
+displayindent displaylimits displaystyle displaywidowpenalties displaywidowpenalty \
+displaywidth divide doublehyphendemerits dp dump \
+eTeXVersion eTeXminorversion eTeXrevision eTeXversion edef \
+efcode else emergencystretch end endcsname \
+endgroup endinput endlinechar eqno errhelp \
+errmessage errorcontextlines errorstopmode escapechar everycr \
+everydisplay everyeof everyhbox everyjob everymath \
+everypar everyvbox exhyphenchar exhyphenpenalty expandafter \
+expanded fam fi finalhyphendemerits firstmark \
+firstmarks floatingpenalty font fontchardp fontcharht \
+fontcharic fontcharwd fontdimen fontid fontname \
+formatname futurelet gdef gleaders global \
+globaldefs glueexpr glueshrink glueshrinkorder gluestretch \
+gluestretchorder gluetomu halign hangafter hangindent \
+hbadness hbox hfil hfill hfilneg \
+hfuzz hoffset holdinginserts hrule hsize \
+hskip hss ht hyphenation hyphenchar \
+hyphenpenalty if ifabsdim ifabsnum ifcase \
+ifcat ifcsname ifdefined ifdim ifeof \
+iffalse iffontchar ifhbox ifhmode ifincsname \
+ifinner ifmmode ifnum ifodd ifpdfabsdim \
+ifpdfabsnum ifpdfprimitive ifprimitive iftrue ifvbox \
+ifvmode ifvoid ifx ignorespaces immediate \
+indent initcatcodetable input inputlineno insert \
+insertpenalties interactionmode interlinepenalties interlinepenalty jobname \
+kern language lastbox lastkern lastlinefit \
+lastnodetype lastpenalty lastskip latelua lccode \
+leaders left leftghost lefthyphenmin leftmarginkern \
+leftskip leqno let letterspacefont limits \
+linepenalty lineskip lineskiplimit localbrokenpenalty localinterlinepenalty \
+localleftbox localrightbox long looseness lower \
+lowercase lpcode luaescapestring luastartup luatexdatestamp \
+luatexrevision luatexversion mag mark marks \
+mathaccent mathbin mathchar mathchardef mathchoice \
+mathclose mathcode mathdir mathinner mathop \
+mathopen mathord mathpunct mathrel mathstyle \
+mathsurround maxdeadcycles maxdepth meaning medmuskip \
+message middle mkern month moveleft \
+moveright mskip muexpr multiply muskip \
+muskipdef mutoglue newlinechar noalign noboundary \
+noexpand noindent nokerns noligs nolimits \
+nolocaldirs nolocalwhatsits nonscript nonstopmode nulldelimiterspace \
+nullfont number numexpr odelcode odelimiter \
+omathaccent omathchar omathchardef omathcode omit \
+openin openout or oradical outer \
+output outputbox outputpenalty over overfullrule \
+overline overwithdelims pagebottomoffset pagedepth pagedir \
+pagediscards pagefilllstretch pagefillstretch pagefilstretch pagegoal \
+pageheight pageleftoffset pagerightoffset pageshrink pagestretch \
+pagetopoffset pagetotal pagewidth par pardir \
+parfillskip parindent parshape parshapedimen parshapeindent \
+parshapelength parskip patterns pausing pdfadjustspacing \
+pdfannot pdfcatalog pdfcolorstack pdfcolorstackinit pdfcompresslevel \
+pdfcopyfont pdfcreationdate pdfdecimaldigits pdfdest pdfdestmargin \
+pdfdraftmode pdfeachlinedepth pdfeachlineheight pdfendlink pdfendthread \
+pdffirstlineheight pdffontattr pdffontexpand pdffontname pdffontobjnum \
+pdffontsize pdfgamma pdfgentounicode pdfglyphtounicode pdfhorigin \
+pdfignoreddimen pdfimageapplygamma pdfimagegamma pdfimagehicolor pdfimageresolution \
+pdfincludechars pdfinclusioncopyfonts pdfinclusionerrorlevel pdfinfo pdfinsertht \
+pdflastannot pdflastlinedepth pdflastlink pdflastobj pdflastxform \
+pdflastximage pdflastximagecolordepth pdflastximagepages pdflastxpos pdflastypos \
+pdflinkmargin pdfliteral pdfmapfile pdfmapline pdfminorversion \
+pdfnames pdfnoligatures pdfnormaldeviate pdfobj pdfobjcompresslevel \
+pdfoptionpdfminorversion pdfoutline pdfoutput pdfpageattr pdfpagebox \
+pdfpageheight pdfpageref pdfpageresources pdfpagesattr pdfpagewidth \
+pdfpkmode pdfpkresolution pdfprimitive pdfprotrudechars pdfpxdimen \
+pdfrandomseed pdfrefobj pdfrefxform pdfrefximage pdfreplacefont \
+pdfrestore pdfretval pdfsave pdfsavepos pdfsetmatrix \
+pdfsetrandomseed pdfstartlink pdfstartthread pdftexbanner pdftexrevision \
+pdftexversion pdfthread pdfthreadmargin pdftracingfonts pdftrailer \
+pdfuniformdeviate pdfuniqueresname pdfvorigin pdfxform pdfxformattr \
+pdfxformname pdfxformresources pdfximage pdfximagebbox penalty \
+postdisplaypenalty postexhyphenchar posthyphenchar predisplaydirection predisplaypenalty \
+predisplaysize preexhyphenchar prehyphenchar pretolerance prevdepth \
+prevgraf primitive protected quitvmode radical \
+raise read readline relax relpenalty \
+right rightghost righthyphenmin rightmarginkern rightskip \
+romannumeral rpcode savecatcodetable savinghyphcodes savingvdiscards \
+scantextokens scantokens scriptfont scriptscriptfont scriptscriptstyle \
+scriptspace scriptstyle scrollmode setbox setlanguage \
+sfcode shipout show showbox showboxbreadth \
+showboxdepth showgroups showifs showlists showthe \
+showtokens skewchar skip skipdef spacefactor \
+spaceskip span special splitbotmark splitbotmarks \
+splitdiscards splitfirstmark splitfirstmarks splitmaxdepth splittopskip \
+string suppressfontnotfounderror suppressifcsnameerror suppresslongerror suppressoutererror \
+synctex tabskip tagcode textdir textfont \
+textstyle the thickmuskip thinmuskip time \
+toks toksdef tolerance topmark topmarks \
+topskip tracingassigns tracingcommands tracinggroups tracingifs \
+tracinglostchars tracingmacros tracingnesting tracingonline tracingoutput \
+tracingpages tracingparagraphs tracingrestores tracingscantokens tracingstats \
+uccode uchyph underline unexpanded unhbox \
+unhcopy unkern unless unpenalty unskip \
+unvbox unvcopy uppercase vadjust valign \
+vbadness vbox vcenter vfil vfill \
+vfilneg vfuzz voffset vrule vsize \
+vskip vsplit vss vtop wd \
+widowpenalties widowpenalty write xdef xleaders \
+xspaceskip year
-keywordclass.tex.omega=\
-OmegaVersion bodydir chardp charht \
-charit charwd leftghost localbrokenpenalty localinterlinepenalty \
-localleftbox localrightbox mathdir odelcode odelimiter \
-omathaccent omathchar omathchardef omathcode oradical \
-pagedir pageheight pagewidth pardir rightghost \
-textdir
+keywordclass.tex.xetex=\
+XeTeXversion
diff --git a/Master/texmf-dist/context/data/scite/scite-context-external.properties b/Master/texmf-dist/context/data/scite/scite-context-external.properties
index 6bba2b7ff91..5c71493412a 100644
--- a/Master/texmf-dist/context/data/scite/scite-context-external.properties
+++ b/Master/texmf-dist/context/data/scite/scite-context-external.properties
@@ -30,23 +30,28 @@ if PLAT_GTK
lexer.*.lpeg=lpeg
+file.patterns.cweb=*.h;*.c;*.w;*.hh;*.cc;*.ww;*.hpp;*.cpp;*.hxx;*.cxx;
+
lexer.$(file.patterns.metapost)=lpeg_scite-context-lexer-mps
lexer.$(file.patterns.metafun)=lpeg_scite-context-lexer-mps
lexer.$(file.patterns.context)=lpeg_scite-context-lexer-tex
-lexer.$(file.patterns.tex)=lpeg_scite-context-lexer-tex
lexer.$(file.patterns.lua)=lpeg_scite-context-lexer-lua
lexer.$(file.patterns.example)=lpeg_scite-context-lexer-xml
lexer.$(file.patterns.text)=lpeg_scite-context-lexer-txt
lexer.$(file.patterns.pdf)=lpeg_scite-context-lexer-pdf
+lexer.$(file.patterns.cweb)=lpeg_scite-context-lexer-web
+
+lexer.$(file.patterns.tex)=lpeg_scite-context-lexer-tex
+lexer.$(file.patterns.xml)=lpeg_scite-context-lexer-xml
+lexer.$(file.patterns.html)=lpeg_scite-context-lexer-xml
+lexer.$(file.patterns.cpp)=lpeg_scite-context-lexer-web
+
+# It's a real pitty that we cannot overload the errorlist lexer. That would
+# make scite even more interesting. Add to that including lpeg and the lpeg
+# lexer and thereby providing an interface to properties.
-#~ lexer.$(file.patterns.metapost)=lpeg_ctx-mps
-#~ lexer.$(file.patterns.metafun)=lpeg_ctx-mps
-#~ lexer.$(file.patterns.context)=lpeg_ctx-tex
-#~ lexer.$(file.patterns.tex)=lpeg_ctx-tex
-#~ lexer.$(file.patterns.lua)=lpeg_ctx-lua
-#~ lexer.$(file.patterns.example)=lpeg_ctx-xml
-#~ lexer.$(file.patterns.text)=lpeg_ctx-txt
-#~ lexer.$(file.patterns.pdf)=lpeg_ctx-pdf
+# lexer.errorlist=lpeg_scite-context-lexer-txt
+# lexer.output=lpeg_scite-context-lexer-txt
comment.block.lpeg_scite-context-lexer-tex=%
comment.block.at.line.start.lpeg_scite-context-lexer-tex=1
diff --git a/Master/texmf-dist/context/data/scite/scite-context-internal.properties b/Master/texmf-dist/context/data/scite/scite-context-internal.properties
index 92806b8e22e..130e64f1e97 100644
--- a/Master/texmf-dist/context/data/scite/scite-context-internal.properties
+++ b/Master/texmf-dist/context/data/scite/scite-context-internal.properties
@@ -80,3 +80,7 @@ lexer.context.auto.if=1
lexer.$(file.patterns.context)=tex
lexer.$(file.patterns.tex)=tex
+
+lexer.$(file.patterns.example)=xml
+lexer.$(file.patterns.lua)=lua
+lexer.$(file.patterns.metafun)=metapost
diff --git a/Master/texmf-dist/context/data/scite/scite-context-readme.pdf b/Master/texmf-dist/context/data/scite/scite-context-readme.pdf
index 32c9628b60d..5e68aecc783 100644
Binary files a/Master/texmf-dist/context/data/scite/scite-context-readme.pdf and b/Master/texmf-dist/context/data/scite/scite-context-readme.pdf differ
diff --git a/Master/texmf-dist/context/data/scite/scite-context-readme.tex b/Master/texmf-dist/context/data/scite/scite-context-readme.tex
index 6221d7cde94..0789401b83c 100644
--- a/Master/texmf-dist/context/data/scite/scite-context-readme.tex
+++ b/Master/texmf-dist/context/data/scite/scite-context-readme.tex
@@ -200,17 +200,19 @@ can move it around. There are no special dependencies on the
operating system.
Next you need to install the lpeg lexers. \footnote {Versions
-later than 2.11 will not run on Windows 2K. In that case you need
+later than 2.11 will not run on \MSWINDOWS\ 2K. In that case you need
to comment the external lexer import.} These can be fetched from:
\starttyping
-code.google.com/p/scintilla
+http://foicica.com/scintillua/
\stoptyping
-On windows you need to copy the \type {lexers} subfolder to the
-\type {wscite} folder. For Linux the place depends on the
-distribution and I just copy them in the same path as where the
-regular properties files live.
+On \MSWINDOWS\ you need to copy the \type {lexers} subfolder to the \type
+{wscite} folder. For \LINUX\ the place depends on the distribution and I just
+copy them in the same path as where the regular properties files live. \footnote
+{If you update, don't do so without testing first. Sometimes there are changes in
+\SCITE\ that influence the lexers in which case you have to wait till we have
+update them to suit those changes.}
For \UNIX, one can take a precompiled version as well. Here we
need to split the set of files into:
@@ -231,7 +233,7 @@ If you want to use \CONTEXT, you need to copy the relevant files from
to the path were \SCITE\ keeps its property files (\type (*.properties).
There is a file called \type {SciteGlobal.properties}. At the end
-of that file (on windows it is in the path where the Scite binary)
+of that file (on \MSWINDOWS\ it is in the path where the Scite binary)
you then add a line to the end:
\starttyping
@@ -312,7 +314,7 @@ property files instead.
These files go to the \type {lexers} subpath in your \SCITE\
installation. Normally this sits in the binary path. The
-following files provide some extensions. On windows you can copy
+following files provide some extensions. On \MSWINDOWS\ you can copy
these files to the path where the \SCITE\ binary lives.
\starttyping
@@ -344,7 +346,7 @@ scite-ctx-context.properties
scite-ctx-example.properties
\stoptyping
-On Windows these go to:
+On \MSWINDOWS\ these go to:
\starttyping
c:/Users/YourName
@@ -444,7 +446,7 @@ But probably better is to use the next directive just below the
usual \XML\ marker line:
\starttyping
-
+
\stoptyping
\subject{Interface selection}
diff --git a/Master/texmf-dist/context/data/scite/scite-context.properties b/Master/texmf-dist/context/data/scite/scite-context.properties
index 1a4f0f5e822..571396b58a6 100644
--- a/Master/texmf-dist/context/data/scite/scite-context.properties
+++ b/Master/texmf-dist/context/data/scite/scite-context.properties
@@ -56,45 +56,41 @@ textwrapper.length=68
file.patterns.tex=
file.patterns.latex=
-file.patterns.context=*.tex;*.mkii;*.mkiv;*.mkvi;
+file.patterns.context=*.tex;*.mkii;*.mkiv;*.mkvi;*.mkix;*.mkxi;
open.suffix.$(file.patterns.context)=.tex
# Example : patterns
file.patterns.xml=
-file.patterns.example=*.xml;*.xsl;*.xsd;*.fo;*.exa;*.rlb;*.rlg;*.rlv;*.rng;*.xfdf;*.xslt;*.dtd;*.lmx;*.ctx;*.export;
-
+file.patterns.example=*.xml;*.xsl;*.xsd;*.fo;*.exa;*.rlb;*.rlg;*.rlv;*.rng;*.xfdf;*.xslt;*.dtd;*.lmx;*.htm;*.html;*.xhtml*.ctx;*.export;
open.suffix.$(file.patterns.example)=.xml
-
filter.example=eXaMpLe|$(file.patterns.example)|
-
-lexer.$(file.patterns.example)=xml
+#~ lexer.$(file.patterns.example)=xml
# Lua : patterns
-file.patterns.lua=*.lua;*.luc;*.cld;*.tuc;*.luj;*.lum;*.tma;*.lfg
-
+file.patterns.lua=*.lua;*.luc;*.cld;*.tuc;*.luj;*.lum;*.tma;*.lfg;*.luv;*.lui
open.suffix.$(file.patterns.lua)=.lua
-
filter.lua=Lua MkIV|$(file.patterns.lua)|
-lexer.$(file.patterns.lua)=lua
+#~ lexer.$(file.patterns.lua)=lua
command.compile.$(file.patterns.lua)=mtxrun --script "$(FileNameExt)"
command.go.$(file.patterns.lua)=mtxrun --script "$(FileNameExt)"
+# W: patterns
+#
+# file.patterns.w=*.c;*.w;*.cc;*.cpp;*.cxx;*.h;*.hh;*.hpp;*.hxx;
+
# Test: patterns
file.patterns.text=*.txt
-
filter.text=Text |$(file.patterns.text)|
+# lexer.$(file.patterns.txt)=txt
file.patterns.pdf=*.pdf
-
filter.pdf=PDF |$(file.patterns.pdf)|
-# lexer.$(file.patterns.txt)=txt
-
# Commands: some scripts
if PLAT_WIN
@@ -140,6 +136,8 @@ if PLAT_GTK
# Commands: help info, e:\websites\www.pragma-ade.com\showcase.pdf / todo: manuals
command.help.$(file.patterns.context)=$(name.context.texshow) $(CurrentWord)
+command.help.$(file.patterns.context)=mtxrun --gethelp --url="http://localhost:31415/mtx-server-ctx-help.lua?command=%command%" --command="$(CurrentWord)"
+command.help.$(file.patterns.context)=mtxrun --gethelp --url="http://www.contextgarden.net/Command/%command%" --command="$(CurrentWord)"
command.help.$(file.patterns.example)=
command.help.$(file.patterns.metafun)=
@@ -169,9 +167,9 @@ command.compile.$(file.patterns.example)=$(name.example.xmlcheck) $(FileNameExt)
command.compile.*.fo=$(name.example.xmlcheck) $(FileNameExt)
command.build.$(file.patterns.context)=$(name.context.run) $(FileNameExt)
-command.build.$(file.patterns.metafun)=$(name.metafun.mptopdf) $(FileNameExt)
-command.build.$(file.patterns.example)=$(name.context.run) --xml $(FileNameExt)
-command.build.*.fo=$(name.context.run) $(name.flag.pdfopen) --xml --use=foxet $(FileNameExt)
+command.build.$(file.patterns.metafun)=$(name.context.mtxrun) --script context $(name.flag.pdfopen) $(FileNameExt)
+command.build.$(file.patterns.example)=$(name.context.run) --forcexml $(FileNameExt)
+command.build.*.fo=$(name.context.run) $(name.flag.pdfopen) --forcexml --use=foxet $(FileNameExt)
command.build.subsystem.$(file.patterns.context)=1
command.build.subsystem.$(file.patterns.metafun)=1
@@ -551,16 +549,12 @@ style.errorlist.16=fore:$(colors.red)
# Metapost: patterns
-file.patterns.metafun=
-
file.patterns.metafun=*.mp;*.mpx;*.mpy;*.mpii;*.mpiv
-
filter.metafun=MetaFun|$(file.patterns.metafun)|
-
-lexer.$(file.patterns.metafun)=metapost
+#~ lexer.$(file.patterns.metafun)=metapost
command.compile.$(file.patterns.metafun)=
-command.build.$(file.patterns.metafun)=context $(FileNameExt)
+command.build.$(file.patterns.metafun)=$(name.context.mtxrun) --script context $(name.flag.pdfopen) $(FileNameExt)
command.go.$(file.patterns.metafun)=gv $(FileName).1
command.0.$(file.patterns.metafun)=
@@ -664,3 +658,5 @@ fold.margin.colour=#CCCCCC
# testing
#~ cache.layout=
+
+find.command=mtxrun --script grep "$(find.what)" "$(find.files)"
diff --git a/Master/texmf-dist/context/data/scite/scite-ctx.lua b/Master/texmf-dist/context/data/scite/scite-ctx.lua
index 3557994f383..546cac41197 100644
--- a/Master/texmf-dist/context/data/scite/scite-ctx.lua
+++ b/Master/texmf-dist/context/data/scite/scite-ctx.lua
@@ -70,7 +70,7 @@
props = props or { } -- setmetatable(props,{ __index = function(k,v) props[k] = "unknown" return "unknown" end } )
-local byte, lower, upper, gsub, sub, find, rep, match, gmatch = string.byte, string.lower, string.upper, string.gsub, string.sub, string.find, string.rep, string.match, string.gmatch
+local byte, lower, upper, gsub, sub, find, rep, match, gmatch, format = string.byte, string.lower, string.upper, string.gsub, string.sub, string.find, string.rep, string.match, string.gmatch, string.format
local sort, concat = table.sort, table.concat
local crlf = "\n"
@@ -80,7 +80,7 @@ function traceln(str)
io.flush()
end
-function string.grab(str,delimiter)
+local function grab(str,delimiter)
local list = { }
for snippet in gmatch(str,delimiter) do
list[#list+1] = snippet
@@ -88,15 +88,15 @@ function string.grab(str,delimiter)
return list
end
-function string.expand(str)
+local function expand(str)
return (gsub(str,"ENV%((%w+)%)", os.envvar))
end
-function string.strip(str)
+local function strip(str)
return (gsub(str,"^%s*(.-)%s*$", "%1"))
end
-function table.alphasort(list,i)
+local function alphasort(list,i)
if i and i > 0 then
local function alphacmp(a,b)
return lower(gsub(sub(a,i),'0',' ')) < lower(gsub(sub(b,i),'0',' '))
@@ -181,13 +181,16 @@ function extend_to_end() -- editor:LineEndExtend() does not work
while line == editor:LineFromPosition(selectionend+1) do
selectionend = selectionend + 1
editor:SetSel(selectionstart,selectionend)
+ if selectionend ~= editor.SelectionEnd then
+ break -- no progress
+ end
end
editor:SetSel(selectionstart,selectionend)
return selectionend
end
function getfiletype()
- local firstline = editor:GetLine(0)
+ local firstline = editor:GetLine(0) or ""
if editor.Lexer == SCLEX_TEX then
return 'tex'
elseif editor.Lexer == SCLEX_XML then
@@ -238,12 +241,12 @@ do
else
print("- 'ctxspellpath is not set")
end
- print("- ctx.spellcheck.wordpath expands to " .. string.expand(props['ctx.spellcheck.wordpath']))
+ print("- ctx.spellcheck.wordpath expands to " .. expand(props['ctx.spellcheck.wordpath']))
end
print("\n- ctx.wraptext.length is set to " .. props['ctx.wraptext.length'])
if props['ctx.helpinfo'] ~= '' then
print("\n- key bindings:\n")
- print((gsub(string.strip(props['ctx.helpinfo']),"%s*\|%s*","\n")))
+ print((gsub(strip(props['ctx.helpinfo']),"%s*|%s*","\n")))
end
print("\n- recognized first lines:\n")
print("xml [^<%-][^<%-]+)([-\/])(%w%w+)","%1 %3"))
+ editor:ReplaceSel(gsub(editor:GetSelText(),"(>[^<%-][^<%-]+)([-/])(%w%w+)","%1 %3"))
else
- editor:ReplaceSel(gsub(editor:GetSelText(),"([^\|])([-\/]+)([^\|])","%1|%2|%3"))
+ editor:ReplaceSel(gsub(editor:GetSelText(),"([^|])([-/]+)([^|])","%1|%2|%3"))
end
end
@@ -570,12 +573,12 @@ function check_text() -- obsolete, replaced by lexer
wordfile, worddone, wordlist = fname, 0, {}
for filename in gmatch(wordfile,"[^%,]+") do
if wordpath ~= '' then
- filename = string.expand(wordpath) .. '/' .. filename
+ filename = expand(wordpath) .. '/' .. filename
end
if io.exists(filename) then
traceln("loading " .. filename)
for line in io.lines(filename) do
- if not find(line,"^[\%\#\-]") then
+ if not find(line,"^[%#-]") then
str = gsub(line,"%s*$", '')
rawset(wordlist,str,true)
worddone = worddone + 1
@@ -644,6 +647,34 @@ function reset_text()
editor:SetStyling(editor.TextLength,INDIC_PLAIN)
end
+function add_text()
+
+ local startposition = editor.SelectionStart
+ local endposition = editor.SelectionEnd
+
+ if startposition == endposition then return end
+
+ local selection = gsub(editor:GetSelText(), "%s*$", '')
+
+ local n, sum = 0, 0
+ for s in gmatch(selection,"[%d%.%,]+") do
+ s = gsub(s,",",".")
+ local m = tonumber(s)
+ if m then
+ n = n + 1
+ sum = sum + m
+ traceln(format("%4i : %s",n,m))
+ end
+ end
+ if n > 0 then
+ traceln("")
+ traceln(format("sum : %s",sum))
+ else
+ traceln("no numbers selected")
+ end
+
+end
+
-- menu
local menuactions = {}
@@ -651,7 +682,7 @@ local menufunctions = {}
function UserListShow(menutrigger, menulist)
local menuentries = {}
- local list = string.grab(menulist,"[^%|]+")
+ local list = grab(menulist,"[^%|]+")
menuactions = {}
for i=1, #list do
if list[i] ~= '' then
diff --git a/Master/texmf-dist/context/data/scite/scite-ctx.properties b/Master/texmf-dist/context/data/scite/scite-ctx.properties
index 8b2651c0d01..e7223d762b2 100644
--- a/Master/texmf-dist/context/data/scite/scite-ctx.properties
+++ b/Master/texmf-dist/context/data/scite/scite-ctx.properties
@@ -25,6 +25,7 @@ ctx.menulist.default=\
wrap=wrap_text|\
unwrap=unwrap_text|\
sort=sort_text|\
+ add=add_text|\
check=check_text|\
reset=reset_text
@@ -35,6 +36,7 @@ ctx.menulist.context=\
document=document_text|\
quote=quote_text|\
compound=compound_text|\
+ add=add_text|\
check=check_text|\
reset=reset_text
@@ -46,6 +48,7 @@ ctx.menulist.example=\
document=document_text|\
quote=quote_text|\
compound=compound_text|\
+ add=add_text|\
check=check_text|\
reset=reset_text
diff --git a/Master/texmf-dist/context/data/scite/scite-pragma.properties b/Master/texmf-dist/context/data/scite/scite-pragma.properties
index 450c609b042..7308f1fb60e 100644
--- a/Master/texmf-dist/context/data/scite/scite-pragma.properties
+++ b/Master/texmf-dist/context/data/scite/scite-pragma.properties
@@ -35,4 +35,6 @@ Metapost|metapost||\
XML|xml||\
Lua|lua||\
Text|txt||\
-PDF|pdf||
+PDF|pdf||\
+CWeb|web||\
+Text|txt||
diff --git a/Master/texmf-dist/doc/context/bib/bibmod-doc.pdf b/Master/texmf-dist/doc/context/bib/bibmod-doc.pdf
deleted file mode 100644
index ea1db316004..00000000000
Binary files a/Master/texmf-dist/doc/context/bib/bibmod-doc.pdf and /dev/null differ
diff --git a/Master/texmf-dist/doc/context/bib/bibmod-doc.tex b/Master/texmf-dist/doc/context/bib/bibmod-doc.tex
deleted file mode 100644
index 2ffdfa9f2f2..00000000000
--- a/Master/texmf-dist/doc/context/bib/bibmod-doc.tex
+++ /dev/null
@@ -1,750 +0,0 @@
-
-\usemodule[int-load]
-\def\loadsetups{}
-\setupinteraction[state=start]
-\setupcolors[state=start]
-
-\usemodule[bib,set-11,mod-01]
-
-
-\startXMLmapping[zero]
-\processXMLfilegrouped{t-bib.xml}
-\stopXMLmapping
-
-\setupitemize[each][packed]
-
-\setuphead[section][page=]
-
-\setupoutput[pdftex]
-
-\def\BIBTEX{Bib\TeX}
-\def\MAPS{Maps}
-
-
-\startbuffer[bibexample]
-\startpublication[k=me,
- t=manual,
- a=Hoekwater,
- y=2006,
- s=TH2006,
- n=1,
- u=http://contextgarden.net/Bibliography]
-\author{Taco}[T.]{}{Hoekwater}
-\title{\CONTEXT\ Publication Module, The user documententation}
-\pubyear{2006}
-\note{In case you didn't know: it's the document you are reading now}
-\pages{14}
-\stoppublication
-\stopbuffer
-
-\getbuffer[bibexample]
-
-\startmodule[type=tex]
-
-\startdocumentation
-
-\module
- [ file=bibmod-doc,
- version=2006.09.15,
- title=Module Documentation,
- subtitle=Bibliographies,
- author={Taco Hoekwater},
- date=\currentdate,
- copyright=Taco Hoekwater]
-
-\completecontent
-
-\section{Introduction}
-
-The bibliographic module (\type{t-bib.tex}) takes care of references
-to publications and the typesetting of publication lists, as well as
-providing an interface between \BIBTEX and \CONTEXT. This manual
-documents version 2009.03.02.
-
-The bibliographic subsystem consists of the main module
-\type{t-bib.tex}; four \BIBTEX\ styles (\type{cont-xx.bst}); and a set
-of example configuration files (\type{bibl-xxx.tex}) that set up
-specific formatting styles for both the citations and the list of
-references.
-
-
-\subsection{General overview}
-
-A typical input file obeys following structure:
-\startitemize[n]
-\item A call to \type{\usemodule[bib]}.
-\item Optionally, a few setup commands for the bibliographic module.
-\item A number of definitions of publications to be referenced in the
-main text of the article. The source of these definitions can be
-a combination of:
- \startitemize
- \item The \type{\jobname.bbl} file (automatically read at \type{\starttext})
- \item extra bbl files
- \item a file or inline macros before \type{\starttext}
- \stopitemize
- These possibilities will be explained below. For now, it is
- only important to realize that of all these definitions have to be known
- {\it before} the first citation in the text.
-\item \type{\starttext}
-\item The body text, with a number of \type{\cite} and \type{\nocite} commands.
-\item The list of publications, called using the command
- \type{\placepublications} or the command\break \type{\completepublications}.
-\item \type{\stoptext}
-\stopitemize
-
-\section{Setup commands}
-
-Bibliographic references use a specific `style', a collection of rules
-for the use of \type{\cite} as well as for the formatting that is
-applied to the publication list. The \CONTEXT\ bibliographic module
-expects you to define all of these style options in one single
-file of which the names starts with the prefix \type{bibl-}.
-
-Unlike the normal situation in \LATEX, this style {\it also\/}
-includes the formatting of the items themselves. Because of this, the
-\type{.bbl} file is set up as a database of entries with fields.
-
-\subsection{Global settings: \type{\setuppublications}}
-
-The most important user-level command is
-\type{\setuppublications}. Most of the options to this command
-shoudl be set by the bibliography style file, but a few of them are of
-immediate interest to the casual user as well.
-
-Like all setup commands, thus command should be given before
-\type{\starttext}, as it sets up global information about the
-bibliographic references used in the document. \CONTEXT\ needs this
-information in order to function correctly.
-
-\setup{setuppublications}
-
-\starttabulate[|l|p|]
-\NC alternative\NC This gives the name of a bibliography style. \crlf
- The chosen style defines the other default options, the options
- given in this documentation are the defaults as they are set up
- by the `apa' style. When this argument is given, the newly set
-style is read in first, before the other options are processed. Thus
-allowing you to override specific settings from the chosen style.\NC\NR
-\NC refcommand \NC the default option for \type{\cite}\NC \NR
-\NC sorttype\NC How the publications in the final publication
- list should be sorted. `cite' means: by the order in which
- they were first cited in your text. `bbl' tells the
- module to keep the relative ordering in which the publication
- definitions were found\crlf
- The current default for apa is `cite'\NC\NR
-\NC criterium\NC Whether to list only the referenced
- publications or all of them.\crlf
- If this value is `all', then if `sorttype' equals `cite', this
- means that all referred-to publications are listed
- before all others, otherwise (if `sorttype' equals `bbl') you will
- just get a typeset version of the used database(s).\crlf
- The default for apa is `used'.\NC\NR
-\NC numbering\NC Whether or not the publication list
- should be labelled and if so, how. \type{yes} uses the item number in
- the publication list as label. \type{short} uses the short
- label. \type{bib}
- uses the original number in the \BIBTEX\ database as a label.
- Anything else turns labelling off.\crlf
- The default for apa is `no'\NC\NR
-\NC autohang\NC Whether or not the
- hanging indent should be re-calculated based on the real size of the
- label. This option only applies if numbering is turned on.\crlf
- The default is `no'.\NC\NR
-\NC monthconversion\NC The presentation form of any month field, if it
- is entered in the database as a numeric value. The default is to
- typeset the number without any conversion\NC\NR
-\stoptabulate
-
-\subsection{How the entries are formatted: \type{\setuppublicationlist}}
-
-\setup{setuppublicationlist}
-
-The list of publications at the end of the article is comparable with
-a sequence of normal \CONTEXT\ `list items' that behaves much like the
-list that defines the table of contents. {\it In previous versions, it was
-in fact implemented as a `normal' \CONTEXT\ list, but this is no
-longer the true.\/}
-
-The module defines a set of extra options. These option names are static, they
-do {\it not} change to follow the selected \CONTEXT\ interface language.
-
-The first two options provide default widths for `autohang':
-\starttabulate[|l|p|]
-\NC totalnumber\NC The total number of items in the following list (used for autohang).\NC\NR
-\NC samplesize\NC The longest short label in the list (used for autohang)\NC\NR
-\stoptabulate
-
-A third option can be used to overrule the use of \type{\title} as
-heading for \type{\completepublications}
-
-\starttabulate[|l|p|]
-\NC title\NC The sectioning command.\NC\NR
-\stoptabulate
-
-A fourth option can be used to nullify the printing of `year suffixes'
-in cases where the author(s) has written multiple works within a
-single year.
-
-\starttabulate[|l|p|]
-\NC maybeyear\NC either \type{on} or \type{off}. Default is \type{on}\NC\NR
-\stoptabulate
-
-The other extra options are needed to control micro||typesetting
-of things that are buried deep within macros. There is a separate
-command to handle the larger layout options
-(\type{\setuppublicationlayout}, explained below), but the options
-here are the only way to make changes in the formatting used for
-editors', authors', and article authors' names.
-\starttabulate[|l|p|]
-\NC author \NC command to typeset one author in the publication list.\NC \NR
-\NC artauthor \NC command to typeset one article author in the publication list.\NC \NR
-\NC editor \NC command to typeset one editor in the publication list.\NC \NR
-\NC namesep \NC the separation between consecutive names (either
- editors, authors or artauthors).\NC \NR
-\NC lastnamesep \NC the separation before the last name in a list of names.\NC \NR
-\NC firstnamesep \NC the separation following the fistname or inits
- within a name in the publication list.\NC \NR
-\NC juniorsep \NC likewise for `junior'.\NC \NR
-\NC vonsep \NC likewise for `von'.\NC \NR
-\NC surnamesep \NC likewise for surname.\NC \NR
-\NC authoretallimit \NC Number of authors needed to trigger `et al.' handling.\NC \NR
-\NC authoretaltext \NC Text to show at the end of an abbreviated list.\NC \NR
-\NC authoretaldisplay \NC Number of authors to actually display in an abbreviated list.\NC \NR
-\NC artauthoretallimit \NC Number of authors needed to trigger `et al.' handling.\NC \NR
-\NC artauthoretaltext \NC Text to show at the end of an abbreviated list.\NC \NR
-\NC artauthoretaldisplay \NC Number of authors to actually display in an abbreviated list.\NC \NR
-\NC editoretallimit \NC Number of editors needed to trigger `et al.' handling.\NC \NR
-\NC editoretaltext \NC Text to show at the end of an abbreviated list.\NC \NR
-\NC editoretaldisplay \NC Number of editors to actually display in an abbreviated list.\NC \NR
-\NC authorcommand \NC A three-argument macro to typeset the list of authors.\NC\NR
-\NC artauthorcommand \NC A three-argument macro to typeset the list of authors.\NC\NR
-\NC editorcommand \NC A three-argument macro to typeset the list of authors.\NC \NR
-\stoptabulate
-
-The commands after `author' e.g. are predefined
-macros that control how a single name is typeset. The four supplied
-macros provide formatting that looks like this:
-
-{\setvalue{@@currentalternative}{data}
-\starttabulate[|l|p|]
-\NC\tex{invertedauthor}\NC \invertedauthor{Taco}{von}{Hoekwater}{T}{jr}\NC\NR
-\NC\tex{invertedshortauthor}\NC \invertedshortauthor{Taco}{von}{Hoekwater}{T}{jr}\NC\NR
-\NC\tex{normalauthor}\NC \normalauthor{Taco}{von}{Hoekwater}{T}{jr}\NC\NR
-\NC\tex{normalshortauthor}\NC \normalshortauthor{Taco}{von}{Hoekwater}{T}{jr}\NC\NR
-\stoptabulate
-}
-As you can see in the examples, there is a connection between certain
-styles of displaying a name and the punctuation used. Punctuation in
-this document has been set up by the `apa' style, and that style makes
-sure that \type{\invertedshortauthor} looks good, since that is the default
-command for `apa' style. (Keep in mind that the comma at the end of the
-author will be inserted by either `namesep' or `lastnamesep'.)
-
-In case you are not happy with the predefined macros; it is quite simple to
-define one of these macros yourself, it is a simple macro with 5
-arguments: firstnames, von-part, surname, inits, junior.
-
-For example, here is the definition of \type{\normalauthor},
-\starttyping
-\def\normalauthor#1#2#3#4#5%
- {\bibdoif{#1}{#1\bibalternative{firstnamesep}}%
- \bibdoif{#2}{#2\bibalternative{vonsep}}%
- #3%
- \bibdoif{#5}{\bibalternative{surnamesep}#5\unskip}}
-\stoptyping
-but commands can be a lot simpler, like this:
-\starttyping
-\def\surnameonly#1#2#3#4#5{#3}
-\setuppublicationlist[editor=\surnameonly]
-\stoptyping
-
-The three-argument macro after `authorcommand' etc. can be used to
-overrule the typesetting of the list of authors (normally done by the
-internal macro \type{\dospecialbibinsert}). This is mostly a hook for
-duplicated author lists in the publication list, that can be handled
-like so:
-
-\starttyping
-\def\oldlist{}
-\def\AbbreviateAuthors#1#2#3%
- {\xdef\newlist{#3}%
- \ifx\oldlist\newlist \hbox to 2em{\hss---\hss}%
- \else \dospecialbibinsert{#1}{#2}{#3}\fi
- \global\let\oldlist\newlist }
-
-\setuppublicationlist
- [artauthorcommand=\AbbreviateAuthors]
-\stoptyping
-The first argument is a list type `author', `artauthor', or `editor',
-the second argument is the number of items that should be typeset,
-and the third argument is a macro containing the commalist of persons,
-in a form suitable for \tex{invertedauthor} and friends.
-
-
-The following options are initialized depending on the
-global settings for `numbering' and `autohang':
-\starttabulate[|l|p|]
-\NC width\NC Set to the calculated width of the largest label, but only if autohang is `yes'\NC\NR
-\NC distance\NC Set to 0pt, but only if autohang is `yes'\NC\NR
-\NC numbercommand\NC A command given in `setuppublications' if numbering is turned on, otherwise empty.\NC\NR
-\NC textcommand\NC Set to a macro that outdents the body text if numbering is turned off, otherwise empty\NC\NR
-\stoptabulate
-
-
-\subsection{Setting citation options: \type{\setupcite}}
-
-The \type{\cite} command has a lot of alternatives, as could be seen
-above in the setting of `refcommand'. And these alternatives have
-their own options:
-
-\setup{setupcite}
-
-\starttabulate[|l|p|]
-\NC andtext \NC separation between two authors (for \type{\cite[author]} styles)\NC \NR
-\NC otherstext \NC text used for `et.al.' (for \type{\cite[author]} styles)\NC \NR
-\NC namesep \NC the separation between consecutive authors (for \type{\cite[author]} styles)\NC \NR
-\NC pubsep \NC separator between publication references in a
- \type{\cite} command.\NC \NR
-\NC lastpubsep \NC same, but for the
- last publication in the list.\NC \NR
-\NC left \NC left side of a \type{\cite} (like \type{[})\NC \NR
-\NC inbetween \NC the separator between parts of a single citation.\NC\NR
-\NC right \NC right side of a \type{\cite} (like \type{]})\NC \NR
-\NC compress \NC Whether \type{\cite} should try to
-compress it's argument list. \NC\NR
-\stoptabulate
-Not all options apply to all types of \type{\cite} commands.
-E.g. `compress' does not apply to the citation
-list for all options of \type{\cite}, since sometimes compression does
-not make sense or is not possible. The `num' version compresses
-into a condensed sorted list, and the various `author' styles try
-to compress all publications by one author, but e.g. years are
-never compressed.
-
-Likewise, `inbetween' only applies to three types: `authoryear' (a
-space), `authoryears' (a comma followed by a space), and `num' (where
-it is `--' (an endash), the character used to separate number ranges).
-
-\subsection{Setting up \BIBTEX: \type{\setupbibtex}}
-
-\BIBTEX\ bibliographic databases are converted into \type{.bbl} files,
-and the generated file is just a more \TEX-minded representation of
-the full database(s).
-
-The four \type{.bst} files do not do any actual formatting on the
-entries, and they do not subset the database either. Instead, the
-{\it entire} database is converted into \TEX-parseable records. About the
-only thing the \type{.bst} files do is sorting the entries (and
-\BIBTEX\ itself resolves any `STRING' specifications, of course).
-
-The module will read the created \type{\jobname.bbl} file
-and select the parts that are needed for the current article.
-
-\setup{setupbibtex}
-
-\starttabulate[|l|p|]
-\NC database\NC List of bibtex database file names to be
- used. The module will write a very short \type{.aux} file instructing
- \BIBTEX\ to create a (possibly very large) \type{\jobname.bbl} file,
- that will be \type{\input} by the module (at \type{\starttext}).\NC\NR
-\NC sort\NC How the publications in the
- \BIBTEX\ database file should be sorted.\crlf
- The default here is `no' (\type{cont-no.bst}), meaning no sorting at all.
- `author' (\type{cont-au.bst}) sorts alphabetically on author and within that on year,
- `title' (\type{cont-ti.bst}) sorts alphabetically on title and then on author and
- year, and `short' (\type{cont-ab.bst}) sorts on the short key that is generated
- by \BIBTEX. If \type{FILE} is given, it specifies an individual \type{.bst} file name used
- by \BIBTEX.\NC\NR
-\stoptabulate
-
-Starting with version 2006.08.08, the module registers \BIBTEX\ as a
-program to be run by texexec, so you no longer need to run \BIBTEX\ by
-hand (and in MkIV, the module runs \BIBTEX\ on the fly using Lua).
-
-Still, you may want to create the \type{\jobname.bbl} yourself. The
-\type{.bbl} syntax is explained below. There is no default
-database of course, and you do not {\it have} to use one: it is
-perfectly OK to just \type{\input} a file with the bibliographic
-records, as long as it has the right input syntax. Or even to include
-the definitions themselves in the preamble of your document.
-
-\subsection{Borrowing publications: \type{\usepublications}}
-
-It is also possible to instruct the module to use the bibliographic
-references belonging to another document. This is done by using the command
-\type{\usepublications[files]}, where \type{files} is a list of other
-\CONTEXT\ documents (without extension).
-
-\setup{usepublications}
-
-To be precise, this command will use the \type{.bbl} and \type{.tuo}
-files from the other document(s), and will therefore not work if these
-files cannot be found (the \type{.tuo} file is needed to get correct
-page references for \type{\cite[page]}).
-
-
-\subsection{Legacy database support}
-
-Old \BIBTEX\ databases tend to contain \LaTeX-specific commands and,
-especially, command||definitions. To make it easier to handle these
-databases, a support module that defines a simplified version of
-\LaTeX's \type{\newcommand} is shipped alongside the bib module.
-You can load this support code by adding
-\starttyping
-\usemodule[bibltx]
-\stoptyping
-to your document preamble.
-
-\section{Citations}
-
-Citations are normally handled through the \type{\cite} command.
-
-\type{\cite} has two basic appearances:
-
-\subsection{Default and explicit citations}
-
-\setup{cite}
-
-The single-argument form executes the style-defined default citation
-command. This is the preferred way of usage, since some styles might
-use numeric citations while others might use a variation of the
-(author,year) style.
-
-The two-argument form allows you to manually select the style you want.
-
-\subsubsection{Citation types}
-
-Following is the full list of recognized keywords for \type{\cite},
-with a short explanation where the data comes from. Most of the
-information that is usable within \type{\cite} comes from the argument
-to \type{\startpublication}. This command is covered in detail below.
-
-
-All of these options are {\it valid} in all publication styles, since
-\CONTEXT\ always has the needed information available. But not all of
-these are {\it sensible} in a particular style: using numbered references if
-the list of publications itself is not numbered is not a good idea, for
-instance. Also, some of the keys are somewhat strange and only
-provided for future extensions.
-
-First, here are the simple ones:
-\starttabulate[|l|l|p|]
-\NC author\NC \cite[author][me] \NC(from `a')\hfil\NC\NR
-\NC doi\NC \cite[doi][me]\NC (from `d')\hfil\NC\NR
-\NC key\NC \cite[key][me]\NC (from `k')\hfil\NC\NR
-\NC serial\NC \cite[serial][me]\NC (from `n')\hfil\NC\NR
-\NC short\NC \cite[short][me]\NC (from `s')\hfil\NC\NR
-\NC type\NC \cite[type][me]\NC (from `t')\hfil\NC\NR
-\NC year\NC \cite[year][me]\NC (from `y')\hfil\NC\NR
-\NC url\NC \cite[url][me]\NC (from `u')\hfil\NC\NR
-\stoptabulate
-Keep in mind that `n' is a database sequence number, and not
-necesarily the same number that is used in the list of
-publications. For instance, if `sorttype' is cite, the list will be
-re-ordered, but the `n' value will remain the same. To get to the
-number that is finally used, use
-\starttabulate[|l|l|p|]
-\NC num\NC \cite[num][me]\NC (this is a reference to
- the sequence number used in the publication list)\hfil\NC\NR
-\stoptabulate
-If the list of publications is not numbered visually, there will still
-be a number available.
-
-Three of the options are combinations:
-\starttabulate[|l|l|p|]
-\NC authoryear\NC \cite[authoryear][me]\NC(from `a' and `y')\hfil\NC\NR
-\NC authoryears\NC \cite[authoryears][me]\NC(from `a' and `y')\hfil\NC\NR
-\NC authornum\NC \cite[authornum][me]\NC(from `a' and `num')\hfil\NC\NR
-\NC data\NC \vtop{\hsize .45\hsize \cite[data][me]}\NC The data content of the entry\hfil\NC\NR
-\stoptabulate
-
-And the last one is a page reference to the page where the
-the entry is typeset within the publication list.
-
-\starttabulate[|l|l|p|]
-\NC page\NC \cite[page][me]\NC (a page reference)\hfil\NC\NR
-\stoptabulate
-
-\subsection{Citations with local setups}
-
-\setup{citealt}
-
-The arguments in this form are inherited from \type{\setupcite},
-except for \type{extras}. The argument of `\type{extras}' is typeset
-at the end of the reference, but before a potential `\type{right}', so
-it can be used for e.g. page or chapter specifiers.
-
-\subsection{Invisible citations}
-
-\setup{nocite}
-
-This command registers the references in the argument list, but does
-not generate typeset material. It can be used to force certain entries
-from the database to appear in the typeset list of publications.
-
-\section{Placing the publication list}
-
-To typset the list of publications, use \type{\completepublications}
-or \type{\placepublications} at the location in your text where you
-want the publication list to appear. As is normal in \CONTEXT,
-\type{\placepublications} gives you a raw list, and
-\type{\completepublications} a list with a title.
-
-
-The default for the publication list is to contain only the `locally'
-referenced items, so if you want to use your own heading instead of
-the default one, you most likely want to call
-\type{\placepublications} with an explicit criterium, like so:
-\starttyping
-\placepublications[criterium=all]
-\stoptyping
-
-If you use a numeric list style combined with multiple , each
-\type{\placepublications} or \type{\completepublications} commands,
-by default each one restarts the displayed number. If you do not
-like that, you can add an option argument like so:
-\starttyping
-\placepublications[option=continue]
-\stoptyping
-
-
-The module uses the following defaults for the generated head:
-\starttyping
-\setupheadtext[en][pubs=References]
-\setupheadtext[nl][pubs=Literatuur]
-\setupheadtext[de][pubs=Literatur]
-\setupheadtext[it][pubs=Bibliografia]
-\setupheadtext[sl][pubs=Literatura]
-\setupheadtext[fr][pubs=Bibliographie]
-\stoptyping
-These (or new ones) can be redefined as needed.
-
-\section{The bbl file}
-
-A typical bbl file consists of one initial command
-(\type{\setuppublicationlist}) that sets some information
-about the number of entries in the bbl file and the widths
-of the labels for the list, and that command is followed by a number of
-appearances of \type{\startpublication ... \stoppublication}
-
-The full appearance version of \type{\cite}
-accepts a number of option keywords, and we saw earlier that
-the argument of the \type{\startpublication} command
-defines most of the things we can reference to. This section explains
-the precise syntax for \type{\startpublication}.
-
-Each single block defines one bibliographic entry. I apologise
-for the use of single||letter keys, but these have the advantage of
-being a)\quad short and b)\quad safe w.r.t. the multi-lingual interface.
-
-\setup{startpublication}
-
-Here is the full example that has been used throughout this document:
-
-\typebuffer[bibexample]
-
-\subsection{Defining a publication}
-
-The list of commands that is allowed to appear between \type{\startpublication}
-and \type{\stoppublication} is given below.
-
-Order within an entry is irrelevant, except for the relative ordering
-within each of the three commands that might appear more than once:
-\type{\artauthor}, \type{\author} and \type{\editor}.
-
-Most of these are `normal' \BIBTEX\ field names (in lowercase), but
-some are extra special, either because they come from non-standard
-databases that I know of, or because the bst file has pre-processed
-the contents of the field.
-
-\subsubsection{Complex fields}
-
-The three fields that contain names are extra special, because they
-have more than one argument. These are: \type{\artauthor},
-\type{\author} and \type{\editor}. These commands require three
-arguments, and there can be two extra optional arguments as well.
-
-
-\starttabulate[|l|l|p|]
-\NC\tex{artauthor[]\{\}[]\{\}\{\}}\NC\tfx AUTHOR\NC For an author of any publication
- that appears within a larger publication, like an article that appears
- within a journal or as part of a proceedings. \NC\NR
-\NC\tex{author[]\{\}[]\{\}\{\}}\NC\tfx AUTHOR\NC The author of a standalone
- publication, like a monograph.\NC\NR
-\NC\tex{editor[]\{\}[]\{\}\{\}}\NC\tfx EDITOR\NC The editor of e.g.
- an edited volume.\NC\NR
-\stoptabulate
-
-The argument lists have this form:
-
-\starttyping
-\author[junior]{firstnames}[inits]{von}{surname}
-\stoptyping
-
-and the meanings are as follows:
-\starttabulate[|l|p|]
-\NC \type{junior} \NC a designation of lineage, only used if confusion is possible (due to family members having the same name).\NC\NR
-\NC \type{firstnames} \NC individual (given) name(s)\NC\NR
-\NC \type{inits} \NC abbreviated form(s) of \type{firstnames}.\NC\NR
-\NC \type{von} \NC any bits of the family name that are normally disregarded in sorting\NC\NR
-\NC \type{surname} \NC remainder of the family (last) name\NC\NR
-\stoptabulate
-
-
-\subsubsection{Simple fields}
-
-Rather a large list, this is caused by the desire to support as many
-existing \BIBTEX\ databases as possible. Please note that a few of
-the fields have names that are not the same as in \BIBTEX, because a
-1~on~1 mapping causes conflicts with predefined macro names in
-\CONTEXT.
-
-\starttabulate[|l|p(2.5cm)|p|]
-\NC\type{\abstract}\NC\tfx ABSTRACT\NC just text.\NC\NR
-\NC\type{\annotate}\NC\tfx ANNOTATE \NC just text.\NC\NR
-\NC\type{\arttitle}\NC\tfx TITLE\NC The title of a partial publication (one that has \type{\artauthor}s).\NC\NR
-\NC\type{\assignee}\NC\tfx ASSIGNEE\NC Assigned person for a patent\NC\NR
-\NC\type{\bibnumber}\NC\tfx NUMBER \NC \NC\NR
-\NC\type{\bibtype}\NC\tfx TYPE \NC See the \BIBTEX\
- documentation for it's use. This is {\it not} related
- to the type of entry that is used for deciding on the
- layout.\NC\NR
-\NC\type{\biburl}\NC\tfx URL \NC Location on the internet. \NC\NR
-\NC\type{\chapter}\NC\tfx CHAPTER \NC the chapter number, if this entry is
-referring to a smaller section of a publication. It might actually
-be a part number or a (sub)section number. The field \type{\bibtype} (above)
-differentiates between these.\NC\NR
-\NC\type{\city}\NC\tfx CITY\NC city of publication.\NC\NR
-\NC\type{\comment}\NC\tfx COMMENT\NC just text.\NC\NR
-\NC\type{\country}\NC\tfx COUNTRY\NC country of publication.\NC\NR
-\NC\type{\crossref}\NC\tfx CROSSREF\NC A cross-reference to another
- bibliographic entry. It will insert a citation
- to that entry, forcing it to be typeset as well.\NC\NR
-\NC\type{\day}\NC\tfx DAY \NC Date of publication (for a patent)\NC\NR
-\NC\type{\dayfiled}\NC\tfx DAYFILED\NC Filing date for a patent\NC\NR
-\NC\type{\doi}\NC\tfx DOI \NC Document Object Identifier\NC\NR
-\NC\type{\edition}\NC\tfx EDITION\NC The edition.\NC\NR
-\NC\type{\eprint}\NC\tfx EPRINT\NC E-print information\NC\NR
-\NC\type{\howpublished}\NC\tfx HOWPUBLISHED\NC \NC\NR
-\NC\type{\isbn}\NC\tfx ISNB\NC isbn number (for books)\NC\NR
-\NC\type{\issn}\NC\tfx ISSN\NC issn number (for journals)\NC\NR
-\NC\type{\issue}\NC\tfx ISSUE\NC issue number (for journals)\NC\NR
-\NC\type{\journal}\NC\tfx JOURNAL \NC The journal's name.\NC\NR
-\NC\type{\keyword}\NC\tfx KEYWORD \NC just text (for use in indices).\NC\NR
-\NC\type{\keywords}\NC\tfx KEYWORDS \NC just text (for use in indices).\NC\NR
-\NC\type{\lang}\NC\tfx LANGUAGE \NC The language of the
- current bibliographic record\NC\NR
-\NC\type{\month}\NC\tfx MONTH\NC Month of publication\NC\NR
-\NC\type{\monthfiled}\NC\tfx MONTHFILED\NC Filing month for a patent\NC\NR
-\NC\type{\names}\NC\tfx NAMES\NC just text (for use in indices).\NC\NR
-\NC\type{\nationality}\NC\tfx NATIONALITY\NC Nationality information for a patent\NC\NR
-\NC\type{\note}\NC\tfx NOTE \NC just text (this is the `standard' \BIBTEX\ commentary field).\NC\NR
-\NC\type{\notes}\NC\tfx NOTES \NC just text.\NC\NR
-\NC\type{\organization}\NC\tfx ORGANIZATION\NC Like institute, but for e.g. companies.\NC\NR
-\NC\type{\pages}\NC\tfx PAGES\NC Either the number of pages, or the page range
- for a partial publication. The `t' key to startpublication
- will decide automatically what is meant.\NC\NR
-\NC\type{\pubname}\NC\tfx INSTITUTION,\crlf PUBLISHER,\crlf SCHOOL\NC Publisher or institution name.\NC\NR
-\NC\type{\pubyear}\NC\tfx YEAR \NC Year of publication. Within this command,
- the \BIBTEX\ bst files will sometimes insert the command
- \type{\maybeyear}, which is needed to make sure that
- the bbl file stay flexible enough to allow all styles of
- formatting.\NC\NR
-\NC\type{\revision}\NC\tfx REVISION \NC Release version\NC\NR
-\NC\type{\series}\NC\tfx SERIES \NC Possible book series information.\NC\NR
-\NC\type{\size}\NC\tfx SIZE \NC Size in KB of a PDF file (this came from
- the NTG \MAPS\ database)\NC\NR
-\NC\type{\thekey}\NC\tfx KEY \NC See the \BIBTEX\
- documentation for it's use. This is {\it not} related to
- the key used for citing this entry.\NC\NR
-\NC\type{\title}\NC\tfx TITLE,\crlf BOOKTITLE \NC The title of a book.\NC\NR
-\NC\type{\volume}\NC\tfx VOLUME \NC Volume number for multi-part books or
- journals.\NC\NR
-\NC\type{\yearfiled}\NC\tfx YEARFILED\NC Filing year for a patent\NC\NR
-\stoptabulate
-
-When the \type{\lang} field's content is a full word instead of a
-two||letter code, correct processing depends on an auxiliary command
-\type{\setbiblanguage}, to be used like this:
-\starttyping
-\setbiblanguage{English}{en}
-\stoptyping
-The first argument is a literal \type{\lang} argument, the second
-argument has to be a two||letter language abbreviation understood by
-\CONTEXT.
-
-Adding in one of your own fields is reasonably simple:
-
-\starttyping
-\newbibfield[mycommand]
-\stoptyping
-This will define \type{\mycommand} for use within
-a publication (plus \type{\bib@mycommand}, it's internal form) as
-well as the command \type{\insertmycommand} that can be used
-within \type{\setuppublicationlayout} to fetch the supplied
-value (see below).
-
-
-\section{Defining a publication type layout}
-
-Publication style files of course take care of setting defaults for the
-commands as explained earlier, but the largest part of a such a
-publication style is concerned with specifying layouts for various
-types of publications.
-
-The command that does the work is \type{\setuppublicationlayout}:
-
-\setup{setuppublicationlayout}
-
-The first argument that is a publication (\BIBTEX\ entry) type, and
-all publications that have this type given as argument to the `t' key
-of \type{\startpublication} will be typeset by executing the commands
-that appear in the group following the command.
-
-For example, here is a possible way to typeset an article: from \type{bibl-apa}:
-\starttyping
-\setuppublicationlayout[article]{%
- \insertartauthors{}{ }{\insertthekey{}{ }{}}%
- \insertpubyear{(}{). }{\unskip.}%
- \insertarttitle{\bgroup }{\egroup. }{}%
- \insertjournal{\bgroup \it}{\egroup}
- {\insertcrossref{In }{}{}}%
- \insertvolume
- {, }
- {\insertissue{(}{)}{}\insertpages{:}{.}{.}}
- {\insertpages{, pages }{.}{.}}%
- \insertnote{ }{.}{}%
- \insertcomment{}{.}{}%
-}
-\stoptyping
-For every command in the long list given in the previous paragraph, there is
-a corresponding \type{\insertxxx} command. (As usual, \type{\author}
-etc. are special: they have a macro called \type{\insertxxxs}
-instead). All of these \type{\insertxxx} macros use the same logic:
-
-\starttyping
-\insertartauthors{}{}{}
-\stoptyping
-
-Sounds easy? It is! But it is also often tedious: database entries can
-be tricky things: some without issue numbers, others without page
-numbers, some even without authors. So, you often need to nest rather
-a lot of commands in the \type{} section of the `upper'
-command, and \type{\unskip} and \type{\ignorespaces} are good friends
-as well.
-
-Incidentally, the distributed \type{bibl-xxx} files define layouts for
-the `standard' publication types that are defined in the example
-bibliography that comes with \BIBTEX. The list of possbile types is in
-no way limited to that list, but it provides a reasonable starting
-point.
-
-\section{References}
-
-\placepublications[criterium=all]
-
-\stopdocumentation
-
-\stopmodule
-
-\stoptext
diff --git a/Master/texmf-dist/doc/context/scripts/mkii/ctxtools.html b/Master/texmf-dist/doc/context/scripts/mkii/ctxtools.html
new file mode 100644
index 00000000000..0cb8799c261
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkii/ctxtools.html
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+ CtxTools 1.3.5
+
+
+
+
+
+
+
+
wiki: http://contextgarden.net | mail: ntg-context@ntg.nl | website: http://www.pragma-ade.nl
+
+
+
+
+
+
+
Command line options
+
+ flag value description
+
+ --touchcontextfile update context version
+ --contextversion report context version
+ --jeditinterface generate jedit syntax files [--pipe]
+ --bbeditinterface generate bbedit syntax files [--pipe]
+ --sciteinterface generate scite syntax files [--pipe]
+ --rawinterface generate raw syntax files [--pipe]
+ --translateinterface generate interface files (xml) [nl de ..]
+ --purgefiles remove temporary files [--all --recurse] [basename]
+ --documentation generate documentation [--type ] [filename]
+ --filterpages' ) # no help, hidden temporary feature
+ --dpxmapfiles convert pdftex mapfiles to dvipdfmx [--force] [texmfroot]
+ --listentities create doctype entity definition from enco-uc.tex
+ --brandfiles add context copyright notice [--force]
+ --platformize replace line-endings [--recurse --force] [pattern]
+ --dependencies analyze depedencies within context [--save --compact --filter [macros|filenames] ] [filename]
+ --updatecontext download latest version and remake formats [--proxy]
+ --disarmutfbom remove utf bom [--force]
+
+
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkii/ctxtools.man b/Master/texmf-dist/doc/context/scripts/mkii/ctxtools.man
new file mode 100644
index 00000000000..93218f2295f
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkii/ctxtools.man
@@ -0,0 +1,75 @@
+.TH "ctxtools" "1" "01-01-2013" "version 1.3.5" "CtxTools"
+.SH NAME
+.B ctxtools
+.SH SYNOPSIS
+.B ctxtools [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B CtxTools
+.SH OPTIONS
+.TP
+.B --touchcontextfile
+update context version
+.TP
+.B --contextversion
+report context version
+.TP
+.B --jeditinterface
+generate jedit syntax files [--pipe]
+.TP
+.B --bbeditinterface
+generate bbedit syntax files [--pipe]
+.TP
+.B --sciteinterface
+generate scite syntax files [--pipe]
+.TP
+.B --rawinterface
+generate raw syntax files [--pipe]
+.TP
+.B --translateinterface
+generate interface files (xml) [nl de ..]
+.TP
+.B --purgefiles
+remove temporary files [--all --recurse] [basename]
+.TP
+.B --documentation generate documentation [--type=]
+[filename]
+.TP
+.B --filterpages'
+) # no help, hidden temporary feature
+.TP
+.B --dpxmapfiles
+convert pdftex mapfiles to dvipdfmx [--force] [texmfroot]
+.TP
+.B --listentities
+create doctype entity definition from enco-uc.tex
+.TP
+.B --brandfiles
+add context copyright notice [--force]
+.TP
+.B --platformize
+replace line-endings [--recurse --force] [pattern]
+.TP
+.B --dependencies analyze depedencies within context [--save --compact --filter=[macros|filenames] ]
+[filename]
+.TP
+.B --updatecontext
+download latest version and remake formats [--proxy]
+.TP
+.B --disarmutfbom
+remove utf bom [--force]
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/context/scripts/mkii/ctxtools.xml b/Master/texmf-dist/doc/context/scripts/mkii/ctxtools.xml
new file mode 100644
index 00000000000..8f51cd93a0d
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkii/ctxtools.xml
@@ -0,0 +1,31 @@
+
+
+
+ ctxtools
+ CtxTools
+ 1.3.5
+
+
+
+
+ update context version
+ report context version
+ generate jedit syntax files [
+ generate bbedit syntax files [
+ generate scite syntax files [
+ generate raw syntax files [
+ generate interface files (xml) [nl de ..]
+ remove temporary files [ [basename]
+ [filename]
+ ) # no help, hidden temporary feature
+ convert pdftex mapfiles to dvipdfmx [ [texmfroot]
+ create doctype entity definition from enco-uc.tex
+ add context copyright notice [
+ replace line-endings [ [pattern]
+ [filename]
+ download latest version and remake formats [
+ remove utf bom [
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkii/imgtopdf.html b/Master/texmf-dist/doc/context/scripts/mkii/imgtopdf.html
new file mode 100644
index 00000000000..37d447aef12
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkii/imgtopdf.html
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+ ImgToPdf 1.1.2
+
+
+
+
+
+
+
+
wiki: http://contextgarden.net | mail: ntg-context@ntg.nl | website: http://www.pragma-ade.nl
+
+
+
+
+
+
+
Command line options
+
+ flag value description
+
+ --convert convert image into pdf
+ --compression level of compression in percent
+ --depth image depth in bits
+ --colorspace colorspace (rgb,cmyk,gray)
+ --quality quality in percent
+ --inputpath path where files are looked for
+ --outputpath path where files end up
+ --auto determine settings automatically
+
+
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkii/imgtopdf.man b/Master/texmf-dist/doc/context/scripts/mkii/imgtopdf.man
new file mode 100644
index 00000000000..5f165363a77
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkii/imgtopdf.man
@@ -0,0 +1,48 @@
+.TH "imgtopdf" "1" "01-01-2013" "version 1.1.2" "ImgToPdf"
+.SH NAME
+.B imgtopdf
+.SH SYNOPSIS
+.B imgtopdf [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B ImgToPdf
+.SH OPTIONS
+.TP
+.B --convert
+convert image into pdf
+.TP
+.B --compression
+level of compression in percent
+.TP
+.B --depth
+image depth in bits
+.TP
+.B --colorspace
+ colorspace (rgb,cmyk,gray)
+.TP
+.B --quality
+quality in percent
+.TP
+.B --inputpath
+path where files are looked for
+.TP
+.B --outputpath
+path where files end up
+.TP
+.B --auto
+determine settings automatically
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/context/scripts/mkii/imgtopdf.xml b/Master/texmf-dist/doc/context/scripts/mkii/imgtopdf.xml
new file mode 100644
index 00000000000..b516852c3d2
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkii/imgtopdf.xml
@@ -0,0 +1,22 @@
+
+
+
+ imgtopdf
+ ImgToPdf
+ 1.1.2
+
+
+
+
+ convert image into pdf
+ level of compression in percent
+ image depth in bits
+ colorspace (rgb,cmyk,gray)
+ quality in percent
+ path where files are looked for
+ path where files end up
+ determine settings automatically
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkii/mptopdf.html b/Master/texmf-dist/doc/context/scripts/mkii/mptopdf.html
new file mode 100644
index 00000000000..e80a3a342ac
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkii/mptopdf.html
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+ MPtoPDF 1.4.1
+
+
+
+
+
+
+
+
wiki: http://contextgarden.net | mail: ntg-context@ntg.nl | website: http://www.pragma-ade.nl
+
+
+
+
+
+
+
Command line options
+
+ flag value description
+
+ --metafun use the metafun format to process the file (default is mpost)
+ --texexec use texexec (context) to process text snippets
+ --latex use latex to process text snippets
+
+
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkii/mptopdf.xml b/Master/texmf-dist/doc/context/scripts/mkii/mptopdf.xml
new file mode 100644
index 00000000000..a3b06a23136
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkii/mptopdf.xml
@@ -0,0 +1,17 @@
+
+
+
+ mptopdf
+ convert MetaPost to PDF
+ 1.4.1
+
+
+
+
+ use the metafun format to process the file (default is mpost)
+ use texexec (context) to process text snippets
+ use latex to process text snippets
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkii/pdftools.html b/Master/texmf-dist/doc/context/scripts/mkii/pdftools.html
new file mode 100644
index 00000000000..4c1e7628100
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkii/pdftools.html
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+ PDFTools 1.2.1
+
+
+
+
+
+
+
+
wiki: http://contextgarden.net | mail: ntg-context@ntg.nl | website: http://www.pragma-ade.nl
+
+
+
+
+
+
+
Command line options
+
+ flag value description
+
+ --spotimage filename --colorspec --colorname= [--retain --invert --subpath=]
+ --colorimage filename --colorspec [--retain --invert --colorname= ]
+ --convertimage filename [--retain --subpath]
+ --downsampleimage filename [--retain --subpath --lowres --normal]
+ --info filename
+ --countpages [--pattern --threshold]
+ --checkembedded [--pattern]
+ --analyzefile filename
+
+
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkii/pdftools.man b/Master/texmf-dist/doc/context/scripts/mkii/pdftools.man
new file mode 100644
index 00000000000..2f182ed0235
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkii/pdftools.man
@@ -0,0 +1,48 @@
+.TH "pdftools" "1" "01-01-2013" "version 1.2.1" "PDFTools"
+.SH NAME
+.B pdftools
+.SH SYNOPSIS
+.B pdftools [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B PDFTools
+.SH OPTIONS
+.TP
+.B --spotimage filename --colorspec
+--colorname= [--retain --invert --subpath=]
+.TP
+.B --colorimage filename --colorspec
+[--retain --invert --colorname= ]
+.TP
+.B --convertimage
+filename [--retain --subpath]
+.TP
+.B --downsampleimage
+filename [--retain --subpath --lowres --normal]
+.TP
+.B --info
+filename
+.TP
+.B --countpages
+[--pattern --threshold]
+.TP
+.B --checkembedded
+[--pattern]
+.TP
+.B --analyzefile
+filename
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/context/scripts/mkii/pdftools.xml b/Master/texmf-dist/doc/context/scripts/mkii/pdftools.xml
new file mode 100644
index 00000000000..292ef4f88f2
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkii/pdftools.xml
@@ -0,0 +1,22 @@
+
+
+
+ pdftools
+ PDFTools
+ 1.2.1
+
+
+
+
+ [
+ [ ]
+ filename [
+ filename [
+ filename
+ [
+ [
+ filename
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkii/pstopdf.html b/Master/texmf-dist/doc/context/scripts/mkii/pstopdf.html
new file mode 100644
index 00000000000..17f9c002dd8
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkii/pstopdf.html
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+ PStoPDF 2.0.1
+
+
+
+
+
+
+
+
wiki: http://contextgarden.net | mail: ntg-context@ntg.nl | website: http://www.pragma-ade.nl
+
+
+
+
+
+
+
Command line options
+
+ flag value description
+
+ --request handles exa request file
+ --watch watch folders for conversions (untested)
+
+
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkii/pstopdf.man b/Master/texmf-dist/doc/context/scripts/mkii/pstopdf.man
new file mode 100644
index 00000000000..71786ce8b79
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkii/pstopdf.man
@@ -0,0 +1,30 @@
+.TH "pstopdf" "1" "01-01-2013" "version 2.0.1" "PStoPDF"
+.SH NAME
+.B pstopdf
+.SH SYNOPSIS
+.B pstopdf [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B PStoPDF
+.SH OPTIONS
+.TP
+.B --request
+handles exa request file
+.TP
+.B --watch
+watch folders for conversions (untested)
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/context/scripts/mkii/pstopdf.xml b/Master/texmf-dist/doc/context/scripts/mkii/pstopdf.xml
new file mode 100644
index 00000000000..d7a7de0ae87
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkii/pstopdf.xml
@@ -0,0 +1,16 @@
+
+
+
+ pstopdf
+ PStoPDF
+ 2.0.1
+
+
+
+
+ handles exa request file
+ watch folders for conversions (untested)
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkii/rlxtools.html b/Master/texmf-dist/doc/context/scripts/mkii/rlxtools.html
new file mode 100644
index 00000000000..a2e39d28677
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkii/rlxtools.html
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+ RlxTools 1.0.1
+
+
+
+
+
+
+
+
wiki: http://contextgarden.net | mail: ntg-context@ntg.nl | website: http://www.pragma-ade.nl
+
+
+
+
+
+
+
Command line options
+
+ flag value description
+
+ --manipulate [--test] manipulatorfile resourselog
+ --identify [--collect] filename
+
+
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkii/rlxtools.man b/Master/texmf-dist/doc/context/scripts/mkii/rlxtools.man
new file mode 100644
index 00000000000..f1bc70b1cc9
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkii/rlxtools.man
@@ -0,0 +1,30 @@
+.TH "rlxtools" "1" "01-01-2013" "version 1.0.1" "RlxTools"
+.SH NAME
+.B rlxtools
+.SH SYNOPSIS
+.B rlxtools [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B RlxTools
+.SH OPTIONS
+.TP
+.B --manipulate
+[--test] manipulatorfile resourselog
+.TP
+.B --identify
+[--collect] filename
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/context/scripts/mkii/rlxtools.xml b/Master/texmf-dist/doc/context/scripts/mkii/rlxtools.xml
new file mode 100644
index 00000000000..8a221eccf63
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkii/rlxtools.xml
@@ -0,0 +1,16 @@
+
+
+
+ rlxtools
+ RlxTools
+ 1.0.1
+
+
+
+
+ [ manipulatorfile resourselog
+ [ filename
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkii/texexec.html b/Master/texmf-dist/doc/context/scripts/mkii/texexec.html
new file mode 100644
index 00000000000..6b0d7c4bec2
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkii/texexec.html
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
+
+
+
+ TeXExec 6.2.1
+
+
+
+
+
+
+
+
wiki: http://contextgarden.net | mail: ntg-context@ntg.nl | website: http://www.pragma-ade.nl
+
+
+
+
+
+
+
Command line options
+
+ flag value description
+
+ --make make formats
+ --check check versions
+ --process process file
+ --mptex process mp file
+ --mpxtex process mpx file
+ --mpgraphic process mp file to stand-alone graphics
+ --mpstatic process mp/ctx file to stand-alone graphics
+ --listing list of file content
+ --figures generate overview of figures
+ --modules generate module documentation
+ --pdfarrange impose pages (booklets)
+ --pdfselect select pages from file(s)
+ --pdfcopy copy pages from file(s)
+ --pdftrim trim pages from file(s)
+ --pdfcombine combine multiple pages
+ --pdfsplit split file in pages
+
+
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkii/texexec.man b/Master/texmf-dist/doc/context/scripts/mkii/texexec.man
new file mode 100644
index 00000000000..54213a30776
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkii/texexec.man
@@ -0,0 +1,72 @@
+.TH "texexec" "1" "01-01-2013" "version 6.2.1" "TeXExec"
+.SH NAME
+.B texexec
+.SH SYNOPSIS
+.B texexec [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B TeXExec
+.SH OPTIONS
+.TP
+.B --make
+make formats
+.TP
+.B --check
+check versions
+.TP
+.B --process
+process file
+.TP
+.B --mptex
+process mp file
+.TP
+.B --mpxtex
+process mpx file
+.TP
+.B --mpgraphic
+process mp file to stand-alone graphics
+.TP
+.B --mpstatic
+process mp/ctx file to stand-alone graphics
+.TP
+.B --listing
+list of file content
+.TP
+.B --figures
+generate overview of figures
+.TP
+.B --modules
+generate module documentation
+.TP
+.B --pdfarrange
+impose pages (booklets)
+.TP
+.B --pdfselect
+select pages from file(s)
+.TP
+.B --pdfcopy
+copy pages from file(s)
+.TP
+.B --pdftrim
+trim pages from file(s)
+.TP
+.B --pdfcombine
+combine multiple pages
+.TP
+.B --pdfsplit
+split file in pages
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/context/scripts/mkii/texexec.xml b/Master/texmf-dist/doc/context/scripts/mkii/texexec.xml
new file mode 100644
index 00000000000..8f85a4f2502
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkii/texexec.xml
@@ -0,0 +1,30 @@
+
+
+
+ texexec
+ TeXExec
+ 6.2.1
+
+
+
+
+ make formats
+ check versions
+ process file
+ process mp file
+ process mpx file
+ process mp file to stand-alone graphics
+ process mp/ctx file to stand-alone graphics
+ list of file content
+ generate overview of figures
+ generate module documentation
+ impose pages (booklets)
+ select pages from file(s)
+ copy pages from file(s)
+ trim pages from file(s)
+ combine multiple pages
+ split file in pages
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkii/texmfstart.html b/Master/texmf-dist/doc/context/scripts/mkii/texmfstart.html
new file mode 100644
index 00000000000..534e95671de
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkii/texmfstart.html
@@ -0,0 +1,94 @@
+
+
+
+
+
+
+
+
+
+
+ texmfstart 7.0.0
+
+
+
+
+
+
+
+
wiki: http://contextgarden.net | mail: ntg-context@ntg.nl | website: http://www.pragma-ade.nl
+
+
+
+
+
+
+
Command line options
+
+ flag value description
+
+ --script run an mtx script (lua prefered method) (--noquotes), no script gives list
+ --execute run a script or program (texmfstart method) (--noquotes)
+ --resolve resolve prefixed arguments
+ --ctxlua run internally (using preloaded libs)
+ --internal run script using built in libraries (same as --ctxlua)
+ --locate locate given filename in database (default) or system (--first --all --detail)
+
+ --autotree use texmf tree cf. env texmfstart_tree or texmfstarttree
+ --tree pathtotree use given texmf tree (default file: setuptex.tmf)
+ --environment name use given (tmf) environment file
+ --path runpath go to given path before execution
+ --ifchanged filename only execute when given file has changed (md checksum)
+ --iftouched old,new only execute when given file has changed (time stamp)
+
+ --makestubs create stubs for (context related) scripts
+ --removestubs remove stubs (context related) scripts
+ --stubpath binpath paths where stubs wil be written
+ --windows create windows (mswin) stubs
+ --unix create unix (linux) stubs
+
+ --verbose give a bit more info
+ --trackers list enable given trackers
+ --progname str format or backend
+
+ --edit launch editor with found file
+ --launch launch files like manuals, assumes os support (--all)
+
+ --timedrun run a script and time its run
+ --autogenerate regenerate databases if needed (handy when used to run context in an editor)
+
+ --usekpse use kpse as fallback (when no mkiv and cache installed, often slower)
+ --forcekpse force using kpse (handy when no mkiv and cache installed but less functionality)
+
+ --prefixes show supported prefixes
+
+ --generate generate file database
+
+ --variables show configuration variables
+ --configurations show configuration order
+
+ --directives show (known) directives
+ --trackers show (known) trackers
+ --experiments show (known) experiments
+
+ --expand-braces expand complex variable
+ --expand-path expand variable (resolve paths)
+ --expand-var expand variable (resolve references)
+ --show-path show path expansion of ...
+ --var-value report value of variable
+ --find-file report file location
+ --find-path report path of file
+
+ --pattern string filter variables
+
+
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkii/texmfstart.man b/Master/texmf-dist/doc/context/scripts/mkii/texmfstart.man
new file mode 100644
index 00000000000..212097ff153
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkii/texmfstart.man
@@ -0,0 +1,147 @@
+.TH "mtxrun" "1" "01-01-2013" "version 1.31" "ConTeXt TDS Runner Tool"
+.SH NAME
+.B mtxrun
+.SH SYNOPSIS
+.B mtxrun [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B ConTeXt TDS Runner Tool
+.SH OPTIONS
+.TP
+.B --script
+run an mtx script (lua prefered method) (--noquotes), no script gives list
+.TP
+.B --execute
+run a script or program (texmfstart method) (--noquotes)
+.TP
+.B --resolve
+resolve prefixed arguments
+.TP
+.B --ctxlua
+run internally (using preloaded libs)
+.TP
+.B --internal
+run script using built in libraries (same as --ctxlua)
+.TP
+.B --locate
+locate given filename in database (default) or system (--first --all --detail)
+.TP
+.B --autotree
+use texmf tree cf. env texmfstart_tree or texmfstarttree
+.TP
+.B --tree=pathtotree
+use given texmf tree (default file: setuptex.tmf)
+.TP
+.B --environment=name
+use given (tmf) environment file
+.TP
+.B --path=runpath
+go to given path before execution
+.TP
+.B --ifchanged=filename
+only execute when given file has changed (md checksum)
+.TP
+.B --iftouched=old,new
+only execute when given file has changed (time stamp)
+.TP
+.B --makestubs
+create stubs for (context related) scripts
+.TP
+.B --removestubs
+remove stubs (context related) scripts
+.TP
+.B --stubpath=binpath
+paths where stubs wil be written
+.TP
+.B --windows
+create windows (mswin) stubs
+.TP
+.B --unix
+create unix (linux) stubs
+.TP
+.B --verbose
+give a bit more info
+.TP
+.B --trackers=list
+enable given trackers
+.TP
+.B --progname=str
+format or backend
+.TP
+.B --edit
+launch editor with found file
+.TP
+.B --launch
+launch files like manuals, assumes os support (--all)
+.TP
+.B --timedrun
+run a script and time its run
+.TP
+.B --autogenerate
+regenerate databases if needed (handy when used to run context in an editor)
+.TP
+.B --usekpse
+use kpse as fallback (when no mkiv and cache installed, often slower)
+.TP
+.B --forcekpse
+force using kpse (handy when no mkiv and cache installed but less functionality)
+.TP
+.B --prefixes
+show supported prefixes
+.TP
+.B --generate
+generate file database
+.TP
+.B --variables
+show configuration variables
+.TP
+.B --configurations
+show configuration order
+.TP
+.B --directives
+show (known) directives
+.TP
+.B --trackers
+show (known) trackers
+.TP
+.B --experiments
+show (known) experiments
+.TP
+.B --expand-braces
+expand complex variable
+.TP
+.B --expand-path
+expand variable (resolve paths)
+.TP
+.B --expand-var
+expand variable (resolve references)
+.TP
+.B --show-path
+show path expansion of ...
+.TP
+.B --var-value
+report value of variable
+.TP
+.B --find-file
+report file location
+.TP
+.B --find-path
+report path of file
+.TP
+.B --pattern=string
+filter variables
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/context/scripts/mkii/texmfstart.xml b/Master/texmf-dist/doc/context/scripts/mkii/texmfstart.xml
new file mode 100644
index 00000000000..249a9bb54ad
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkii/texmfstart.xml
@@ -0,0 +1,78 @@
+
+
+ mtxrun
+ ConTeXt TDS Runner Tool
+ 1.31
+
+
+
+
+ run an mtx script (lua prefered method) (), no script gives list
+ run a script or program (texmfstart method) ()
+ resolve prefixed arguments
+ run internally (using preloaded libs)
+ run script using built in libraries (same as )
+ locate given filename in database (default) or system ( )
+
+
+ use texmf tree cf. env texmfstart_tree or texmfstarttree
+ use given texmf tree (default file: setuptex.tmf)
+ use given (tmf) environment file
+ go to given path before execution
+ only execute when given file has changed (md checksum)
+ only execute when given file has changed (time stamp)
+
+
+ create stubs for (context related) scripts
+ remove stubs (context related) scripts
+ paths where stubs wil be written
+ create windows (mswin) stubs
+ create unix (linux) stubs
+
+
+ give a bit more info
+ enable given trackers
+ format or backend
+
+
+ launch editor with found file
+ launch files like manuals, assumes os support ()
+
+
+ run a script and time its run
+ regenerate databases if needed (handy when used to run context in an editor)
+
+
+ use kpse as fallback (when no mkiv and cache installed, often slower)
+ force using kpse (handy when no mkiv and cache installed but less functionality)
+
+
+ show supported prefixes
+
+
+ generate file database
+
+
+ show configuration variables
+ show configuration order
+
+
+ show (known) directives
+ show (known) trackers
+ show (known) experiments
+
+
+ expand complex variable
+ expand variable (resolve paths)
+ expand variable (resolve references)
+ show path expansion of ...
+ report value of variable
+ report file location
+ report path of file
+
+
+ filter variables
+
+
+
+
\ No newline at end of file
diff --git a/Master/texmf-dist/doc/context/scripts/mkii/textools.html b/Master/texmf-dist/doc/context/scripts/mkii/textools.html
new file mode 100644
index 00000000000..8874050fb8b
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkii/textools.html
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
+
+
+
+ TeXTools 1.3.1
+
+
+
+
+
+
+
+
wiki: http://contextgarden.net | mail: ntg-context@ntg.nl | website: http://www.pragma-ade.nl
+
+
+
+
+
+
+
Command line options
+
+ flag value description
+
+ --removemapnames [pattern] [--recurse]
+ --restoremapnames [pattern] [--recurse]
+ --hidemapnames [pattern] [--recurse]
+ --videmapnames [pattern] [--recurse]
+ --findfile filename [--recurse]
+ --unzipfiles [pattern] [--recurse]
+ --fixafmfiles [pattern] [--recurse]
+ --mactodos [pattern] [--recurse]
+ --fixtexmftrees [texmfroot] [--force]
+ --replacefile filename [--force]
+ --updatetree fromroot toroot [--force --nocheck --merge --delete]
+ --downcasefilenames [--recurse] [--force]
+ --stripformfeeds [--recurse] [--force]
+ --showfont filename
+ --encmake afmfile encodingname
+ --tpmmake tpm file (run in texmf root)
+
+
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkii/textools.man b/Master/texmf-dist/doc/context/scripts/mkii/textools.man
new file mode 100644
index 00000000000..f8aba4683ea
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkii/textools.man
@@ -0,0 +1,72 @@
+.TH "textools" "1" "01-01-2013" "version 1.3.1" "TeXTools"
+.SH NAME
+.B textools
+.SH SYNOPSIS
+.B textools [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B TeXTools
+.SH OPTIONS
+.TP
+.B --removemapnames
+[pattern] [--recurse]
+.TP
+.B --restoremapnames
+[pattern] [--recurse]
+.TP
+.B --hidemapnames
+[pattern] [--recurse]
+.TP
+.B --videmapnames
+[pattern] [--recurse]
+.TP
+.B --findfile
+filename [--recurse]
+.TP
+.B --unzipfiles
+[pattern] [--recurse]
+.TP
+.B --fixafmfiles
+[pattern] [--recurse]
+.TP
+.B --mactodos
+[pattern] [--recurse]
+.TP
+.B --fixtexmftrees
+[texmfroot] [--force]
+.TP
+.B --replacefile
+filename [--force]
+.TP
+.B --updatetree
+fromroot toroot [--force --nocheck --merge --delete]
+.TP
+.B --downcasefilenames
+[--recurse] [--force]
+.TP
+.B --stripformfeeds
+[--recurse] [--force]
+.TP
+.B --showfont
+filename
+.TP
+.B --encmake
+afmfile encodingname
+.TP
+.B --tpmmake
+tpm file (run in texmf root)
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/context/scripts/mkii/textools.xml b/Master/texmf-dist/doc/context/scripts/mkii/textools.xml
new file mode 100644
index 00000000000..963c4a3a4d9
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkii/textools.xml
@@ -0,0 +1,30 @@
+
+
+
+ textools
+ TeXTools
+ 1.3.1
+
+
+
+
+ [pattern] [
+ [pattern] [
+ [pattern] [
+ [pattern] [
+ filename [
+ [pattern] [
+ [pattern] [
+ [pattern] [
+ [texmfroot] [
+ filename [
+ fromroot toroot [
+ [ [
+ [ [
+ filename
+ afmfile encodingname
+ tpm file (run in texmf root)
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkii/texutil.html b/Master/texmf-dist/doc/context/scripts/mkii/texutil.html
new file mode 100644
index 00000000000..05880e2788a
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkii/texutil.html
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
+
+ TeXUtil 9.1.0
+
+
+
+
+
+
+
+
wiki: http://contextgarden.net | mail: ntg-context@ntg.nl | website: http://www.pragma-ade.nl
+
+
+
+
+
+
+
Command line options
+
+ flag value description
+
+ --references convert tui file into tuo file
+ --figures generate figure dimensions file
+ --logfile filter essential log messages
+ --purgefiles remove most temporary files
+ --purgeallfiles remove all temporary files
+ --documentation generate documentation file from source
+ --analyzefile analyze pdf file
+
+
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkii/texutil.man b/Master/texmf-dist/doc/context/scripts/mkii/texutil.man
new file mode 100644
index 00000000000..9268e7b19c7
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkii/texutil.man
@@ -0,0 +1,45 @@
+.TH "texutil" "1" "01-01-2013" "version 9.1.0" "TeXUtil"
+.SH NAME
+.B texutil
+.SH SYNOPSIS
+.B texutil [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B TeXUtil
+.SH OPTIONS
+.TP
+.B --references
+convert tui file into tuo file
+.TP
+.B --figures
+generate figure dimensions file
+.TP
+.B --logfile
+filter essential log messages
+.TP
+.B --purgefiles
+remove most temporary files
+.TP
+.B --purgeallfiles
+remove all temporary files
+.TP
+.B --documentation
+generate documentation file from source
+.TP
+.B --analyzefile
+analyze pdf file
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/context/scripts/mkii/texutil.xml b/Master/texmf-dist/doc/context/scripts/mkii/texutil.xml
new file mode 100644
index 00000000000..fde9abd586a
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkii/texutil.xml
@@ -0,0 +1,21 @@
+
+
+
+ texutil
+ TeXUtil
+ 9.1.0
+
+
+
+
+ convert tui file into tuo file
+ generate figure dimensions file
+ filter essential log messages
+ remove most temporary files
+ remove all temporary files
+ generate documentation file from source
+ analyze pdf file
+
+
+
+
\ No newline at end of file
diff --git a/Master/texmf-dist/doc/context/scripts/mkii/tmftools.html b/Master/texmf-dist/doc/context/scripts/mkii/tmftools.html
new file mode 100644
index 00000000000..d3db5fd16b7
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkii/tmftools.html
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+ TMFTools 1.2.1
+
+
+
+
+
+
+
+
wiki: http://contextgarden.net | mail: ntg-context@ntg.nl | website: http://www.pragma-ade.nl
+
+
+
+
+
+
+
Command line options
+
+ flag value description
+
+ --analyze [--strict --sort --rootpath --treepath --delete --force] [pattern]
+
+ --serve act as kpse server
+
+
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkii/tmftools.man b/Master/texmf-dist/doc/context/scripts/mkii/tmftools.man
new file mode 100644
index 00000000000..9a88f4c4d4a
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkii/tmftools.man
@@ -0,0 +1,30 @@
+.TH "tmftools" "1" "01-01-2013" "version 1.1.0" "TMFTools"
+.SH NAME
+.B tmftools
+.SH SYNOPSIS
+.B tmftools [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B TMFTools
+.SH OPTIONS
+.TP
+.B --analyze
+[--strict --sort --rootpath --treepath --delete --force] [pattern]
+.TP
+.B --serve
+act as kpse server
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/context/scripts/mkii/tmftools.xml b/Master/texmf-dist/doc/context/scripts/mkii/tmftools.xml
new file mode 100644
index 00000000000..c52aa30673d
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkii/tmftools.xml
@@ -0,0 +1,18 @@
+
+
+
+ tmftools
+ TMFTools
+ 1.1.0
+
+
+
+
+ [ ] [pattern]
+
+
+ act as kpse server
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkii/xmltools.html b/Master/texmf-dist/doc/context/scripts/mkii/xmltools.html
new file mode 100644
index 00000000000..7712336097f
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkii/xmltools.html
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
+
+ XMLTools 1.2.1
+
+
+
+
+
+
+
+
wiki: http://contextgarden.net | mail: ntg-context@ntg.nl | website: http://www.pragma-ade.nl
+
+
+
+
+
+
+
Command line options
+
+ flag value description
+
+ --dir generate directory listing
+ --mmlpages generate graphic from mathml
+ --analyze report entities and elements [--utf --process]
+ --cleanup cleanup xml file [--force]
+ --enhance enhance xml file (partial)
+ --filter filter elements from xml file [--element]
+ --dir generate ddirectory listing
+
+
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkii/xmltools.man b/Master/texmf-dist/doc/context/scripts/mkii/xmltools.man
new file mode 100644
index 00000000000..3d2ca856ff3
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkii/xmltools.man
@@ -0,0 +1,45 @@
+.TH "xmltools" "1" "01-01-2013" "version 1.2.2" "XMLTools"
+.SH NAME
+.B xmltools
+.SH SYNOPSIS
+.B xmltools [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B XMLTools
+.SH OPTIONS
+.TP
+.B --dir
+generate directory listing
+.TP
+.B --mmlpages
+generate graphic from mathml
+.TP
+.B --analyze
+report entities and elements [--utf --process]
+.TP
+.B --cleanup
+cleanup xml file [--force]
+.TP
+.B --enhance
+enhance xml file (partial)
+.TP
+.B --filter
+filter elements from xml file [--element]
+.TP
+.B --dir
+generate ddirectory listing
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/context/scripts/mkii/xmltools.xml b/Master/texmf-dist/doc/context/scripts/mkii/xmltools.xml
new file mode 100644
index 00000000000..4b784c4e721
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkii/xmltools.xml
@@ -0,0 +1,21 @@
+
+
+
+ xmltools
+ XMLTools
+ 1.2.2
+
+
+
+
+ generate directory listing
+ generate graphic from mathml
+ report entities and elements [ ]
+ cleanup xml file []
+ enhance xml file (partial)
+ filter elements from xml file []
+ generate ddirectory listing
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/context.html b/Master/texmf-dist/doc/context/scripts/mkiv/context.html
new file mode 100644
index 00000000000..40e479d300f
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/context.html
@@ -0,0 +1,104 @@
+
+
+
+
+
+
+
+
+
+
+ ConTeXt Process Management 0.60
+
+
+
+
+
+
+
ConTeXt Process Management 0.60
+
+
+
+
wiki: http://contextgarden.net | mail: ntg-context@ntg.nl | website: http://www.pragma-ade.nl
+
+
+
+
+
+
+
Command line options
+
+ flag value description
+ basic
+
+ --run process (one or more) files (default action)
+ --make create context formats
+
+ --ctx=name use ctx file (process management specification)
+ --interface use specified user interface (default: en)
+
+ --autopdf close pdf file in viewer and start pdf viewer afterwards
+ --purge purge files either or not after a run (--pattern=...)
+ --purgeall purge all files either or not after a run (--pattern=...)
+
+ --usemodule list load the given module or style, normally part of the distribution
+ --environment list load the given environment file first (document styles)
+ --mode list enable given the modes (conditional processing in styles)
+ --path list also consult the given paths when files are looked for
+ --arguments list set variables that can be consulted during a run (key/value pairs)
+ --randomseed number set the randomseed
+ --result name rename the resulting output to the given name
+ --trackers list set tracker variables (show list with --showtrackers)
+ --directives list set directive variables (show list with --showdirectives)
+ --silent list disable logcatgories (show list with --showlogcategories)
+ --noconsole disable logging to the console (logfile only)
+ --purgeresult purge result file before run
+
+ --forcexml force xml stub
+ --forcecld force cld (context lua document) stub
+ --forcelua force lua stub (like texlua)
+ --forcemp force mp stub
+
+ --arrange run extra imposition pass, given that the style sets up imposition
+ --noarrange ignore imposition specifications in the style
+
+ --jit use luajittex with jit turned off (only use the faster virtual machine)
+ --jiton use luajittex with jit turned on (in most cases not faster, even slower)
+
+ --once only run once (no multipass data file is produced)
+ --batchmode run without stopping and do not show messages on the console
+ --nonstopmode run without stopping
+ --synctex run with synctex enabled (optional value: zipped, unzipped, 1, -1)
+
+ --generate generate file database etc. (as luatools does)
+ --paranoid do not descend to .. and ../..
+ --version report installed context version
+
+ --global assume given file present elsewhere
+ --nofile use dummy file as jobname
+ expert
+
+ --touch update context version number (remake needed afterwards, also provide --expert)
+ --nostatistics omit runtime statistics at the end of the run
+ --update update context from website (not to be confused with contextgarden)
+ --profile profile job (use: mtxrun --script profile --analyze)
+ --timing generate timing and statistics overview
+
+ --extra=name process extra (mtx-context-... in distribution)
+ --extras show extras
+ special
+
+ --pdftex process file with texexec using pdftex
+ --xetex process file with texexec using xetex
+ --mkii process file with texexec
+
+ --pipe do not check for file and enter scroll mode (--dummyfile=whatever.tmp)
+
+
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/context.man b/Master/texmf-dist/doc/context/scripts/mkiv/context.man
new file mode 100644
index 00000000000..e1fb28a994e
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/context.man
@@ -0,0 +1,167 @@
+.TH "mtx-context" "1" "01-01-2013" "version 0.60" "ConTeXt Process Management"
+.SH NAME
+.B mtx-context
+.SH SYNOPSIS
+.B mtxrun --script context [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B ConTeXt Process Management
+.SH OPTIONS: BASIC
+.TP
+.B --run
+process (one or more) files (default action)
+.TP
+.B --make
+create context formats
+.TP
+.B --ctx=name
+use ctx file (process management specification)
+.TP
+.B --interface
+use specified user interface (default: en)
+.TP
+.B --autopdf
+close pdf file in viewer and start pdf viewer afterwards
+.TP
+.B --purge
+purge files either or not after a run (--pattern=...)
+.TP
+.B --purgeall
+purge all files either or not after a run (--pattern=...)
+.TP
+.B --usemodule=list
+load the given module or style, normally part of the distribution
+.TP
+.B --environment=list
+load the given environment file first (document styles)
+.TP
+.B --mode=list
+enable given the modes (conditional processing in styles)
+.TP
+.B --path=list
+also consult the given paths when files are looked for
+.TP
+.B --arguments=list
+set variables that can be consulted during a run (key/value pairs)
+.TP
+.B --randomseed=number
+set the randomseed
+.TP
+.B --result=name
+rename the resulting output to the given name
+.TP
+.B --trackers=list
+set tracker variables (show list with --showtrackers)
+.TP
+.B --directives=list
+set directive variables (show list with --showdirectives)
+.TP
+.B --silent=list
+disable logcatgories (show list with --showlogcategories)
+.TP
+.B --noconsole
+disable logging to the console (logfile only)
+.TP
+.B --purgeresult
+purge result file before run
+.TP
+.B --forcexml
+force xml stub
+.TP
+.B --forcecld
+force cld (context lua document) stub
+.TP
+.B --forcelua
+force lua stub (like texlua)
+.TP
+.B --forcemp
+force mp stub
+.TP
+.B --arrange
+run extra imposition pass, given that the style sets up imposition
+.TP
+.B --noarrange
+ignore imposition specifications in the style
+.TP
+.B --jit
+use luajittex with jit turned off (only use the faster virtual machine)
+.TP
+.B --jiton
+use luajittex with jit turned on (in most cases not faster, even slower)
+.TP
+.B --once
+only run once (no multipass data file is produced)
+.TP
+.B --batchmode
+run without stopping and do not show messages on the console
+.TP
+.B --nonstopmode
+run without stopping
+.TP
+.B --synctex
+run with synctex enabled (optional value: zipped, unzipped, 1, -1)
+.TP
+.B --generate
+generate file database etc. (as luatools does)
+.TP
+.B --paranoid
+do not descend to .. and ../..
+.TP
+.B --version
+report installed context version
+.TP
+.B --global
+assume given file present elsewhere
+.TP
+.B --nofile
+use dummy file as jobname
+.SH OPTIONS: EXPERT
+.TP
+.B --touch
+update context version number (remake needed afterwards, also provide --expert)
+.TP
+.B --nostatistics
+omit runtime statistics at the end of the run
+.TP
+.B --update
+update context from website (not to be confused with contextgarden)
+.TP
+.B --profile
+profile job (use: mtxrun --script profile --analyze)
+.TP
+.B --timing
+generate timing and statistics overview
+.TP
+.B --extra=name
+process extra (mtx-context-... in distribution)
+.TP
+.B --extras
+show extras
+.SH OPTIONS: SPECIAL
+.TP
+.B --pdftex
+process file with texexec using pdftex
+.TP
+.B --xetex
+process file with texexec using xetex
+.TP
+.B --mkii
+process file with texexec
+.TP
+.B --pipe
+do not check for file and enter scroll mode (--dummyfile=whatever.tmp)
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/context.xml b/Master/texmf-dist/doc/context/scripts/mkiv/context.xml
new file mode 100644
index 00000000000..6eb8afeb105
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/context.xml
@@ -0,0 +1,187 @@
+
+
+
+
+ mtx-context
+ ConTeXt Process Management
+ 0.60
+ external helpinfo file
+
+
+
+
+
+ process (one or more) files (default action)
+
+
+ create context formats
+
+
+
+
+ use ctx file (process management specification)
+
+
+ use specified user interface (default: en)
+
+
+
+
+ close pdf file in viewer and start pdf viewer afterwards
+
+
+ purge files either or not after a run (=...)
+
+
+ purge all files either or not after a run (=...)
+
+
+
+
+ load the given module or style, normally part of the distribution
+
+
+ load the given environment file first (document styles)
+
+
+ enable given the modes (conditional processing in styles)
+
+
+ also consult the given paths when files are looked for
+
+
+ set variables that can be consulted during a run (key/value pairs)
+
+
+ set the randomseed
+
+
+ rename the resulting output to the given name
+
+
+ set tracker variables (show list with )
+
+
+ set directive variables (show list with )
+
+
+ disable logcatgories (show list with )
+
+
+ disable logging to the console (logfile only)
+
+
+ purge result file before run
+
+
+
+
+ force xml stub
+
+
+ force cld (context lua document) stub
+
+
+ force lua stub (like texlua)
+
+
+ force mp stub
+
+
+
+
+ run extra imposition pass, given that the style sets up imposition
+
+
+ ignore imposition specifications in the style
+
+
+
+
+ use luajittex with jit turned off (only use the faster virtual machine)
+
+
+ use luajittex with jit turned on (in most cases not faster, even slower)
+
+
+
+
+ only run once (no multipass data file is produced)
+
+
+ run without stopping and do not show messages on the console
+
+
+ run without stopping
+
+
+ run with synctex enabled (optional value: zipped, unzipped, 1, -1)
+
+
+
+
+ generate file database etc. (as luatools does)
+
+
+ do not descend to .. and ../..
+
+
+ report installed context version
+
+
+
+
+ assume given file present elsewhere
+
+
+ use dummy file as jobname
+
+
+
+
+
+
+ update context version number (remake needed afterwards, also provide )
+
+
+ omit runtime statistics at the end of the run
+
+
+ update context from website (not to be confused with contextgarden)
+
+
+ profile job (use: mtxrun profile )
+
+
+ generate timing and statistics overview
+
+
+
+
+ process extra (mtx-context-... in distribution)
+
+
+ show extras
+
+
+
+
+
+
+ process file with texexec using pdftex
+
+
+ process file with texexec using xetex
+
+
+ process file with texexec
+
+
+
+
+ do not check for file and enter scroll mode (=whatever.tmp)
+
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/luatools.html b/Master/texmf-dist/doc/context/scripts/mkiv/luatools.html
new file mode 100644
index 00000000000..6cb869a2bac
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/luatools.html
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+
+
+
+
+ luatools 1.35
+
+
+
+
+
+
+
+
wiki: http://contextgarden.net | mail: ntg-context@ntg.nl | website: http://www.pragma-ade.nl
+
+
+
+
+
+
+
Command line options
+
+ flag value description
+
+ --generate generate file database
+ --variables show configuration variables
+ --configurations show configuration order
+ --expand-braces expand complex variable
+ --expand-path expand variable (resolve paths)
+ --expand-var expand variable (resolve references)
+ --show-path show path expansion of ...
+ --var-value report value of variable
+ --find-file report file location
+ --find-path report path of file
+ --make [or --ini] make luatex format
+ --run [or --fmt] run luatex format
+ --compile assemble and compile lua inifile
+ --verbose give a bit more info
+ --all show all found files
+ --format str filter cf format specification (default 'tex', use 'any' for any match)
+ --pattern str filter variables
+ --trackers list enable given trackers
+
+
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/luatools.man b/Master/texmf-dist/doc/context/scripts/mkiv/luatools.man
new file mode 100644
index 00000000000..145e9f6083b
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/luatools.man
@@ -0,0 +1,78 @@
+.TH "luatools" "1" "01-01-2013" "version 1.35" "ConTeXt TDS Management Tool (aka luatools)"
+.SH NAME
+.B luatools
+.SH SYNOPSIS
+.B luatools [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B ConTeXt TDS Management Tool (aka luatools)
+.SH OPTIONS
+.TP
+.B --generate
+generate file database
+.TP
+.B --variables
+show configuration variables
+.TP
+.B --configurations
+show configuration order
+.TP
+.B --expand-braces
+expand complex variable
+.TP
+.B --expand-path
+expand variable (resolve paths)
+.TP
+.B --expand-var
+expand variable (resolve references)
+.TP
+.B --show-path
+show path expansion of ...
+.TP
+.B --var-value
+report value of variable
+.TP
+.B --find-file
+report file location
+.TP
+.B --find-path
+report path of file
+.TP
+.B --make
+[or --ini] make luatex format
+.TP
+.B --run
+[or --fmt] run luatex format
+.TP
+.B --compile
+assemble and compile lua inifile
+.TP
+.B --verbose
+give a bit more info
+.TP
+.B --all
+show all found files
+.TP
+.B --format=str
+filter cf format specification (default 'tex', use 'any' for any match)
+.TP
+.B --pattern=str
+filter variables
+.TP
+.B --trackers=list
+enable given trackers
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/luatools.xml b/Master/texmf-dist/doc/context/scripts/mkiv/luatools.xml
new file mode 100644
index 00000000000..34460fffec4
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/luatools.xml
@@ -0,0 +1,31 @@
+
+
+ luatools
+ ConTeXt TDS Management Tool (aka luatools)
+ 1.35
+
+
+
+
+ generate file database
+ show configuration variables
+ show configuration order
+ expand complex variable
+ expand variable (resolve paths)
+ expand variable (resolve references)
+ show path expansion of ...
+ report value of variable
+ report file location
+ report path of file
+ [or ] make luatex format
+ [or ] run luatex format
+ assemble and compile lua inifile
+ give a bit more info
+ show all found files
+ filter cf format specification (default 'tex', use 'any' for any match)
+ filter variables
+ enable given trackers
+
+
+
+
\ No newline at end of file
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-babel.html b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-babel.html
new file mode 100644
index 00000000000..21de59c086f
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-babel.html
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+ Babel Input To UTF Conversion 1.20
+
+
+
+
+
+
+
Babel Input To UTF Conversion 1.20
+
+
+
+
wiki: http://contextgarden.net | mail: ntg-context@ntg.nl | website: http://www.pragma-ade.nl
+
+
+
+
+
+
+
Command line options
+
+ flag value description
+
+ --language string conversion language (e.g. greek)
+ --structure string obey given structure (e.g. 'document', default: 'context')
+ --convert convert babel codes into utf
+
+
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-babel.man b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-babel.man
new file mode 100644
index 00000000000..cd0b007fb3d
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-babel.man
@@ -0,0 +1,33 @@
+.TH "mtx-babel" "1" "01-01-2013" "version 1.20" "Babel Input To UTF Conversion"
+.SH NAME
+.B mtx-babel
+.SH SYNOPSIS
+.B mtxrun --script babel [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B Babel Input To UTF Conversion
+.SH OPTIONS
+.TP
+.B --language=string
+conversion language (e.g. greek)
+.TP
+.B --structure=string
+obey given structure (e.g. 'document', default: 'context')
+.TP
+.B --convert
+convert babel codes into utf
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-babel.xml b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-babel.xml
new file mode 100644
index 00000000000..6a6efde1591
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-babel.xml
@@ -0,0 +1,17 @@
+
+
+
+ mtx-babel
+ Babel Input To UTF Conversion
+ 1.20
+
+
+
+
+ conversion language (e.g. greek)
+ obey given structure (e.g. 'document', default: 'context')
+ convert babel codes into utf
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-base.html b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-base.html
new file mode 100644
index 00000000000..2d97a2811db
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-base.html
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+
+
+
+
+ ConTeXt TDS Management Tool (aka luatools) 1.35
+
+
+
+
+
+
+
ConTeXt TDS Management Tool (aka luatools) 1.35
+
+
+
+
wiki: http://contextgarden.net | mail: ntg-context@ntg.nl | website: http://www.pragma-ade.nl
+
+
+
+
+
+
+
Command line options
+
+ flag value description
+
+ --generate generate file database
+ --variables show configuration variables
+ --configurations show configuration order
+ --expand-braces expand complex variable
+ --expand-path expand variable (resolve paths)
+ --expand-var expand variable (resolve references)
+ --show-path show path expansion of ...
+ --var-value report value of variable
+ --find-file report file location
+ --find-path report path of file
+ --make [or --ini] make luatex format
+ --run [or --fmt] run luatex format
+ --compile assemble and compile lua inifile
+ --verbose give a bit more info
+ --all show all found files
+ --format str filter cf format specification (default 'tex', use 'any' for any match)
+ --pattern str filter variables
+ --trackers list enable given trackers
+
+
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-base.man b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-base.man
new file mode 100644
index 00000000000..6c72dcb07f1
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-base.man
@@ -0,0 +1,78 @@
+.TH "mtx-base" "1" "01-01-2013" "version 1.35" "ConTeXt TDS Management Tool (aka luatools)"
+.SH NAME
+.B mtx-base
+.SH SYNOPSIS
+.B mtxrun --script base [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B ConTeXt TDS Management Tool (aka luatools)
+.SH OPTIONS
+.TP
+.B --generate
+generate file database
+.TP
+.B --variables
+show configuration variables
+.TP
+.B --configurations
+show configuration order
+.TP
+.B --expand-braces
+expand complex variable
+.TP
+.B --expand-path
+expand variable (resolve paths)
+.TP
+.B --expand-var
+expand variable (resolve references)
+.TP
+.B --show-path
+show path expansion of ...
+.TP
+.B --var-value
+report value of variable
+.TP
+.B --find-file
+report file location
+.TP
+.B --find-path
+report path of file
+.TP
+.B --make
+[or --ini] make luatex format
+.TP
+.B --run
+[or --fmt] run luatex format
+.TP
+.B --compile
+assemble and compile lua inifile
+.TP
+.B --verbose
+give a bit more info
+.TP
+.B --all
+show all found files
+.TP
+.B --format=str
+filter cf format specification (default 'tex', use 'any' for any match)
+.TP
+.B --pattern=str
+filter variables
+.TP
+.B --trackers=list
+enable given trackers
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-base.xml b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-base.xml
new file mode 100644
index 00000000000..de15b018815
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-base.xml
@@ -0,0 +1,32 @@
+
+
+
+ mtx-base
+ ConTeXt TDS Management Tool (aka luatools)
+ 1.35
+
+
+
+
+ generate file database
+ show configuration variables
+ show configuration order
+ expand complex variable
+ expand variable (resolve paths)
+ expand variable (resolve references)
+ show path expansion of ...
+ report value of variable
+ report file location
+ report path of file
+ [or ] make luatex format
+ [or ] run luatex format
+ assemble and compile lua inifile
+ give a bit more info
+ show all found files
+ filter cf format specification (default 'tex', use 'any' for any match)
+ filter variables
+ enable given trackers
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-cache.html b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-cache.html
new file mode 100644
index 00000000000..a344d2394a9
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-cache.html
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+ ConTeXt & MetaTeX Cache Management 0.10
+
+
+
+
+
+
+
ConTeXt & MetaTeX Cache Management 0.10
+
+
+
+
wiki: http://contextgarden.net | mail: ntg-context@ntg.nl | website: http://www.pragma-ade.nl
+
+
+
+
+
+
+
Command line options
+
+ flag value description
+
+ --purge remove not used files
+ --erase completely remove cache
+ --list show cache
+
+ --all all (not yet implemented)
+
+
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-cache.man b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-cache.man
new file mode 100644
index 00000000000..26f3793fc2b
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-cache.man
@@ -0,0 +1,36 @@
+.TH "mtx-cache" "1" "01-01-2013" "version 0.10" "ConTeXt &error; MetaTeX Cache Management"
+.SH NAME
+.B mtx-cache
+.SH SYNOPSIS
+.B mtxrun --script cache [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B ConTeXt &error; MetaTeX Cache Management
+.SH OPTIONS
+.TP
+.B --purge
+remove not used files
+.TP
+.B --erase
+completely remove cache
+.TP
+.B --list
+show cache
+.TP
+.B --all
+all (not yet implemented)
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-cache.xml b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-cache.xml
new file mode 100644
index 00000000000..2e37f036c3e
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-cache.xml
@@ -0,0 +1,20 @@
+
+
+
+ mtx-cache
+ ConTeXt & MetaTeX Cache Management
+ 0.10
+
+
+
+
+ remove not used files
+ completely remove cache
+ show cache
+
+
+ all (not yet implemented)
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-chars.html b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-chars.html
new file mode 100644
index 00000000000..64bb3703886
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-chars.html
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+ MkII Character Table Generators 0.10
+
+
+
+
+
+
+
MkII Character Table Generators 0.10
+
+
+
+
wiki: http://contextgarden.net | mail: ntg-context@ntg.nl | website: http://www.pragma-ade.nl
+
+
+
+
+
+
+
Command line options
+
+ flag value description
+
+ --xtx generate xetx-*.tex (used by xetex)
+ --pdf generate pdfr-def.tex (used by pdftex)
+ --entities generate entities table
+
+
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-chars.man b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-chars.man
new file mode 100644
index 00000000000..5d3df23e6a4
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-chars.man
@@ -0,0 +1,33 @@
+.TH "mtx-chars" "1" "01-01-2013" "version 0.10" "MkII Character Table Generators"
+.SH NAME
+.B mtx-chars
+.SH SYNOPSIS
+.B mtxrun --script chars [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B MkII Character Table Generators
+.SH OPTIONS
+.TP
+.B --xtx
+generate xetx-*.tex (used by xetex)
+.TP
+.B --pdf
+generate pdfr-def.tex (used by pdftex)
+.TP
+.B --entities
+generate entities table
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-chars.xml b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-chars.xml
new file mode 100644
index 00000000000..dd774923569
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-chars.xml
@@ -0,0 +1,17 @@
+
+
+
+ mtx-chars
+ MkII Character Table Generators
+ 0.10
+
+
+
+
+ generate xetx-*.tex (used by xetex)
+ generate pdfr-def.tex (used by pdftex)
+ generate entities table
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-check.html b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-check.html
new file mode 100644
index 00000000000..88cbc875948
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-check.html
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+ Basic ConTeXt Syntax Checking 0.10
+
+
+
+
+
+
+
Basic ConTeXt Syntax Checking 0.10
+
+
+
+
wiki: http://contextgarden.net | mail: ntg-context@ntg.nl | website: http://www.pragma-ade.nl
+
+
+
+
+
+
+
Command line options
+
+ flag value description
+
+ --convert check tex file for errors
+
+
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-check.man b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-check.man
new file mode 100644
index 00000000000..72e33b088eb
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-check.man
@@ -0,0 +1,27 @@
+.TH "mtx-check" "1" "01-01-2013" "version 0.10" "Basic ConTeXt Syntax Checking"
+.SH NAME
+.B mtx-check
+.SH SYNOPSIS
+.B mtxrun --script check [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B Basic ConTeXt Syntax Checking
+.SH OPTIONS
+.TP
+.B --convert
+check tex file for errors
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-check.xml b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-check.xml
new file mode 100644
index 00000000000..a8dcb82fdca
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-check.xml
@@ -0,0 +1,15 @@
+
+
+
+ mtx-check
+ Basic ConTeXt Syntax Checking
+ 0.10
+
+
+
+
+ check tex file for errors
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-colors.html b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-colors.html
new file mode 100644
index 00000000000..3628fb66aab
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-colors.html
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+ ConTeXt Color Management 0.10
+
+
+
+
+
+
+
ConTeXt Color Management 0.10
+
+
+
+
wiki: http://contextgarden.net | mail: ntg-context@ntg.nl | website: http://www.pragma-ade.nl
+
+
+
+
+
+
+
Command line options
+
+ flag value description
+
+ --table show icc table
+
+
+
Example
+
mtxrun --script color --table somename
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-colors.man b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-colors.man
new file mode 100644
index 00000000000..d466b5ea30c
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-colors.man
@@ -0,0 +1,27 @@
+.TH "mtx-colors" "1" "01-01-2013" "version 0.10" "ConTeXt Color Management"
+.SH NAME
+.B mtx-colors
+.SH SYNOPSIS
+.B mtxrun --script colors [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B ConTeXt Color Management
+.SH OPTIONS
+.TP
+.B --table
+show icc table
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-colors.xml b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-colors.xml
new file mode 100644
index 00000000000..ee6418b29d4
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-colors.xml
@@ -0,0 +1,23 @@
+
+
+
+ mtx-colors
+ ConTeXt Color Management
+ 0.10
+
+
+
+
+ show icc table
+
+
+
+
+
+ Example
+
+ mtxrun --script color --table somename
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-context.html b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-context.html
new file mode 100644
index 00000000000..40e479d300f
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-context.html
@@ -0,0 +1,104 @@
+
+
+
+
+
+
+
+
+
+
+ ConTeXt Process Management 0.60
+
+
+
+
+
+
+
ConTeXt Process Management 0.60
+
+
+
+
wiki: http://contextgarden.net | mail: ntg-context@ntg.nl | website: http://www.pragma-ade.nl
+
+
+
+
+
+
+
Command line options
+
+ flag value description
+ basic
+
+ --run process (one or more) files (default action)
+ --make create context formats
+
+ --ctx=name use ctx file (process management specification)
+ --interface use specified user interface (default: en)
+
+ --autopdf close pdf file in viewer and start pdf viewer afterwards
+ --purge purge files either or not after a run (--pattern=...)
+ --purgeall purge all files either or not after a run (--pattern=...)
+
+ --usemodule list load the given module or style, normally part of the distribution
+ --environment list load the given environment file first (document styles)
+ --mode list enable given the modes (conditional processing in styles)
+ --path list also consult the given paths when files are looked for
+ --arguments list set variables that can be consulted during a run (key/value pairs)
+ --randomseed number set the randomseed
+ --result name rename the resulting output to the given name
+ --trackers list set tracker variables (show list with --showtrackers)
+ --directives list set directive variables (show list with --showdirectives)
+ --silent list disable logcatgories (show list with --showlogcategories)
+ --noconsole disable logging to the console (logfile only)
+ --purgeresult purge result file before run
+
+ --forcexml force xml stub
+ --forcecld force cld (context lua document) stub
+ --forcelua force lua stub (like texlua)
+ --forcemp force mp stub
+
+ --arrange run extra imposition pass, given that the style sets up imposition
+ --noarrange ignore imposition specifications in the style
+
+ --jit use luajittex with jit turned off (only use the faster virtual machine)
+ --jiton use luajittex with jit turned on (in most cases not faster, even slower)
+
+ --once only run once (no multipass data file is produced)
+ --batchmode run without stopping and do not show messages on the console
+ --nonstopmode run without stopping
+ --synctex run with synctex enabled (optional value: zipped, unzipped, 1, -1)
+
+ --generate generate file database etc. (as luatools does)
+ --paranoid do not descend to .. and ../..
+ --version report installed context version
+
+ --global assume given file present elsewhere
+ --nofile use dummy file as jobname
+ expert
+
+ --touch update context version number (remake needed afterwards, also provide --expert)
+ --nostatistics omit runtime statistics at the end of the run
+ --update update context from website (not to be confused with contextgarden)
+ --profile profile job (use: mtxrun --script profile --analyze)
+ --timing generate timing and statistics overview
+
+ --extra=name process extra (mtx-context-... in distribution)
+ --extras show extras
+ special
+
+ --pdftex process file with texexec using pdftex
+ --xetex process file with texexec using xetex
+ --mkii process file with texexec
+
+ --pipe do not check for file and enter scroll mode (--dummyfile=whatever.tmp)
+
+
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-context.man b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-context.man
new file mode 100644
index 00000000000..e1fb28a994e
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-context.man
@@ -0,0 +1,167 @@
+.TH "mtx-context" "1" "01-01-2013" "version 0.60" "ConTeXt Process Management"
+.SH NAME
+.B mtx-context
+.SH SYNOPSIS
+.B mtxrun --script context [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B ConTeXt Process Management
+.SH OPTIONS: BASIC
+.TP
+.B --run
+process (one or more) files (default action)
+.TP
+.B --make
+create context formats
+.TP
+.B --ctx=name
+use ctx file (process management specification)
+.TP
+.B --interface
+use specified user interface (default: en)
+.TP
+.B --autopdf
+close pdf file in viewer and start pdf viewer afterwards
+.TP
+.B --purge
+purge files either or not after a run (--pattern=...)
+.TP
+.B --purgeall
+purge all files either or not after a run (--pattern=...)
+.TP
+.B --usemodule=list
+load the given module or style, normally part of the distribution
+.TP
+.B --environment=list
+load the given environment file first (document styles)
+.TP
+.B --mode=list
+enable given the modes (conditional processing in styles)
+.TP
+.B --path=list
+also consult the given paths when files are looked for
+.TP
+.B --arguments=list
+set variables that can be consulted during a run (key/value pairs)
+.TP
+.B --randomseed=number
+set the randomseed
+.TP
+.B --result=name
+rename the resulting output to the given name
+.TP
+.B --trackers=list
+set tracker variables (show list with --showtrackers)
+.TP
+.B --directives=list
+set directive variables (show list with --showdirectives)
+.TP
+.B --silent=list
+disable logcatgories (show list with --showlogcategories)
+.TP
+.B --noconsole
+disable logging to the console (logfile only)
+.TP
+.B --purgeresult
+purge result file before run
+.TP
+.B --forcexml
+force xml stub
+.TP
+.B --forcecld
+force cld (context lua document) stub
+.TP
+.B --forcelua
+force lua stub (like texlua)
+.TP
+.B --forcemp
+force mp stub
+.TP
+.B --arrange
+run extra imposition pass, given that the style sets up imposition
+.TP
+.B --noarrange
+ignore imposition specifications in the style
+.TP
+.B --jit
+use luajittex with jit turned off (only use the faster virtual machine)
+.TP
+.B --jiton
+use luajittex with jit turned on (in most cases not faster, even slower)
+.TP
+.B --once
+only run once (no multipass data file is produced)
+.TP
+.B --batchmode
+run without stopping and do not show messages on the console
+.TP
+.B --nonstopmode
+run without stopping
+.TP
+.B --synctex
+run with synctex enabled (optional value: zipped, unzipped, 1, -1)
+.TP
+.B --generate
+generate file database etc. (as luatools does)
+.TP
+.B --paranoid
+do not descend to .. and ../..
+.TP
+.B --version
+report installed context version
+.TP
+.B --global
+assume given file present elsewhere
+.TP
+.B --nofile
+use dummy file as jobname
+.SH OPTIONS: EXPERT
+.TP
+.B --touch
+update context version number (remake needed afterwards, also provide --expert)
+.TP
+.B --nostatistics
+omit runtime statistics at the end of the run
+.TP
+.B --update
+update context from website (not to be confused with contextgarden)
+.TP
+.B --profile
+profile job (use: mtxrun --script profile --analyze)
+.TP
+.B --timing
+generate timing and statistics overview
+.TP
+.B --extra=name
+process extra (mtx-context-... in distribution)
+.TP
+.B --extras
+show extras
+.SH OPTIONS: SPECIAL
+.TP
+.B --pdftex
+process file with texexec using pdftex
+.TP
+.B --xetex
+process file with texexec using xetex
+.TP
+.B --mkii
+process file with texexec
+.TP
+.B --pipe
+do not check for file and enter scroll mode (--dummyfile=whatever.tmp)
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-context.xml b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-context.xml
new file mode 100644
index 00000000000..6eb8afeb105
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-context.xml
@@ -0,0 +1,187 @@
+
+
+
+
+ mtx-context
+ ConTeXt Process Management
+ 0.60
+ external helpinfo file
+
+
+
+
+
+ process (one or more) files (default action)
+
+
+ create context formats
+
+
+
+
+ use ctx file (process management specification)
+
+
+ use specified user interface (default: en)
+
+
+
+
+ close pdf file in viewer and start pdf viewer afterwards
+
+
+ purge files either or not after a run (=...)
+
+
+ purge all files either or not after a run (=...)
+
+
+
+
+ load the given module or style, normally part of the distribution
+
+
+ load the given environment file first (document styles)
+
+
+ enable given the modes (conditional processing in styles)
+
+
+ also consult the given paths when files are looked for
+
+
+ set variables that can be consulted during a run (key/value pairs)
+
+
+ set the randomseed
+
+
+ rename the resulting output to the given name
+
+
+ set tracker variables (show list with )
+
+
+ set directive variables (show list with )
+
+
+ disable logcatgories (show list with )
+
+
+ disable logging to the console (logfile only)
+
+
+ purge result file before run
+
+
+
+
+ force xml stub
+
+
+ force cld (context lua document) stub
+
+
+ force lua stub (like texlua)
+
+
+ force mp stub
+
+
+
+
+ run extra imposition pass, given that the style sets up imposition
+
+
+ ignore imposition specifications in the style
+
+
+
+
+ use luajittex with jit turned off (only use the faster virtual machine)
+
+
+ use luajittex with jit turned on (in most cases not faster, even slower)
+
+
+
+
+ only run once (no multipass data file is produced)
+
+
+ run without stopping and do not show messages on the console
+
+
+ run without stopping
+
+
+ run with synctex enabled (optional value: zipped, unzipped, 1, -1)
+
+
+
+
+ generate file database etc. (as luatools does)
+
+
+ do not descend to .. and ../..
+
+
+ report installed context version
+
+
+
+
+ assume given file present elsewhere
+
+
+ use dummy file as jobname
+
+
+
+
+
+
+ update context version number (remake needed afterwards, also provide )
+
+
+ omit runtime statistics at the end of the run
+
+
+ update context from website (not to be confused with contextgarden)
+
+
+ profile job (use: mtxrun profile )
+
+
+ generate timing and statistics overview
+
+
+
+
+ process extra (mtx-context-... in distribution)
+
+
+ show extras
+
+
+
+
+
+
+ process file with texexec using pdftex
+
+
+ process file with texexec using xetex
+
+
+ process file with texexec
+
+
+
+
+ do not check for file and enter scroll mode (=whatever.tmp)
+
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-epub.html b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-epub.html
new file mode 100644
index 00000000000..6c8bb99d845
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-epub.html
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+ ConTeXt EPUB Helpers 0.12
+
+
+
+
+
+
+
ConTeXt EPUB Helpers 0.12
+
+
+
+
wiki: http://contextgarden.net | mail: ntg-context@ntg.nl | website: http://www.pragma-ade.nl
+
+
+
+
+
+
+
Command line options
+
+ flag value description
+
+ --make create epub zip file
+
+
+
Example
+
mtxrun --script epub --make mydocument
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-epub.man b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-epub.man
new file mode 100644
index 00000000000..518435d1e2b
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-epub.man
@@ -0,0 +1,27 @@
+.TH "mtx-epub" "1" "01-01-2013" "version 0.12" "ConTeXt EPUB Helpers"
+.SH NAME
+.B mtx-epub
+.SH SYNOPSIS
+.B mtxrun --script epub [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B ConTeXt EPUB Helpers
+.SH OPTIONS
+.TP
+.B --make
+create epub zip file
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-epub.xml b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-epub.xml
new file mode 100644
index 00000000000..5ef5dc81b39
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-epub.xml
@@ -0,0 +1,23 @@
+
+
+
+ mtx-epub
+ ConTeXt EPUB Helpers
+ 0.12
+
+
+
+
+ create epub zip file
+
+
+
+
+
+ Example
+
+ mtxrun --script epub --make mydocument
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-fcd.html b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-fcd.html
new file mode 100644
index 00000000000..0719d9c0b2c
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-fcd.html
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+
+ Fast Directory Change 1.00
+
+
+
+
+
+
+
Fast Directory Change 1.00
+
+
+
+
wiki: http://contextgarden.net | mail: ntg-context@ntg.nl | website: http://www.pragma-ade.nl
+
+
+
+
+
+
+
Command line options
+
+ flag value description
+
+ --clear clear the cache
+ --clear --history [entry] clear the history
+ --scan clear the cache and add given path(s)
+ --add add given path(s)
+ --find find given path (can be substring)
+ --find --nohistory find given path (can be substring) but don't use history
+ --stub print platform stub file
+ --list show roots of cached dirs
+ --list --history show history of chosen dirs
+ --help show this help
+
+
+
Example
+
fcd --scan t:\
+
fcd --add f:\project
+
fcd [--find] whatever
+
fcd --list
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-fcd.man b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-fcd.man
new file mode 100644
index 00000000000..43de2a3a4de
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-fcd.man
@@ -0,0 +1,54 @@
+.TH "mtx-fcd" "1" "01-01-2013" "version 1.00" "Fast Directory Change"
+.SH NAME
+.B mtx-fcd
+.SH SYNOPSIS
+.B mtxrun --script fcd [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B Fast Directory Change
+.SH OPTIONS
+.TP
+.B --clear
+clear the cache
+.TP
+.B --clear
+--history [entry] clear the history
+.TP
+.B --scan
+clear the cache and add given path(s)
+.TP
+.B --add
+add given path(s)
+.TP
+.B --find
+find given path (can be substring)
+.TP
+.B --find
+--nohistory find given path (can be substring) but don't use history
+.TP
+.B --stub
+print platform stub file
+.TP
+.B --list
+show roots of cached dirs
+.TP
+.B --list
+--history show history of chosen dirs
+.TP
+.B --help
+show this help
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-fcd.xml b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-fcd.xml
new file mode 100644
index 00000000000..f20975efdf3
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-fcd.xml
@@ -0,0 +1,35 @@
+
+
+
+ mtx-fcd
+ Fast Directory Change
+ 1.00
+
+
+
+
+ clear the cache
+ [entry] clear the history
+ clear the cache and add given path(s)
+ add given path(s)
+ find given path (can be substring)
+ find given path (can be substring) but don't use history
+ print platform stub file
+ show roots of cached dirs
+ show history of chosen dirs
+ show this help
+
+
+
+
+
+ Example
+
+ fcd --scan t:\
+ fcd --add f:\project
+ fcd [--find] whatever
+ fcd --list
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-flac.html b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-flac.html
new file mode 100644
index 00000000000..293b1cb95e8
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-flac.html
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+ ConTeXt Flac Helpers 0.10
+
+
+
+
+
+
+
ConTeXt Flac Helpers 0.10
+
+
+
+
wiki: http://contextgarden.net | mail: ntg-context@ntg.nl | website: http://www.pragma-ade.nl
+
+
+
+
+
+
+
Command line options
+
+ flag value description
+
+ --collect collect albums in xml file
+
+
+
Example
+
mtxrun --script flac --collect somename.flac
+
mtxrun --script flac --collect --pattern="m:/music/**")
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-flac.man b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-flac.man
new file mode 100644
index 00000000000..ef914f2acff
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-flac.man
@@ -0,0 +1,27 @@
+.TH "mtx-flac" "1" "01-01-2013" "version 0.10" "ConTeXt Flac Helpers"
+.SH NAME
+.B mtx-flac
+.SH SYNOPSIS
+.B mtxrun --script flac [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B ConTeXt Flac Helpers
+.SH OPTIONS
+.TP
+.B --collect
+collect albums in xml file
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-flac.xml b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-flac.xml
new file mode 100644
index 00000000000..bd5fc9bc9e7
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-flac.xml
@@ -0,0 +1,24 @@
+
+
+
+ mtx-flac
+ ConTeXt Flac Helpers
+ 0.10
+
+
+
+
+ collect albums in xml file
+
+
+
+
+
+ Example
+
+ mtxrun --script flac --collect somename.flac
+ mtxrun --script flac --collect --pattern="m:/music/**")
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-fonts.html b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-fonts.html
new file mode 100644
index 00000000000..5fdfc5feb74
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-fonts.html
@@ -0,0 +1,71 @@
+
+
+
+
+
+
+
+
+
+
+ ConTeXt Font Database Management 0.21
+
+
+
+
+
+
+
ConTeXt Font Database Management 0.21
+
+
+
+
wiki: http://contextgarden.net | mail: ntg-context@ntg.nl | website: http://www.pragma-ade.nl
+
+
+
+
+
+
+
Command line options
+
+ flag value description
+
+ --save save open type font in raw table
+ --unpack save a tma file in a more readale format
+
+ --reload generate new font database (use --force when in doubt)
+ --reload --simple:generate luatex-fonts-names.lua (not for context!)
+
+ --list --name: list installed fonts, filter by name [--pattern]
+ --list --spec: list installed fonts, filter by spec [--filter]
+ --list --file: list installed fonts, filter by file [--pattern]
+
+ --pattern str filter files using pattern
+ --filter list key-value pairs
+ --all show all found instances (combined with other flags)
+ --info give more details
+ --track list enable trackers
+ --statistics some info about the database
+
+
+
Examples
+
mtxrun --script font --list somename (== --pattern=*somename*)
+
mtxrun --script font --list --name somename
+
mtxrun --script font --list --name --pattern=*somename*
+
mtxrun --script font --list --spec somename
+
mtxrun --script font --list --spec somename-bold-italic
+
mtxrun --script font --list --spec --pattern=*somename*
+
mtxrun --script font --list --spec --filter="fontname=somename"
+
mtxrun --script font --list --spec --filter="familyname=somename,weight=bold,style=italic,width=condensed"
+
mtxrun --script font --list --spec --filter="familyname=crap*,weight=bold,style=italic"
+
mtxrun --script font --list --all
+
mtxrun --script font --list --file somename
+
mtxrun --script font --list --file --all somename
+
mtxrun --script font --list --file --pattern=*somename*
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-fonts.man b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-fonts.man
new file mode 100644
index 00000000000..b576b9de35d
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-fonts.man
@@ -0,0 +1,63 @@
+.TH "mtx-fonts" "1" "01-01-2013" "version 0.21" "ConTeXt Font Database Management"
+.SH NAME
+.B mtx-fonts
+.SH SYNOPSIS
+.B mtxrun --script fonts [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B ConTeXt Font Database Management
+.SH OPTIONS
+.TP
+.B --save
+save open type font in raw table
+.TP
+.B --unpack
+save a tma file in a more readale format
+.TP
+.B --reload
+generate new font database (use --force when in doubt)
+.TP
+.B --reload
+--simple:generate luatex-fonts-names.lua (not for context!)
+.TP
+.B --list
+--name: list installed fonts, filter by name [--pattern]
+.TP
+.B --list
+--spec: list installed fonts, filter by spec [--filter]
+.TP
+.B --list
+--file: list installed fonts, filter by file [--pattern]
+.TP
+.B --pattern=str
+filter files using pattern
+.TP
+.B --filter=list
+key-value pairs
+.TP
+.B --all
+show all found instances (combined with other flags)
+.TP
+.B --info
+give more details
+.TP
+.B --track=list
+enable trackers
+.TP
+.B --statistics
+some info about the database
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-fonts.xml b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-fonts.xml
new file mode 100644
index 00000000000..f38633e5100
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-fonts.xml
@@ -0,0 +1,59 @@
+
+
+
+ mtx-fonts
+ ConTeXt Font Database Management
+ 0.21
+
+
+
+
+ save open type font in raw table
+ save a tma file in a more readale format
+
+
+ generate new font database (use when in doubt)
+ :generate luatex-fonts-names.lua (not for context!)
+
+
+ : list installed fonts, filter by name []
+ : list installed fonts, filter by spec []
+ : list installed fonts, filter by file []
+
+
+ filter files using pattern
+ key-value pairs
+ show all found instances (combined with other flags)
+ give more details
+ enable trackers
+ some info about the database
+
+
+
+
+
+ Examples
+
+ mtxrun --script font --list somename (== --pattern=*somename*)
+
+
+ mtxrun --script font --list --name somename
+ mtxrun --script font --list --name --pattern=*somename*
+
+
+ mtxrun --script font --list --spec somename
+ mtxrun --script font --list --spec somename-bold-italic
+ mtxrun --script font --list --spec --pattern=*somename*
+ mtxrun --script font --list --spec --filter="fontname=somename"
+ mtxrun --script font --list --spec --filter="familyname=somename,weight=bold,style=italic,width=condensed"
+ mtxrun --script font --list --spec --filter="familyname=crap*,weight=bold,style=italic"
+
+
+ mtxrun --script font --list --all
+ mtxrun --script font --list --file somename
+ mtxrun --script font --list --file --all somename
+ mtxrun --script font --list --file --pattern=*somename*
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-grep.html b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-grep.html
new file mode 100644
index 00000000000..3df541ba847
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-grep.html
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+ Simple Grepper 0.10
+
+
+
+
+
+
+
+
wiki: http://contextgarden.net | mail: ntg-context@ntg.nl | website: http://www.pragma-ade.nl
+
+
+
+
+
+
+
Command line options
+
+ flag value description
+
+ --pattern search for pattern (optional)
+ --count count matches only
+ --nocomment skip lines that start with %% or #
+ --xml pattern is lpath expression
+
+
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-grep.man b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-grep.man
new file mode 100644
index 00000000000..6b86ec75591
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-grep.man
@@ -0,0 +1,36 @@
+.TH "mtx-grep" "1" "01-01-2013" "version 0.10" "Simple Grepper"
+.SH NAME
+.B mtx-grep
+.SH SYNOPSIS
+.B mtxrun --script grep [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B Simple Grepper
+.SH OPTIONS
+.TP
+.B --pattern
+search for pattern (optional)
+.TP
+.B --count
+count matches only
+.TP
+.B --nocomment
+skip lines that start with %% or #
+.TP
+.B --xml
+pattern is lpath expression
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-grep.xml b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-grep.xml
new file mode 100644
index 00000000000..d8567e03576
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-grep.xml
@@ -0,0 +1,21 @@
+
+
+
+ mtx-grep
+ Simple Grepper
+ 0.10
+
+
+
+
+ search for pattern (optional)
+ count matches only
+ skip lines that start with %% or #
+ pattern is lpath expression
+
+
+
+
+ patterns are lua patterns and need to be escaped accordingly
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-interface.html b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-interface.html
new file mode 100644
index 00000000000..25d26392538
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-interface.html
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+ ConTeXt Interface Related Goodies 0.13
+
+
+
+
+
+
+
ConTeXt Interface Related Goodies 0.13
+
+
+
+
wiki: http://contextgarden.net | mail: ntg-context@ntg.nl | website: http://www.pragma-ade.nl
+
+
+
+
+
+
+
Command line options
+
+ flag value description
+
+ --interfaces generate context interface files
+ --messages generate context message files
+ --labels generate context label files
+
+ --context equals --interfaces --messages --languages
+
+ --scite generate scite interface
+ --bbedit generate bbedit interface files
+ --jedit generate jedit interface files
+ --textpad generate textpad interface files
+ --text create text files for commands and environments
+ --raw report commands to the console
+ --check generate check file
+
+ --toutf replace named characters by utf
+ --preprocess preprocess mkvi files to tex files [force,suffix]
+
+ --suffix use given suffix for output files
+ --force force action even when in doubt
+
+
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-interface.man b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-interface.man
new file mode 100644
index 00000000000..232451621a6
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-interface.man
@@ -0,0 +1,69 @@
+.TH "mtx-interface" "1" "01-01-2013" "version 0.13" "ConTeXt Interface Related Goodies"
+.SH NAME
+.B mtx-interface
+.SH SYNOPSIS
+.B mtxrun --script interface [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B ConTeXt Interface Related Goodies
+.SH OPTIONS
+.TP
+.B --interfaces
+generate context interface files
+.TP
+.B --messages
+generate context message files
+.TP
+.B --labels
+generate context label files
+.TP
+.B --context
+equals --interfaces --messages --languages
+.TP
+.B --scite
+generate scite interface
+.TP
+.B --bbedit
+generate bbedit interface files
+.TP
+.B --jedit
+generate jedit interface files
+.TP
+.B --textpad
+generate textpad interface files
+.TP
+.B --text
+create text files for commands and environments
+.TP
+.B --raw
+report commands to the console
+.TP
+.B --check
+generate check file
+.TP
+.B --toutf
+replace named characters by utf
+.TP
+.B --preprocess
+preprocess mkvi files to tex files [force,suffix]
+.TP
+.B --suffix
+use given suffix for output files
+.TP
+.B --force
+force action even when in doubt
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-interface.xml b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-interface.xml
new file mode 100644
index 00000000000..6150215f6bb
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-interface.xml
@@ -0,0 +1,37 @@
+
+
+
+ mtx-interface
+ ConTeXt Interface Related Goodies
+ 0.13
+
+
+
+
+ generate context interface files
+ generate context message files
+ generate context label files
+
+
+ equals
+
+
+ generate scite interface
+ generate bbedit interface files
+ generate jedit interface files
+ generate textpad interface files
+ create text files for commands and environments
+ report commands to the console
+ generate check file
+
+
+ replace named characters by utf
+ preprocess mkvi files to tex files [force,suffix]
+
+
+ use given suffix for output files
+ force action even when in doubt
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-metapost.html b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-metapost.html
new file mode 100644
index 00000000000..d9be7074423
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-metapost.html
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+
+
+ MetaPost to PDF processor 0.10
+
+
+
+
+
+
+
MetaPost to PDF processor 0.10
+
+
+
+
wiki: http://contextgarden.net | mail: ntg-context@ntg.nl | website: http://www.pragma-ade.nl
+
+
+
+
+
+
+
Command line options
+
+ flag value description
+
+ --rawmp raw metapost run
+ --metafun use metafun instead of plain
+ --latex force --tex=latex
+ --texexec force texexec usage (mkii)
+ --split split single result file into pages
+
+
+
Examples
+
mtxrun --script metapost yourfile.mp
+
mtxrun --script metapost --split yourfile.mp
+
mtxrun --script metapost yourfile.123 myfile.mps
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-metapost.man b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-metapost.man
new file mode 100644
index 00000000000..9ccaddc9f2d
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-metapost.man
@@ -0,0 +1,39 @@
+.TH "mtx-metapost" "1" "01-01-2013" "version 0.10" "MetaPost to PDF processor"
+.SH NAME
+.B mtx-metapost
+.SH SYNOPSIS
+.B mtxrun --script metapost [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B MetaPost to PDF processor
+.SH OPTIONS
+.TP
+.B --rawmp
+raw metapost run
+.TP
+.B --metafun
+use metafun instead of plain
+.TP
+.B --latex
+force --tex=latex
+.TP
+.B --texexec
+force texexec usage (mkii)
+.TP
+.B --split
+split single result file into pages
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-metapost.xml b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-metapost.xml
new file mode 100644
index 00000000000..dbeb77a2a94
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-metapost.xml
@@ -0,0 +1,32 @@
+
+
+
+ mtx-metapost
+ MetaPost to PDF processor
+ 0.10
+
+
+
+
+ raw metapost run
+ use metafun instead of plain
+ force
+ force texexec usage (mkii)
+ split single result file into pages
+
+
+
+
+
+ Examples
+
+ mtxrun --script metapost yourfile.mp
+ mtxrun --script metapost --split yourfile.mp
+ mtxrun --script metapost yourfile.123 myfile.mps
+
+
+
+
+ other usage resembles mptopdf.pl
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-metatex.html b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-metatex.html
new file mode 100644
index 00000000000..ac6c33b98db
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-metatex.html
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+ MetaTeX Process Management 0.10
+
+
+
+
+
+
+
MetaTeX Process Management 0.10
+
+
+
+
wiki: http://contextgarden.net | mail: ntg-context@ntg.nl | website: http://www.pragma-ade.nl
+
+
+
+
+
+
+
Command line options
+
+ flag value description
+
+ --run process (one or more) files (default action)
+ --make create metatex format(s)
+
+
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-metatex.man b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-metatex.man
new file mode 100644
index 00000000000..bd67ff4d321
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-metatex.man
@@ -0,0 +1,30 @@
+.TH "mtx-metatex" "1" "01-01-2013" "version 0.10" "MetaTeX Process Management"
+.SH NAME
+.B mtx-metatex
+.SH SYNOPSIS
+.B mtxrun --script metatex [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B MetaTeX Process Management
+.SH OPTIONS
+.TP
+.B --run
+process (one or more) files (default action)
+.TP
+.B --make
+create metatex format(s)
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-metatex.xml b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-metatex.xml
new file mode 100644
index 00000000000..649673fbf90
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-metatex.xml
@@ -0,0 +1,16 @@
+
+
+
+ mtx-metatex
+ MetaTeX Process Management
+ 0.10
+
+
+
+
+ process (one or more) files (default action)
+ create metatex format(s)
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-modules.html b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-modules.html
new file mode 100644
index 00000000000..4edfbdb8278
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-modules.html
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+ ConTeXt Module Documentation Generators 1.00
+
+
+
+
+
+
+
ConTeXt Module Documentation Generators 1.00
+
+
+
+
wiki: http://contextgarden.net | mail: ntg-context@ntg.nl | website: http://www.pragma-ade.nl
+
+
+
+
+
+
+
Command line options
+
+ flag value description
+
+ --convert convert source files (tex, mkii, mkiv, mp) to 'ted' files
+ --process process source files (tex, mkii, mkiv, mp) to 'pdf' files
+ --prep use original name with suffix 'prep' appended
+
+
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-modules.man b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-modules.man
new file mode 100644
index 00000000000..a719c16a077
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-modules.man
@@ -0,0 +1,33 @@
+.TH "mtx-modules" "1" "01-01-2013" "version 1.00" "ConTeXt Module Documentation Generators"
+.SH NAME
+.B mtx-modules
+.SH SYNOPSIS
+.B mtxrun --script modules [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B ConTeXt Module Documentation Generators
+.SH OPTIONS
+.TP
+.B --convert
+convert source files (tex, mkii, mkiv, mp) to 'ted' files
+.TP
+.B --process
+process source files (tex, mkii, mkiv, mp) to 'pdf' files
+.TP
+.B --prep
+use original name with suffix 'prep' appended
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-modules.xml b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-modules.xml
new file mode 100644
index 00000000000..fe0311d1632
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-modules.xml
@@ -0,0 +1,17 @@
+
+
+
+ mtx-modules
+ ConTeXt Module Documentation Generators
+ 1.00
+
+
+
+
+ convert source files (tex, mkii, mkiv, mp) to 'ted' files
+ process source files (tex, mkii, mkiv, mp) to 'pdf' files
+ use original name with suffix 'prep' appended
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-package.html b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-package.html
new file mode 100644
index 00000000000..42e54a3ac9a
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-package.html
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+ Distribution Related Goodies 0.10
+
+
+
+
+
+
+
Distribution Related Goodies 0.10
+
+
+
+
wiki: http://contextgarden.net | mail: ntg-context@ntg.nl | website: http://www.pragma-ade.nl
+
+
+
+
+
+
+
Command line options
+
+ flag value description
+
+ --merge merge 'loadmodule' into merge file
+
+
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-package.man b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-package.man
new file mode 100644
index 00000000000..af11e6aec01
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-package.man
@@ -0,0 +1,27 @@
+.TH "mtx-package" "1" "01-01-2013" "version 0.10" "Distribution Related Goodies"
+.SH NAME
+.B mtx-package
+.SH SYNOPSIS
+.B mtxrun --script package [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B Distribution Related Goodies
+.SH OPTIONS
+.TP
+.B --merge
+merge 'loadmodule' into merge file
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-package.xml b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-package.xml
new file mode 100644
index 00000000000..0443704266a
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-package.xml
@@ -0,0 +1,15 @@
+
+
+
+ mtx-package
+ Distribution Related Goodies
+ 0.10
+
+
+
+
+ merge 'loadmodule' into merge file
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-patterns.html b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-patterns.html
new file mode 100644
index 00000000000..427bee3bd2a
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-patterns.html
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+
+ ConTeXt Pattern File Management 0.20
+
+
+
+
+
+
+
ConTeXt Pattern File Management 0.20
+
+
+
+
wiki: http://contextgarden.net | mail: ntg-context@ntg.nl | website: http://www.pragma-ade.nl
+
+
+
+
+
+
+
Command line options
+
+ flag value description
+
+ --convert generate context language files (mnemonic driven, if not given then all)
+ --check check pattern file (or those used by context when no file given)
+ --path source path where hyph-foo.tex files are stored
+ --destination destination path
+ --specification additional patterns: e.g.: =cy,hyph-cy,welsh
+
+
+
Examples
+
mtxrun --script pattern --check hyph-*.tex
+
mtxrun --script pattern --check --path=c:/data/develop/svn-hyphen/trunk/hyph-utf8/tex/generic/hyph-utf8/patterns
+
mtxrun --script pattern --convert --path=c:/data/develop/svn-hyphen/trunk/hyph-utf8/tex/generic/hyph-utf8/patterns/tex --destination=e:/tmp/patterns
+
mtxrun --script pattern --convert --path=c:/data/develop/svn-hyphen/trunk/hyph-utf8/tex/generic/hyph-utf8/patterns/txt --destination=e:/tmp/patterns
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-patterns.man b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-patterns.man
new file mode 100644
index 00000000000..96e3c4d4879
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-patterns.man
@@ -0,0 +1,39 @@
+.TH "mtx-patterns" "1" "01-01-2013" "version 0.20" "ConTeXt Pattern File Management"
+.SH NAME
+.B mtx-patterns
+.SH SYNOPSIS
+.B mtxrun --script patterns [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B ConTeXt Pattern File Management
+.SH OPTIONS
+.TP
+.B --convert
+generate context language files (mnemonic driven, if not given then all)
+.TP
+.B --check
+check pattern file (or those used by context when no file given)
+.TP
+.B --path
+source path where hyph-foo.tex files are stored
+.TP
+.B --destination
+destination path
+.TP
+.B --specification
+additional patterns: e.g.: =cy,hyph-cy,welsh
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-patterns.xml b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-patterns.xml
new file mode 100644
index 00000000000..f3255aebee2
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-patterns.xml
@@ -0,0 +1,30 @@
+
+
+
+ mtx-patterns
+ ConTeXt Pattern File Management
+ 0.20
+
+
+
+
+ generate context language files (mnemonic driven, if not given then all)
+ check pattern file (or those used by context when no file given)
+ source path where hyph-foo.tex files are stored
+ destination path
+ additional patterns: e.g.: =cy,hyph-cy,welsh
+
+
+
+
+
+ Examples
+
+ mtxrun --script pattern --check hyph-*.tex
+ mtxrun --script pattern --check --path=c:/data/develop/svn-hyphen/trunk/hyph-utf8/tex/generic/hyph-utf8/patterns
+ mtxrun --script pattern --convert --path=c:/data/develop/svn-hyphen/trunk/hyph-utf8/tex/generic/hyph-utf8/patterns/tex --destination=e:/tmp/patterns
+ mtxrun --script pattern --convert --path=c:/data/develop/svn-hyphen/trunk/hyph-utf8/tex/generic/hyph-utf8/patterns/txt --destination=e:/tmp/patterns
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-pdf.html b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-pdf.html
new file mode 100644
index 00000000000..be923581f7e
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-pdf.html
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+ ConTeXt PDF Helpers 0.10
+
+
+
+
+
+
+
ConTeXt PDF Helpers 0.10
+
+
+
+
wiki: http://contextgarden.net | mail: ntg-context@ntg.nl | website: http://www.pragma-ade.nl
+
+
+
+
+
+
+
Command line options
+
+ flag value description
+
+ --info show some info about the given file
+ --metadata show metadata xml blob
+ --fonts show used fonts (--detail)
+
+
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-pdf.man b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-pdf.man
new file mode 100644
index 00000000000..7ac50df0d63
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-pdf.man
@@ -0,0 +1,33 @@
+.TH "mtx-pdf" "1" "01-01-2013" "version 0.10" "ConTeXt PDF Helpers"
+.SH NAME
+.B mtx-pdf
+.SH SYNOPSIS
+.B mtxrun --script pdf [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B ConTeXt PDF Helpers
+.SH OPTIONS
+.TP
+.B --info
+show some info about the given file
+.TP
+.B --metadata
+show metadata xml blob
+.TP
+.B --fonts
+show used fonts (--detail)
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-pdf.xml b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-pdf.xml
new file mode 100644
index 00000000000..22e85988b52
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-pdf.xml
@@ -0,0 +1,17 @@
+
+
+
+ mtx-pdf
+ ConTeXt PDF Helpers
+ 0.10
+
+
+
+
+ show some info about the given file
+ show metadata xml blob
+ show used fonts (
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-profile.html b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-profile.html
new file mode 100644
index 00000000000..843349e4d70
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-profile.html
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+ ConTeXt MkIV LuaTeX Profiler 1.00
+
+
+
+
+
+
+
ConTeXt MkIV LuaTeX Profiler 1.00
+
+
+
+
wiki: http://contextgarden.net | mail: ntg-context@ntg.nl | website: http://www.pragma-ade.nl
+
+
+
+
+
+
+
Command line options
+
+ flag value description
+
+ --analyze analyze lua calls
+ --trace analyze tex calls
+
+
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-profile.man b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-profile.man
new file mode 100644
index 00000000000..5eba4861aa4
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-profile.man
@@ -0,0 +1,30 @@
+.TH "mtx-profile" "1" "01-01-2013" "version 1.00" "ConTeXt MkIV LuaTeX Profiler"
+.SH NAME
+.B mtx-profile
+.SH SYNOPSIS
+.B mtxrun --script profile [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B ConTeXt MkIV LuaTeX Profiler
+.SH OPTIONS
+.TP
+.B --analyze
+analyze lua calls
+.TP
+.B --trace
+analyze tex calls
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-profile.xml b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-profile.xml
new file mode 100644
index 00000000000..48252c2c8d0
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-profile.xml
@@ -0,0 +1,16 @@
+
+
+
+ mtx-profile
+ ConTeXt MkIV LuaTeX Profiler
+ 1.00
+
+
+
+
+ analyze lua calls
+ analyze tex calls
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-rsync.html b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-rsync.html
new file mode 100644
index 00000000000..0f805ff8367
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-rsync.html
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+ Rsync Helpers 0.10
+
+
+
+
+
+
+
+
wiki: http://contextgarden.net | mail: ntg-context@ntg.nl | website: http://www.pragma-ade.nl
+
+
+
+
+
+
+
Command line options
+
+ flag value description
+
+ --job use given file as specification
+ --dryrun show what would happen
+ --force force run
+
+
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-rsync.man b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-rsync.man
new file mode 100644
index 00000000000..5f3bc1fea00
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-rsync.man
@@ -0,0 +1,33 @@
+.TH "mtx-rsync" "1" "01-01-2013" "version 0.10" "Rsync Helpers"
+.SH NAME
+.B mtx-rsync
+.SH SYNOPSIS
+.B mtxrun --script rsync [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B Rsync Helpers
+.SH OPTIONS
+.TP
+.B --job
+use given file as specification
+.TP
+.B --dryrun
+show what would happen
+.TP
+.B --force
+force run
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-rsync.xml b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-rsync.xml
new file mode 100644
index 00000000000..28352cc368e
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-rsync.xml
@@ -0,0 +1,17 @@
+
+
+
+ mtx-rsync
+ Rsync Helpers
+ 0.10
+
+
+
+
+ use given file as specification
+ show what would happen
+ force run
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-scite.html b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-scite.html
new file mode 100644
index 00000000000..041fbaa5197
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-scite.html
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+ Scite Helper Script 1.00
+
+
+
+
+
+
+
Scite Helper Script 1.00
+
+
+
+
wiki: http://contextgarden.net | mail: ntg-context@ntg.nl | website: http://www.pragma-ade.nl
+
+
+
+
+
+
+
Command line options
+
+ flag value description
+
+ --words convert spell-*.txt into spell-*.lua
+
+
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-scite.man b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-scite.man
new file mode 100644
index 00000000000..118179e9184
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-scite.man
@@ -0,0 +1,27 @@
+.TH "mtx-scite" "1" "01-01-2013" "version 1.00" "Scite Helper Script"
+.SH NAME
+.B mtx-scite
+.SH SYNOPSIS
+.B mtxrun --script scite [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B Scite Helper Script
+.SH OPTIONS
+.TP
+.B --words
+convert spell-*.txt into spell-*.lua
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-scite.xml b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-scite.xml
new file mode 100644
index 00000000000..87fe506dc8f
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-scite.xml
@@ -0,0 +1,15 @@
+
+
+
+ mtx-scite
+ Scite Helper Script
+ 1.00
+
+
+
+
+ convert spell-*.txt into spell-*.lua
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-server.html b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-server.html
new file mode 100644
index 00000000000..74d1d40f14a
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-server.html
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+ Simple Webserver For Helpers 0.10
+
+
+
+
+
+
+
Simple Webserver For Helpers 0.10
+
+
+
+
wiki: http://contextgarden.net | mail: ntg-context@ntg.nl | website: http://www.pragma-ade.nl
+
+
+
+
+
+
+
Command line options
+
+ flag value description
+
+ --start start server
+ --port port to listen to
+ --root server root
+ --scripts scripts sub path
+ --index index file
+ --auto start on own path
+
+
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-server.man b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-server.man
new file mode 100644
index 00000000000..18373ad4b1c
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-server.man
@@ -0,0 +1,42 @@
+.TH "mtx-server" "1" "01-01-2013" "version 0.10" "Simple Webserver For Helpers"
+.SH NAME
+.B mtx-server
+.SH SYNOPSIS
+.B mtxrun --script server [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B Simple Webserver For Helpers
+.SH OPTIONS
+.TP
+.B --start
+start server
+.TP
+.B --port
+port to listen to
+.TP
+.B --root
+server root
+.TP
+.B --scripts
+scripts sub path
+.TP
+.B --index
+index file
+.TP
+.B --auto
+start on own path
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-server.xml b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-server.xml
new file mode 100644
index 00000000000..d7f3988baee
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-server.xml
@@ -0,0 +1,20 @@
+
+
+
+ mtx-server
+ Simple Webserver For Helpers
+ 0.10
+
+
+
+
+ start server
+ port to listen to
+ server root
+ scripts sub path
+ index file
+ start on own path
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-texworks.html b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-texworks.html
new file mode 100644
index 00000000000..996fe90eba1
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-texworks.html
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+ TeXworks Startup Script 1.00
+
+
+
+
+
+
+
TeXworks Startup Script 1.00
+
+
+
+
wiki: http://contextgarden.net | mail: ntg-context@ntg.nl | website: http://www.pragma-ade.nl
+
+
+
+
+
+
+
Command line options
+
+ flag value description
+
+ --start [--verbose] start texworks
+ --test report what will happen
+
+
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-texworks.man b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-texworks.man
new file mode 100644
index 00000000000..df2d4b84367
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-texworks.man
@@ -0,0 +1,30 @@
+.TH "mtx-texworks" "1" "01-01-2013" "version 1.00" "TeXworks Startup Script"
+.SH NAME
+.B mtx-texworks
+.SH SYNOPSIS
+.B mtxrun --script texworks [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B TeXworks Startup Script
+.SH OPTIONS
+.TP
+.B --start
+[--verbose] start texworks
+.TP
+.B --test
+report what will happen
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-texworks.xml b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-texworks.xml
new file mode 100644
index 00000000000..0dcb6b9dc22
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-texworks.xml
@@ -0,0 +1,16 @@
+
+
+
+ mtx-texworks
+ TeXworks Startup Script
+ 1.00
+
+
+
+
+ [ start texworks
+ report what will happen
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-timing.html b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-timing.html
new file mode 100644
index 00000000000..ebad34be5fe
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-timing.html
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+ ConTeXt Timing Tools 0.10
+
+
+
+
+
+
+
ConTeXt Timing Tools 0.10
+
+
+
+
wiki: http://contextgarden.net | mail: ntg-context@ntg.nl | website: http://www.pragma-ade.nl
+
+
+
+
+
+
+
Command line options
+
+ flag value description
+
+ --xhtml make xhtml file
+ --launch launch after conversion
+ --remove remove after launching
+
+
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-timing.man b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-timing.man
new file mode 100644
index 00000000000..831ce60eda4
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-timing.man
@@ -0,0 +1,33 @@
+.TH "mtx-timing" "1" "01-01-2013" "version 0.10" "ConTeXt Timing Tools"
+.SH NAME
+.B mtx-timing
+.SH SYNOPSIS
+.B mtxrun --script timing [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B ConTeXt Timing Tools
+.SH OPTIONS
+.TP
+.B --xhtml
+make xhtml file
+.TP
+.B --launch
+launch after conversion
+.TP
+.B --remove
+remove after launching
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-timing.xml b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-timing.xml
new file mode 100644
index 00000000000..d41322799dd
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-timing.xml
@@ -0,0 +1,17 @@
+
+
+
+ mtx-timing
+ ConTeXt Timing Tools
+ 0.10
+
+
+
+
+ make xhtml file
+ launch after conversion
+ remove after launching
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-tools.html b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-tools.html
new file mode 100644
index 00000000000..c4f25b2ed13
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-tools.html
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+
+ Some File Related Goodies 1.01
+
+
+
+
+
+
+
Some File Related Goodies 1.01
+
+
+
+
wiki: http://contextgarden.net | mail: ntg-context@ntg.nl | website: http://www.pragma-ade.nl
+
+
+
+
+
+
+
Command line options
+
+ flag value description
+
+ --disarmutfbomb remove utf bomb if present
+ --force remove indeed
+
+ --dirtoxml glob directory into xml
+ --pattern glob pattern (default: *)
+ --url url attribute (no processing)
+ --root the root of the globbed path (default: .)
+ --output output filename (console by default)
+ --recurse recurse into subdirecories
+ --stripname take pathpart of given pattern
+ --longname set name attributes to full path name
+
+ --pattern glob pattern (default: *)
+ --recurse recurse into subdirecories
+ --force downcase indeed
+
+
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-tools.man b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-tools.man
new file mode 100644
index 00000000000..f56b27bde55
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-tools.man
@@ -0,0 +1,63 @@
+.TH "mtx-tools" "1" "01-01-2013" "version 1.01" "Some File Related Goodies"
+.SH NAME
+.B mtx-tools
+.SH SYNOPSIS
+.B mtxrun --script tools [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B Some File Related Goodies
+.SH OPTIONS
+.TP
+.B --disarmutfbomb
+remove utf bomb if present
+.TP
+.B --force
+remove indeed
+.TP
+.B --dirtoxml
+glob directory into xml
+.TP
+.B --pattern
+glob pattern (default: *)
+.TP
+.B --url
+url attribute (no processing)
+.TP
+.B --root
+the root of the globbed path (default: .)
+.TP
+.B --output
+output filename (console by default)
+.TP
+.B --recurse
+recurse into subdirecories
+.TP
+.B --stripname
+take pathpart of given pattern
+.TP
+.B --longname
+set name attributes to full path name
+.TP
+.B --pattern
+glob pattern (default: *)
+.TP
+.B --recurse
+recurse into subdirecories
+.TP
+.B --force
+downcase indeed
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-tools.xml b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-tools.xml
new file mode 100644
index 00000000000..a2ce84d5b32
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-tools.xml
@@ -0,0 +1,31 @@
+
+
+
+ mtx-tools
+ Some File Related Goodies
+ 1.01
+
+
+
+
+ remove utf bomb if present
+ remove indeed
+
+
+ glob directory into xml
+ glob pattern (default: *)
+ url attribute (no processing)
+ the root of the globbed path (default: .)
+ output filename (console by default)
+ recurse into subdirecories
+ take pathpart of given pattern
+ set name attributes to full path name
+
+
+ glob pattern (default: *)
+ recurse into subdirecories
+ downcase indeed
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-unzip.html b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-unzip.html
new file mode 100644
index 00000000000..58c124487db
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-unzip.html
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+ Simple Unzipper 0.10
+
+
+
+
+
+
+
+
wiki: http://contextgarden.net | mail: ntg-context@ntg.nl | website: http://www.pragma-ade.nl
+
+
+
+
+
+
+
Command line options
+
+ flag value description
+
+ --list list files in archive
+ --junk flatten unzipped directory structure
+ --extract extract files
+
+
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-unzip.man b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-unzip.man
new file mode 100644
index 00000000000..5e1a369b2f7
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-unzip.man
@@ -0,0 +1,33 @@
+.TH "mtx-unzip" "1" "01-01-2013" "version 0.10" "Simple Unzipper"
+.SH NAME
+.B mtx-unzip
+.SH SYNOPSIS
+.B mtxrun --script unzip [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B Simple Unzipper
+.SH OPTIONS
+.TP
+.B --list
+list files in archive
+.TP
+.B --junk
+flatten unzipped directory structure
+.TP
+.B --extract
+extract files
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-unzip.xml b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-unzip.xml
new file mode 100644
index 00000000000..9f56ca076d1
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-unzip.xml
@@ -0,0 +1,17 @@
+
+
+
+ mtx-unzip
+ Simple Unzipper
+ 0.10
+
+
+
+
+ list files in archive
+ flatten unzipped directory structure
+ extract files
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-update.html b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-update.html
new file mode 100644
index 00000000000..ea04dcfb36d
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-update.html
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+
+
+
+
+ ConTeXt Minimals Updater 0.31
+
+
+
+
+
+
+
ConTeXt Minimals Updater 0.31
+
+
+
+
wiki: http://contextgarden.net | mail: ntg-context@ntg.nl | website: http://www.pragma-ade.nl
+
+
+
+
+
+
+
Command line options
+
+ flag value description
+
+ --platform string platform (windows, linux, linux-64, osx-intel, osx-ppc, linux-ppc)
+ --server string repository url (rsync://contextgarden.net)
+ --module string repository url (minimals)
+ --repository string specify version (current, experimental)
+ --context string specify version (current, latest, beta, yyyy.mm.dd)
+ --rsync string rsync binary (rsync)
+ --texroot string installation directory (not guessed for the moment)
+ --engine string tex engine (luatex, pdftex, xetex)
+ --modules string extra modules (can be list or 'all')
+ --fonts string additional fonts (can be list or 'all')
+ --goodies string extra binaries (like scite and texworks)
+ --force instead of a dryrun, do the real thing
+ --update update minimal tree
+ --make also make formats and generate file databases
+ --keep don't delete unused or obsolete files
+ --state update tree using saved state
+ --cygwin adapt drive specs to cygwin
+ --mingw assume mingw binaries being used
+
+
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-update.man b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-update.man
new file mode 100644
index 00000000000..72e7ce1b5ae
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-update.man
@@ -0,0 +1,78 @@
+.TH "mtx-update" "1" "01-01-2013" "version 0.31" "ConTeXt Minimals Updater"
+.SH NAME
+.B mtx-update
+.SH SYNOPSIS
+.B mtxrun --script update [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B ConTeXt Minimals Updater
+.SH OPTIONS
+.TP
+.B --platform=string
+platform (windows, linux, linux-64, osx-intel, osx-ppc, linux-ppc)
+.TP
+.B --server=string
+repository url (rsync://contextgarden.net)
+.TP
+.B --module=string
+repository url (minimals)
+.TP
+.B --repository=string
+specify version (current, experimental)
+.TP
+.B --context=string
+specify version (current, latest, beta, yyyy.mm.dd)
+.TP
+.B --rsync=string
+rsync binary (rsync)
+.TP
+.B --texroot=string
+installation directory (not guessed for the moment)
+.TP
+.B --engine=string
+tex engine (luatex, pdftex, xetex)
+.TP
+.B --modules=string
+extra modules (can be list or 'all')
+.TP
+.B --fonts=string
+additional fonts (can be list or 'all')
+.TP
+.B --goodies=string
+extra binaries (like scite and texworks)
+.TP
+.B --force
+instead of a dryrun, do the real thing
+.TP
+.B --update
+update minimal tree
+.TP
+.B --make
+also make formats and generate file databases
+.TP
+.B --keep
+don't delete unused or obsolete files
+.TP
+.B --state
+update tree using saved state
+.TP
+.B --cygwin
+adapt drive specs to cygwin
+.TP
+.B --mingw
+assume mingw binaries being used
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-update.xml b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-update.xml
new file mode 100644
index 00000000000..95e99134156
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-update.xml
@@ -0,0 +1,32 @@
+
+
+
+ mtx-update
+ ConTeXt Minimals Updater
+ 0.31
+
+
+
+
+ platform (windows, linux, linux-64, osx-intel, osx-ppc, linux-ppc)
+ repository url (rsync://contextgarden.net)
+ repository url (minimals)
+ specify version (current, experimental)
+ specify version (current, latest, beta, yyyy.mm.dd)
+ rsync binary (rsync)
+ installation directory (not guessed for the moment)
+ tex engine (luatex, pdftex, xetex)
+ extra modules (can be list or 'all')
+ additional fonts (can be list or 'all')
+ extra binaries (like scite and texworks)
+ instead of a dryrun, do the real thing
+ update minimal tree
+ also make formats and generate file databases
+ don't delete unused or obsolete files
+ update tree using saved state
+ adapt drive specs to cygwin
+ assume mingw binaries being used
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-watch.html b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-watch.html
new file mode 100644
index 00000000000..a4f783e0449
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-watch.html
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+ ConTeXt Request Watchdog 1.00
+
+
+
+
+
+
+
ConTeXt Request Watchdog 1.00
+
+
+
+
wiki: http://contextgarden.net | mail: ntg-context@ntg.nl | website: http://www.pragma-ade.nl
+
+
+
+
+
+
+
Command line options
+
+ flag value description
+
+ --logpath optional path for log files
+ --watch watch given path [--delay]
+ --pipe use pipe instead of execute
+ --delay delay between sweeps
+ --automachine replace /machine/ in path /servername/
+ --collect condense log files
+ --cleanup delay remove files in given path [--force]
+ --showlog show log data
+
+
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-watch.man b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-watch.man
new file mode 100644
index 00000000000..9f4a0d3b9d7
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-watch.man
@@ -0,0 +1,48 @@
+.TH "mtx-watch" "1" "01-01-2013" "version 1.00" "ConTeXt Request Watchdog"
+.SH NAME
+.B mtx-watch
+.SH SYNOPSIS
+.B mtxrun --script watch [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B ConTeXt Request Watchdog
+.SH OPTIONS
+.TP
+.B --logpath
+optional path for log files
+.TP
+.B --watch
+watch given path [--delay]
+.TP
+.B --pipe
+use pipe instead of execute
+.TP
+.B --delay
+delay between sweeps
+.TP
+.B --automachine
+replace /machine/ in path /servername/
+.TP
+.B --collect
+condense log files
+.TP
+.B --cleanup=delay
+remove files in given path [--force]
+.TP
+.B --showlog
+show log data
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtx-watch.xml b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-watch.xml
new file mode 100644
index 00000000000..14a3a5f1690
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtx-watch.xml
@@ -0,0 +1,22 @@
+
+
+
+ mtx-watch
+ ConTeXt Request Watchdog
+ 1.00
+
+
+
+
+ optional path for log files
+ watch given path [
+ use pipe instead of execute
+ delay between sweeps
+ replace /machine/ in path /servername/
+ condense log files
+ remove files in given path [
+ show log data
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtxrun.html b/Master/texmf-dist/doc/context/scripts/mkiv/mtxrun.html
new file mode 100644
index 00000000000..37731369499
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtxrun.html
@@ -0,0 +1,94 @@
+
+
+
+
+
+
+
+
+
+
+ ConTeXt TDS Runner Tool 1.31
+
+
+
+
+
+
+
ConTeXt TDS Runner Tool 1.31
+
+
+
+
wiki: http://contextgarden.net | mail: ntg-context@ntg.nl | website: http://www.pragma-ade.nl
+
+
+
+
+
+
+
Command line options
+
+ flag value description
+
+ --script run an mtx script (lua prefered method) (--noquotes), no script gives list
+ --execute run a script or program (texmfstart method) (--noquotes)
+ --resolve resolve prefixed arguments
+ --ctxlua run internally (using preloaded libs)
+ --internal run script using built in libraries (same as --ctxlua)
+ --locate locate given filename in database (default) or system (--first --all --detail)
+
+ --autotree use texmf tree cf. env texmfstart_tree or texmfstarttree
+ --tree pathtotree use given texmf tree (default file: setuptex.tmf)
+ --environment name use given (tmf) environment file
+ --path runpath go to given path before execution
+ --ifchanged filename only execute when given file has changed (md checksum)
+ --iftouched old,new only execute when given file has changed (time stamp)
+
+ --makestubs create stubs for (context related) scripts
+ --removestubs remove stubs (context related) scripts
+ --stubpath binpath paths where stubs wil be written
+ --windows create windows (mswin) stubs
+ --unix create unix (linux) stubs
+
+ --verbose give a bit more info
+ --trackers list enable given trackers
+ --progname str format or backend
+
+ --edit launch editor with found file
+ --launch launch files like manuals, assumes os support (--all)
+
+ --timedrun run a script and time its run
+ --autogenerate regenerate databases if needed (handy when used to run context in an editor)
+
+ --usekpse use kpse as fallback (when no mkiv and cache installed, often slower)
+ --forcekpse force using kpse (handy when no mkiv and cache installed but less functionality)
+
+ --prefixes show supported prefixes
+
+ --generate generate file database
+
+ --variables show configuration variables
+ --configurations show configuration order
+
+ --directives show (known) directives
+ --trackers show (known) trackers
+ --experiments show (known) experiments
+
+ --expand-braces expand complex variable
+ --expand-path expand variable (resolve paths)
+ --expand-var expand variable (resolve references)
+ --show-path show path expansion of ...
+ --var-value report value of variable
+ --find-file report file location
+ --find-path report path of file
+
+ --pattern string filter variables
+
+
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtxrun.man b/Master/texmf-dist/doc/context/scripts/mkiv/mtxrun.man
new file mode 100644
index 00000000000..212097ff153
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtxrun.man
@@ -0,0 +1,147 @@
+.TH "mtxrun" "1" "01-01-2013" "version 1.31" "ConTeXt TDS Runner Tool"
+.SH NAME
+.B mtxrun
+.SH SYNOPSIS
+.B mtxrun [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B ConTeXt TDS Runner Tool
+.SH OPTIONS
+.TP
+.B --script
+run an mtx script (lua prefered method) (--noquotes), no script gives list
+.TP
+.B --execute
+run a script or program (texmfstart method) (--noquotes)
+.TP
+.B --resolve
+resolve prefixed arguments
+.TP
+.B --ctxlua
+run internally (using preloaded libs)
+.TP
+.B --internal
+run script using built in libraries (same as --ctxlua)
+.TP
+.B --locate
+locate given filename in database (default) or system (--first --all --detail)
+.TP
+.B --autotree
+use texmf tree cf. env texmfstart_tree or texmfstarttree
+.TP
+.B --tree=pathtotree
+use given texmf tree (default file: setuptex.tmf)
+.TP
+.B --environment=name
+use given (tmf) environment file
+.TP
+.B --path=runpath
+go to given path before execution
+.TP
+.B --ifchanged=filename
+only execute when given file has changed (md checksum)
+.TP
+.B --iftouched=old,new
+only execute when given file has changed (time stamp)
+.TP
+.B --makestubs
+create stubs for (context related) scripts
+.TP
+.B --removestubs
+remove stubs (context related) scripts
+.TP
+.B --stubpath=binpath
+paths where stubs wil be written
+.TP
+.B --windows
+create windows (mswin) stubs
+.TP
+.B --unix
+create unix (linux) stubs
+.TP
+.B --verbose
+give a bit more info
+.TP
+.B --trackers=list
+enable given trackers
+.TP
+.B --progname=str
+format or backend
+.TP
+.B --edit
+launch editor with found file
+.TP
+.B --launch
+launch files like manuals, assumes os support (--all)
+.TP
+.B --timedrun
+run a script and time its run
+.TP
+.B --autogenerate
+regenerate databases if needed (handy when used to run context in an editor)
+.TP
+.B --usekpse
+use kpse as fallback (when no mkiv and cache installed, often slower)
+.TP
+.B --forcekpse
+force using kpse (handy when no mkiv and cache installed but less functionality)
+.TP
+.B --prefixes
+show supported prefixes
+.TP
+.B --generate
+generate file database
+.TP
+.B --variables
+show configuration variables
+.TP
+.B --configurations
+show configuration order
+.TP
+.B --directives
+show (known) directives
+.TP
+.B --trackers
+show (known) trackers
+.TP
+.B --experiments
+show (known) experiments
+.TP
+.B --expand-braces
+expand complex variable
+.TP
+.B --expand-path
+expand variable (resolve paths)
+.TP
+.B --expand-var
+expand variable (resolve references)
+.TP
+.B --show-path
+show path expansion of ...
+.TP
+.B --var-value
+report value of variable
+.TP
+.B --find-file
+report file location
+.TP
+.B --find-path
+report path of file
+.TP
+.B --pattern=string
+filter variables
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/context/scripts/mkiv/mtxrun.xml b/Master/texmf-dist/doc/context/scripts/mkiv/mtxrun.xml
new file mode 100644
index 00000000000..f1b1e01f4b6
--- /dev/null
+++ b/Master/texmf-dist/doc/context/scripts/mkiv/mtxrun.xml
@@ -0,0 +1,79 @@
+
+
+
+ mtxrun
+ ConTeXt TDS Runner Tool
+ 1.31
+
+
+
+
+ run an mtx script (lua prefered method) (), no script gives list
+ run a script or program (texmfstart method) ()
+ resolve prefixed arguments
+ run internally (using preloaded libs)
+ run script using built in libraries (same as )
+ locate given filename in database (default) or system ( )
+
+
+ use texmf tree cf. env texmfstart_tree or texmfstarttree
+ use given texmf tree (default file: setuptex.tmf)
+ use given (tmf) environment file
+ go to given path before execution
+ only execute when given file has changed (md checksum)
+ only execute when given file has changed (time stamp)
+
+
+ create stubs for (context related) scripts
+ remove stubs (context related) scripts
+ paths where stubs wil be written
+ create windows (mswin) stubs
+ create unix (linux) stubs
+
+
+ give a bit more info
+ enable given trackers
+ format or backend
+
+
+ launch editor with found file
+ launch files like manuals, assumes os support ()
+
+
+ run a script and time its run
+ regenerate databases if needed (handy when used to run context in an editor)
+
+
+ use kpse as fallback (when no mkiv and cache installed, often slower)
+ force using kpse (handy when no mkiv and cache installed but less functionality)
+
+
+ show supported prefixes
+
+
+ generate file database
+
+
+ show configuration variables
+ show configuration order
+
+
+ show (known) directives
+ show (known) trackers
+ show (known) experiments
+
+
+ expand complex variable
+ expand variable (resolve paths)
+ expand variable (resolve references)
+ show path expansion of ...
+ report value of variable
+ report file location
+ report path of file
+
+
+ filter variables
+
+
+
+
diff --git a/Master/texmf-dist/doc/context/scripts/perl/texshow.1 b/Master/texmf-dist/doc/context/scripts/perl/texshow.1
deleted file mode 100644
index 618928b8f4b..00000000000
--- a/Master/texmf-dist/doc/context/scripts/perl/texshow.1
+++ /dev/null
@@ -1,70 +0,0 @@
-.TH "texshow" "1" "Jul 2006" "ConTeXt" "CONTEXT"
-.PP
-.SH "NAME"
-texshow \- ConTeXt command and parameter reference
-.PP
-.SH "SYNOPSIS"
-\fBtexshow\fP [ \fIOPTION\fP ] [ \fICOMMAND\fP ]
-[ \fILANGUAGE\fP ]
-.PP
-.SH "DESCRIPTION"
-.PP
-\fBtexshow\fP uses \fBperl\fP(1) and PerlTk (see \fBTk\fP(3pm)) to
-show a overview of the commands and parameters of those\&. In the Tk
-window you can search for a command and by switching the interface,
-you can see the equivalent in another interface language\&.
-.PP
-\fICOMMAND\fP is a \fBConTeXt\fP command to search for in the
-database\&. Note that Plain TeX commands are not (yet) in this database
-although they can be used in \fBConTeXt\fP source files\&.
-.PP
-\fILANGUAGE\fP can be one of \fBcz\fP (Czech), \fBde\fP
-(German), \fBen\fP (US-English) or \fBnl\fP (Dutch)\&. The default
-language is English\&.
-.PP
-You can also set the interface language with the
-\fB--interface\fP switch\&.
-.PP
-.SH "BINDINGS"
-.PP
-Most keyboard events are bound to the search widget, with the
-exception of \fB\fP (aka \fB\fP) and \fB\fP
-(aka \fB\fP). \fB\fP, \fB\fP, and
-\fB\fP quit the application\&.
-.PP
-.SH "OPTIONS"
-.PP
-.IP "\fB--help\fP"
-Print a brief syntax summary
-.IP "\fB--interface=\fP\fILANGUAGE\fP"
-Primary interface language\&.
-See DESCRIPTION for \fILANGUAGE\fP options\&.
-.PP
-.SH "FILES"
-.PP
-.IP "\fITEXMF/tex/context/interface/cont-\fIXX\fP\&.xml\fP"
-The database
-file\&. At this writing, \fIXX\fP can be one of \fBcz\fP (Czech),
-\fBde\fP (German), \fBen\fP (English), \fBfr\fP (French),
-\fBit\fP (Italian), \fBnl\fP (Dutch), or \fBro\fP (Romanian)\&.
-Which file is used is determined by the
-\fILANGUAGE\fP specified on the command line\&.
-.PP
-.SH "SEE ALSO"
-.PP
-\fBtexexec\fP(1), \fBpdfetex\fP(1), \fBpdftex\fP(1)\&.
-.PP
-Web page:
-.PP
-.SH "AUTHOR"
-.PP
-This version of \fBtexshow\fP was written by Taco Hoekwater
-\&.
-.PP
-This manpage was written by Tobias Burnus
- and C\&.M\&. Connelly
-\&.
-.PP
-\fBtexshow\fP is part of \fBConTeXt\fP and is available
-from \&.
-.PP
diff --git a/Master/texmf-dist/doc/context/scripts/perl/texshow.html b/Master/texmf-dist/doc/context/scripts/perl/texshow.html
deleted file mode 100644
index a9af24284c6..00000000000
--- a/Master/texmf-dist/doc/context/scripts/perl/texshow.html
+++ /dev/null
@@ -1,137 +0,0 @@
-Manpage of texshow
-
-texshow
-Section: CONTEXT (1) Updated: Jul 2006Index
-Return to Main Contents
-
-
-
-
-
NAME
-
-texshow - ConTeXt command and parameter reference
-
-
-
-
SYNOPSIS
-
-texshow [ OPTION ] [ COMMAND ]
-[ LANGUAGE ]
-
-
-
-
DESCRIPTION
-
-
-
-texshow uses perl (1) and PerlTk (see Tk (3pm)) to
-show a overview of the commands and parameters of those. In the Tk
-window you can search for a command and by switching the interface,
-you can see the equivalent in another interface language.
-
-
-COMMAND is a ConTeXt command to search for in the
-database. Note that Plain TeX commands are not (yet) in this database
-although they can be used in ConTeXt source files.
-
-
-LANGUAGE can be one of cz (Czech), de
-(German), en (US-English) or nl (Dutch). The default
-language is English.
-
-
-You can also set the interface language with the
---interface switch.
-
-
-
-
BINDINGS
-
-
-
-Most keyboard events are bound to the search widget, with the
-exception of <Page Up> (aka <Prior> ) and <Page Down>
-(aka <Next> ). <Control-q> , <Control-x> , and
-<Alt-F4> quit the application.
-
-
-
-
OPTIONS
-
-
-
-
---help
-Print a brief syntax summary
- --interface= LANGUAGE
-Primary interface language.
-See DESCRIPTION for LANGUAGE options.
-
-
-
-
-
FILES
-
-
-
-
-TEXMF/tex/context/interface/cont-XX .xml
-The database
-file. At this writing, XX can be one of cz (Czech),
-de (German), en (English), fr (French),
-it (Italian), nl (Dutch), or ro (Romanian).
-Which file is used is determined by the
-LANGUAGE specified on the command line.
-
-
-
-
-
SEE ALSO
-
-
-
-texexec (1), pdfetex (1), pdftex (1).
-
-
-Web page: <http://www.pragma-ade.com/ >
-
-
-
-
AUTHOR
-
-
-
-This version of texshow was written by Taco Hoekwater
-<taco@elvenkind.com >.
-
-
-This manpage was written by Tobias Burnus
-<burnus@gmx.de > and C.M. Connelly
-<c@eskimo.com>.
-
-
-texshow is part of ConTeXt and is available
-from <http://www.pragma-ade.com/pragma-ade/ >.
-
-
-
-
-
- Index
-
-NAME
- SYNOPSIS
- DESCRIPTION
- BINDINGS
- OPTIONS
- FILES
- SEE ALSO
- AUTHOR
-
-
-This document was created by
-man2html ,
-using the manual pages.
-Time: 09:31:15 GMT, July 19, 2006
-
-
diff --git a/Master/texmf-dist/doc/man/man1/context.1 b/Master/texmf-dist/doc/man/man1/context.1
index 254d9b87468..e1fb28a994e 100644
--- a/Master/texmf-dist/doc/man/man1/context.1
+++ b/Master/texmf-dist/doc/man/man1/context.1
@@ -1,140 +1,167 @@
-.TH "CONTEXT" "1" "June 2011" "context 0.52" "ConTeXt"
-.de URL
-\\$2 \(laURL: \\$1 \(ra\\$3
-..
-.if \n[.g] .mso www.tmac
-.de EX
-.in +3
-.nf
-.ft CW
-..
-.de EE
-.in -3
-.ft R
-.fi
-..
-
-.SH "NAME"
-context \- front end to the new ConTeXt typesetting system
-
-.SH "SYNOPSIS"
-\fBcontext\fP [ \fIOPTION\fP ... ] \fIFILE\fP [ ... ]
-
-.SH "DESCRIPTION"
-
-\fBcontext\fP, a \fBtexlua\fP(1) script,
-is the command-line front end to the new version of the
-ConTeXt typesetting system, an extensive macro package
-built on the \fBtex\fP(1) family of typesetting programs.
-\fBcontext\fP provides several facilties:
-.IP \(bu
-Process a ConTeXt source file,
-performing as many runs as
-necessary of \fBluatex\fP(1). Options control the output
-format, the pages to process, paper size, and so forth.
-.IP \(bu
-Create new ConTeXt formats, useful during installation.
-.IP \(bu
-Post-process existing PDF files, including merging multiple
-files, and extracting and rearranging pages within a file,
-similar to the facilities provided for PostScript files by
-\fBpsnup\fP(1) or for PDF files by \fBpdftk\fP(1).
-.IP
-.SH "OPTIONS"
-
-All switches should always be specified in full. With no options,
-\fBcontext\fP assumes that
-the file on the command line is a ConTeXt source file, i.e. a TeX file
-in the ConTeXt dialect, and produces a PDF file using the source file.
-
-.IP "\fB--run\fP"
+.TH "mtx-context" "1" "01-01-2013" "version 0.60" "ConTeXt Process Management"
+.SH NAME
+.B mtx-context
+.SH SYNOPSIS
+.B mtxrun --script context [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B ConTeXt Process Management
+.SH OPTIONS: BASIC
+.TP
+.B --run
process (one or more) files (default action)
-.IP "\fB--make\fP"
+.TP
+.B --make
create context formats
-.IP "\fB--ctx\fP\fI=\fP\fIname\fP"
+.TP
+.B --ctx=name
use ctx file (process management specification)
-.IP "\fB--interface\fP"
+.TP
+.B --interface
use specified user interface (default: en)
-.IP "\fB--autopdf\fP"
+.TP
+.B --autopdf
close pdf file in viewer and start pdf viewer afterwards
-.IP "\fB--purge(all)\fP"
-purge files either or not after a run (\fB--pattern\fP\fI=\fP\fI...\fP)
-.IP "\fB--usemodule\fP\fI=\fP\fIlist\fP"
-load the given module or style, normally part o fthe distribution
-.IP "\fB--environment\fP\fI=\fP\fIlist\fP"
+.TP
+.B --purge
+purge files either or not after a run (--pattern=...)
+.TP
+.B --purgeall
+purge all files either or not after a run (--pattern=...)
+.TP
+.B --usemodule=list
+load the given module or style, normally part of the distribution
+.TP
+.B --environment=list
load the given environment file first (document styles)
-.IP "\fB--mode\fP\fI=\fP\fIlist\fP"
+.TP
+.B --mode=list
enable given the modes (conditional processing in styles)
-.IP "\fB--path\fP\fI=\fP\fIlist\fP"
+.TP
+.B --path=list
also consult the given paths when files are looked for
-.IP "\fB--arguments\fP\fI=\fP\fIlist\fP"
+.TP
+.B --arguments=list
set variables that can be consulted during a run (key/value pairs)
-.IP "\fB--randomseed\fP\fI=\fP\fInumber\fP"
+.TP
+.B --randomseed=number
set the randomseed
-.IP "\fB--result\fP\fI=\fP\fIname\fP"
+.TP
+.B --result=name
rename the resulting output to the given name
-.IP "\fB--trackers\fP\fI=\fP\fIlist\fP"
-set tracker variables (show list with \fB--showtrackers\fP)
-.IP "\fB--directives\fP\fI=\fP\fIlist\fP"
-set directive variables (show list with \fB--showdirectives\fP)
-.IP "\fB--silent\fP\fI=\fP\fIlist\fP"
-disable logcatgories (show list with \fB--showlogcategories\fP)
-.IP "\fB--noconsole\fP"
+.TP
+.B --trackers=list
+set tracker variables (show list with --showtrackers)
+.TP
+.B --directives=list
+set directive variables (show list with --showdirectives)
+.TP
+.B --silent=list
+disable logcatgories (show list with --showlogcategories)
+.TP
+.B --noconsole
disable logging to the console (logfile only)
-.IP "\fB--purgeresult\fP"
+.TP
+.B --purgeresult
purge result file before run
-.IP "\fB--forcexml\fP"
-force xml stub (optional flag: \fB--mkii\fP)
-.IP "\fB--forcecld\fP"
+.TP
+.B --forcexml
+force xml stub
+.TP
+.B --forcecld
force cld (context lua document) stub
-.IP "\fB--arrange\fP"
+.TP
+.B --forcelua
+force lua stub (like texlua)
+.TP
+.B --forcemp
+force mp stub
+.TP
+.B --arrange
run extra imposition pass, given that the style sets up imposition
-.IP "\fB--noarrange\fP"
+.TP
+.B --noarrange
ignore imposition specifications in the style
-.IP "\fB--once\fP"
+.TP
+.B --jit
+use luajittex with jit turned off (only use the faster virtual machine)
+.TP
+.B --jiton
+use luajittex with jit turned on (in most cases not faster, even slower)
+.TP
+.B --once
only run once (no multipass data file is produced)
-.IP "\fB--batchmode\fP"
-run without stopping and don't show messages on the console
-.IP "\fB--nonstopmode\fP"
+.TP
+.B --batchmode
+run without stopping and do not show messages on the console
+.TP
+.B --nonstopmode
run without stopping
-.IP "\fB--generate\fP"
-generate file database etc. (as \fBmtxrun\fP does)
-.IP "\fB--paranoid\fP"
-don't descend to .. and ../..
-.IP "\fB--version\fP"
+.TP
+.B --synctex
+run with synctex enabled (optional value: zipped, unzipped, 1, -1)
+.TP
+.B --generate
+generate file database etc. (as luatools does)
+.TP
+.B --paranoid
+do not descend to .. and ../..
+.TP
+.B --version
report installed context version
-.IP "\fB--expert\fP"
-show expert options
-
-
-.SH "INITIALIZATION"
-
-.PP
-The \fBcontext\fP command is just a stub that runs the larger \fBmtxrun\fP
-script, which is a scripting framework written for \fBtexlua\fP(1) that
-supports loading of extra modules, of which \fBcontext\fP is one. The
-implementation actually resides in a file named \fBmtx-context.lua\fP
-deep within the TDS structure.
-
-If \fBcontext\fP complains about \fBUnknown script 'context'\fP, this
-can usually be fixed by executing \fBmtxrun --generate\fP on the
-command line: this command regenerates the database that \fBmtxrun\fP
-uses to find its extra modules.
+.TP
+.B --global
+assume given file present elsewhere
+.TP
+.B --nofile
+use dummy file as jobname
+.SH OPTIONS: EXPERT
+.TP
+.B --touch
+update context version number (remake needed afterwards, also provide --expert)
+.TP
+.B --nostatistics
+omit runtime statistics at the end of the run
+.TP
+.B --update
+update context from website (not to be confused with contextgarden)
+.TP
+.B --profile
+profile job (use: mtxrun --script profile --analyze)
+.TP
+.B --timing
+generate timing and statistics overview
+.TP
+.B --extra=name
+process extra (mtx-context-... in distribution)
+.TP
+.B --extras
+show extras
+.SH OPTIONS: SPECIAL
+.TP
+.B --pdftex
+process file with texexec using pdftex
+.TP
+.B --xetex
+process file with texexec using xetex
+.TP
+.B --mkii
+process file with texexec
+.TP
+.B --pipe
+do not check for file and enter scroll mode (--dummyfile=whatever.tmp)
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
-.SH "SEE ALSO"
-.PP
-\fBtex\fP(1), \fBluatex\fP(1), \fBtexlua\fP(1), \fBpsnup\fP(1), \fBpdftk\fP(1).
-.PP
-.URL "http://www.contextgarden.net" "ConTeXt wiki" .
-.PP
-.URL "http://www.ntg.nl/mailman/listinfo/ntg-context" "ConTeXt mailing list home" .
-.SH "BUGS"
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
-.PP
-This manpage is horribly incomplete.
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
-.SH "AUTHOR"
-This partial manpage was written by Taco Hoekwater
-.
-It is based on the \fB--help\fP output of \fBcontext\fP.
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/man/man1/ctxtools.1 b/Master/texmf-dist/doc/man/man1/ctxtools.1
index c22263d4267..93218f2295f 100644
--- a/Master/texmf-dist/doc/man/man1/ctxtools.1
+++ b/Master/texmf-dist/doc/man/man1/ctxtools.1
@@ -1,89 +1,75 @@
-.de URL
-\\$2 \(laURL: \\$1 \(ra\\$3
-..
-.if \n[.g] .mso www.tmac
-.de EX
-.in +3
-.nf
-.ft CW
-..
-.de EE
-.in -3
-.ft R
-.fi
-..
-.TH CTXTOOLS "1" "January 2007" "ctxtools 1.3.3" "ConTeXt"
-
+.TH "ctxtools" "1" "01-01-2013" "version 1.3.5" "CtxTools"
.SH NAME
-ctxtools \- clean up temporary ConTeXt files, install latest ConTeXt
-
-.SH "SYNOPSIS"
-\fBctxtools\fP [ \fIOPTION\fP ... ]
-
+.B ctxtools
+.SH SYNOPSIS
+.B ctxtools [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
.SH DESCRIPTION
-\fBctxtools\fP is useful for dealing with ConTeXt source and generated
-files and for installing new versions of ConTeXt.
-
-.SH "OPTIONS"
-.TP
-.B --help
-Print the available options.
-.TP
-.B --purgefiles
-Get rid of many temporary files generated by ConTeXt. You can give the
-.B --all
-option to remove a larger fraction of those files,
-and the
-.B --recurse
-option to remove these files also in subdirectories.
-.TP
+.B CtxTools
+.SH OPTIONS
+.TP
+.B --touchcontextfile
+update context version
+.TP
.B --contextversion
-Show the date of the ConTeXt macros and the format file. Useful after
-upgrading ConTeXt (perhaps using \fB--updatecontext\fP) to check
-whether the new formats and macros are visible to the TeX path
-searches (see
-.BR kpsewhich (1).
-.TP
+report context version
+.TP
+.B --jeditinterface
+generate jedit syntax files [--pipe]
+.TP
+.B --bbeditinterface
+generate bbedit syntax files [--pipe]
+.TP
+.B --sciteinterface
+generate scite syntax files [--pipe]
+.TP
+.B --rawinterface
+generate raw syntax files [--pipe]
+.TP
+.B --translateinterface
+generate interface files (xml) [nl de ..]
+.TP
+.B --purgefiles
+remove temporary files [--all --recurse] [basename]
+.TP
+.B --documentation generate documentation [--type=]
+[filename]
+.TP
+.B --filterpages'
+) # no help, hidden temporary feature
+.TP
+.B --dpxmapfiles
+convert pdftex mapfiles to dvipdfmx [--force] [texmfroot]
+.TP
+.B --listentities
+create doctype entity definition from enco-uc.tex
+.TP
+.B --brandfiles
+add context copyright notice [--force]
+.TP
+.B --platformize
+replace line-endings [--recurse --force] [pattern]
+.TP
+.B --dependencies analyze depedencies within context [--save --compact --filter=[macros|filenames] ]
+[filename]
+.TP
.B --updatecontext
-Download the latest ConTeXt distribution and install it in the
-TEXMFLOCAL tree (see
-.BR kpsewhich (1)
-for information on
-TeX path searching). TEXMFLOCAL usually points to a system-wide
-location. If you want to install the new ConTeXt in your home
-directory (i.e. an install for one user), then set the TEXMFLOCAL
-environment variable while running
-.BR ctxtools .
-For example, using the syntax of the Bourne shell
-.BR sh (1):
-.EX
-TEXMFLOCAL=$HOME/texmf ctxtools --updatecontext
-.EE
-.TP
-.B --documentation
-Generate a \fI.ted\fP file from the source file. See also the
-\fB--module\fP option to
-.BR texexec (1).
-.TP
-\fB--patternfiles\fP [languagecode]
-Generate pattern files. You can also give the
-\fB--all\fP, \fB--xml\fP, and \fB--utf8\fP options.
-
-.SH "ENVIRONMENT"
+download latest version and remake formats [--proxy]
.TP
-TEXMFLOCAL
-Used by \f(CW--updatecontext\fP to decide where to install the distribution.
+.B --disarmutfbom
+remove utf bom [--force]
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
-.SH "SEE ALSO"
-.PP
-.BR texexec (1),
-.BR texmfstart (1).
-.PP
-.URL "http://www.contextgarden.net" "ConTeXt wiki" .
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
-.SH BUGS
-This manual page is not complete.
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
-.SH "AUTHOR"
-This manual page was written by Sanjoy Mahajan . It is in
-the public domain.
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/man/man1/luatools.1 b/Master/texmf-dist/doc/man/man1/luatools.1
new file mode 100644
index 00000000000..145e9f6083b
--- /dev/null
+++ b/Master/texmf-dist/doc/man/man1/luatools.1
@@ -0,0 +1,78 @@
+.TH "luatools" "1" "01-01-2013" "version 1.35" "ConTeXt TDS Management Tool (aka luatools)"
+.SH NAME
+.B luatools
+.SH SYNOPSIS
+.B luatools [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B ConTeXt TDS Management Tool (aka luatools)
+.SH OPTIONS
+.TP
+.B --generate
+generate file database
+.TP
+.B --variables
+show configuration variables
+.TP
+.B --configurations
+show configuration order
+.TP
+.B --expand-braces
+expand complex variable
+.TP
+.B --expand-path
+expand variable (resolve paths)
+.TP
+.B --expand-var
+expand variable (resolve references)
+.TP
+.B --show-path
+show path expansion of ...
+.TP
+.B --var-value
+report value of variable
+.TP
+.B --find-file
+report file location
+.TP
+.B --find-path
+report path of file
+.TP
+.B --make
+[or --ini] make luatex format
+.TP
+.B --run
+[or --fmt] run luatex format
+.TP
+.B --compile
+assemble and compile lua inifile
+.TP
+.B --verbose
+give a bit more info
+.TP
+.B --all
+show all found files
+.TP
+.B --format=str
+filter cf format specification (default 'tex', use 'any' for any match)
+.TP
+.B --pattern=str
+filter variables
+.TP
+.B --trackers=list
+enable given trackers
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/man/man1/luatools.man1.pdf b/Master/texmf-dist/doc/man/man1/luatools.man1.pdf
new file mode 100644
index 00000000000..52b46b6bd83
Binary files /dev/null and b/Master/texmf-dist/doc/man/man1/luatools.man1.pdf differ
diff --git a/Master/texmf-dist/doc/man/man1/mtx-babel.1 b/Master/texmf-dist/doc/man/man1/mtx-babel.1
new file mode 100644
index 00000000000..cd0b007fb3d
--- /dev/null
+++ b/Master/texmf-dist/doc/man/man1/mtx-babel.1
@@ -0,0 +1,33 @@
+.TH "mtx-babel" "1" "01-01-2013" "version 1.20" "Babel Input To UTF Conversion"
+.SH NAME
+.B mtx-babel
+.SH SYNOPSIS
+.B mtxrun --script babel [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B Babel Input To UTF Conversion
+.SH OPTIONS
+.TP
+.B --language=string
+conversion language (e.g. greek)
+.TP
+.B --structure=string
+obey given structure (e.g. 'document', default: 'context')
+.TP
+.B --convert
+convert babel codes into utf
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/man/man1/mtx-babel.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-babel.man1.pdf
new file mode 100644
index 00000000000..aa026870301
Binary files /dev/null and b/Master/texmf-dist/doc/man/man1/mtx-babel.man1.pdf differ
diff --git a/Master/texmf-dist/doc/man/man1/mtx-base.1 b/Master/texmf-dist/doc/man/man1/mtx-base.1
new file mode 100644
index 00000000000..6c72dcb07f1
--- /dev/null
+++ b/Master/texmf-dist/doc/man/man1/mtx-base.1
@@ -0,0 +1,78 @@
+.TH "mtx-base" "1" "01-01-2013" "version 1.35" "ConTeXt TDS Management Tool (aka luatools)"
+.SH NAME
+.B mtx-base
+.SH SYNOPSIS
+.B mtxrun --script base [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B ConTeXt TDS Management Tool (aka luatools)
+.SH OPTIONS
+.TP
+.B --generate
+generate file database
+.TP
+.B --variables
+show configuration variables
+.TP
+.B --configurations
+show configuration order
+.TP
+.B --expand-braces
+expand complex variable
+.TP
+.B --expand-path
+expand variable (resolve paths)
+.TP
+.B --expand-var
+expand variable (resolve references)
+.TP
+.B --show-path
+show path expansion of ...
+.TP
+.B --var-value
+report value of variable
+.TP
+.B --find-file
+report file location
+.TP
+.B --find-path
+report path of file
+.TP
+.B --make
+[or --ini] make luatex format
+.TP
+.B --run
+[or --fmt] run luatex format
+.TP
+.B --compile
+assemble and compile lua inifile
+.TP
+.B --verbose
+give a bit more info
+.TP
+.B --all
+show all found files
+.TP
+.B --format=str
+filter cf format specification (default 'tex', use 'any' for any match)
+.TP
+.B --pattern=str
+filter variables
+.TP
+.B --trackers=list
+enable given trackers
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/man/man1/mtx-base.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-base.man1.pdf
new file mode 100644
index 00000000000..447b9341262
Binary files /dev/null and b/Master/texmf-dist/doc/man/man1/mtx-base.man1.pdf differ
diff --git a/Master/texmf-dist/doc/man/man1/mtx-cache.1 b/Master/texmf-dist/doc/man/man1/mtx-cache.1
new file mode 100644
index 00000000000..26f3793fc2b
--- /dev/null
+++ b/Master/texmf-dist/doc/man/man1/mtx-cache.1
@@ -0,0 +1,36 @@
+.TH "mtx-cache" "1" "01-01-2013" "version 0.10" "ConTeXt &error; MetaTeX Cache Management"
+.SH NAME
+.B mtx-cache
+.SH SYNOPSIS
+.B mtxrun --script cache [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B ConTeXt &error; MetaTeX Cache Management
+.SH OPTIONS
+.TP
+.B --purge
+remove not used files
+.TP
+.B --erase
+completely remove cache
+.TP
+.B --list
+show cache
+.TP
+.B --all
+all (not yet implemented)
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/man/man1/mtx-cache.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-cache.man1.pdf
new file mode 100644
index 00000000000..24ae98e4a16
Binary files /dev/null and b/Master/texmf-dist/doc/man/man1/mtx-cache.man1.pdf differ
diff --git a/Master/texmf-dist/doc/man/man1/mtx-chars.1 b/Master/texmf-dist/doc/man/man1/mtx-chars.1
new file mode 100644
index 00000000000..5d3df23e6a4
--- /dev/null
+++ b/Master/texmf-dist/doc/man/man1/mtx-chars.1
@@ -0,0 +1,33 @@
+.TH "mtx-chars" "1" "01-01-2013" "version 0.10" "MkII Character Table Generators"
+.SH NAME
+.B mtx-chars
+.SH SYNOPSIS
+.B mtxrun --script chars [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B MkII Character Table Generators
+.SH OPTIONS
+.TP
+.B --xtx
+generate xetx-*.tex (used by xetex)
+.TP
+.B --pdf
+generate pdfr-def.tex (used by pdftex)
+.TP
+.B --entities
+generate entities table
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/man/man1/mtx-chars.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-chars.man1.pdf
new file mode 100644
index 00000000000..ff2eca72000
Binary files /dev/null and b/Master/texmf-dist/doc/man/man1/mtx-chars.man1.pdf differ
diff --git a/Master/texmf-dist/doc/man/man1/mtx-check.1 b/Master/texmf-dist/doc/man/man1/mtx-check.1
new file mode 100644
index 00000000000..72e33b088eb
--- /dev/null
+++ b/Master/texmf-dist/doc/man/man1/mtx-check.1
@@ -0,0 +1,27 @@
+.TH "mtx-check" "1" "01-01-2013" "version 0.10" "Basic ConTeXt Syntax Checking"
+.SH NAME
+.B mtx-check
+.SH SYNOPSIS
+.B mtxrun --script check [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B Basic ConTeXt Syntax Checking
+.SH OPTIONS
+.TP
+.B --convert
+check tex file for errors
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/man/man1/mtx-check.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-check.man1.pdf
new file mode 100644
index 00000000000..f8266ee15e3
Binary files /dev/null and b/Master/texmf-dist/doc/man/man1/mtx-check.man1.pdf differ
diff --git a/Master/texmf-dist/doc/man/man1/mtx-colors.1 b/Master/texmf-dist/doc/man/man1/mtx-colors.1
new file mode 100644
index 00000000000..d466b5ea30c
--- /dev/null
+++ b/Master/texmf-dist/doc/man/man1/mtx-colors.1
@@ -0,0 +1,27 @@
+.TH "mtx-colors" "1" "01-01-2013" "version 0.10" "ConTeXt Color Management"
+.SH NAME
+.B mtx-colors
+.SH SYNOPSIS
+.B mtxrun --script colors [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B ConTeXt Color Management
+.SH OPTIONS
+.TP
+.B --table
+show icc table
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/man/man1/mtx-colors.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-colors.man1.pdf
new file mode 100644
index 00000000000..1c96774eee8
Binary files /dev/null and b/Master/texmf-dist/doc/man/man1/mtx-colors.man1.pdf differ
diff --git a/Master/texmf-dist/doc/man/man1/mtx-context.1 b/Master/texmf-dist/doc/man/man1/mtx-context.1
new file mode 100644
index 00000000000..e1fb28a994e
--- /dev/null
+++ b/Master/texmf-dist/doc/man/man1/mtx-context.1
@@ -0,0 +1,167 @@
+.TH "mtx-context" "1" "01-01-2013" "version 0.60" "ConTeXt Process Management"
+.SH NAME
+.B mtx-context
+.SH SYNOPSIS
+.B mtxrun --script context [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B ConTeXt Process Management
+.SH OPTIONS: BASIC
+.TP
+.B --run
+process (one or more) files (default action)
+.TP
+.B --make
+create context formats
+.TP
+.B --ctx=name
+use ctx file (process management specification)
+.TP
+.B --interface
+use specified user interface (default: en)
+.TP
+.B --autopdf
+close pdf file in viewer and start pdf viewer afterwards
+.TP
+.B --purge
+purge files either or not after a run (--pattern=...)
+.TP
+.B --purgeall
+purge all files either or not after a run (--pattern=...)
+.TP
+.B --usemodule=list
+load the given module or style, normally part of the distribution
+.TP
+.B --environment=list
+load the given environment file first (document styles)
+.TP
+.B --mode=list
+enable given the modes (conditional processing in styles)
+.TP
+.B --path=list
+also consult the given paths when files are looked for
+.TP
+.B --arguments=list
+set variables that can be consulted during a run (key/value pairs)
+.TP
+.B --randomseed=number
+set the randomseed
+.TP
+.B --result=name
+rename the resulting output to the given name
+.TP
+.B --trackers=list
+set tracker variables (show list with --showtrackers)
+.TP
+.B --directives=list
+set directive variables (show list with --showdirectives)
+.TP
+.B --silent=list
+disable logcatgories (show list with --showlogcategories)
+.TP
+.B --noconsole
+disable logging to the console (logfile only)
+.TP
+.B --purgeresult
+purge result file before run
+.TP
+.B --forcexml
+force xml stub
+.TP
+.B --forcecld
+force cld (context lua document) stub
+.TP
+.B --forcelua
+force lua stub (like texlua)
+.TP
+.B --forcemp
+force mp stub
+.TP
+.B --arrange
+run extra imposition pass, given that the style sets up imposition
+.TP
+.B --noarrange
+ignore imposition specifications in the style
+.TP
+.B --jit
+use luajittex with jit turned off (only use the faster virtual machine)
+.TP
+.B --jiton
+use luajittex with jit turned on (in most cases not faster, even slower)
+.TP
+.B --once
+only run once (no multipass data file is produced)
+.TP
+.B --batchmode
+run without stopping and do not show messages on the console
+.TP
+.B --nonstopmode
+run without stopping
+.TP
+.B --synctex
+run with synctex enabled (optional value: zipped, unzipped, 1, -1)
+.TP
+.B --generate
+generate file database etc. (as luatools does)
+.TP
+.B --paranoid
+do not descend to .. and ../..
+.TP
+.B --version
+report installed context version
+.TP
+.B --global
+assume given file present elsewhere
+.TP
+.B --nofile
+use dummy file as jobname
+.SH OPTIONS: EXPERT
+.TP
+.B --touch
+update context version number (remake needed afterwards, also provide --expert)
+.TP
+.B --nostatistics
+omit runtime statistics at the end of the run
+.TP
+.B --update
+update context from website (not to be confused with contextgarden)
+.TP
+.B --profile
+profile job (use: mtxrun --script profile --analyze)
+.TP
+.B --timing
+generate timing and statistics overview
+.TP
+.B --extra=name
+process extra (mtx-context-... in distribution)
+.TP
+.B --extras
+show extras
+.SH OPTIONS: SPECIAL
+.TP
+.B --pdftex
+process file with texexec using pdftex
+.TP
+.B --xetex
+process file with texexec using xetex
+.TP
+.B --mkii
+process file with texexec
+.TP
+.B --pipe
+do not check for file and enter scroll mode (--dummyfile=whatever.tmp)
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/man/man1/mtx-context.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-context.man1.pdf
new file mode 100644
index 00000000000..1fe6753ac13
Binary files /dev/null and b/Master/texmf-dist/doc/man/man1/mtx-context.man1.pdf differ
diff --git a/Master/texmf-dist/doc/man/man1/mtx-epub.1 b/Master/texmf-dist/doc/man/man1/mtx-epub.1
new file mode 100644
index 00000000000..518435d1e2b
--- /dev/null
+++ b/Master/texmf-dist/doc/man/man1/mtx-epub.1
@@ -0,0 +1,27 @@
+.TH "mtx-epub" "1" "01-01-2013" "version 0.12" "ConTeXt EPUB Helpers"
+.SH NAME
+.B mtx-epub
+.SH SYNOPSIS
+.B mtxrun --script epub [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B ConTeXt EPUB Helpers
+.SH OPTIONS
+.TP
+.B --make
+create epub zip file
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/man/man1/mtx-epub.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-epub.man1.pdf
new file mode 100644
index 00000000000..f444aadf814
Binary files /dev/null and b/Master/texmf-dist/doc/man/man1/mtx-epub.man1.pdf differ
diff --git a/Master/texmf-dist/doc/man/man1/mtx-fcd.1 b/Master/texmf-dist/doc/man/man1/mtx-fcd.1
new file mode 100644
index 00000000000..43de2a3a4de
--- /dev/null
+++ b/Master/texmf-dist/doc/man/man1/mtx-fcd.1
@@ -0,0 +1,54 @@
+.TH "mtx-fcd" "1" "01-01-2013" "version 1.00" "Fast Directory Change"
+.SH NAME
+.B mtx-fcd
+.SH SYNOPSIS
+.B mtxrun --script fcd [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B Fast Directory Change
+.SH OPTIONS
+.TP
+.B --clear
+clear the cache
+.TP
+.B --clear
+--history [entry] clear the history
+.TP
+.B --scan
+clear the cache and add given path(s)
+.TP
+.B --add
+add given path(s)
+.TP
+.B --find
+find given path (can be substring)
+.TP
+.B --find
+--nohistory find given path (can be substring) but don't use history
+.TP
+.B --stub
+print platform stub file
+.TP
+.B --list
+show roots of cached dirs
+.TP
+.B --list
+--history show history of chosen dirs
+.TP
+.B --help
+show this help
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/man/man1/mtx-fcd.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-fcd.man1.pdf
new file mode 100644
index 00000000000..2809a922631
Binary files /dev/null and b/Master/texmf-dist/doc/man/man1/mtx-fcd.man1.pdf differ
diff --git a/Master/texmf-dist/doc/man/man1/mtx-flac.1 b/Master/texmf-dist/doc/man/man1/mtx-flac.1
new file mode 100644
index 00000000000..ef914f2acff
--- /dev/null
+++ b/Master/texmf-dist/doc/man/man1/mtx-flac.1
@@ -0,0 +1,27 @@
+.TH "mtx-flac" "1" "01-01-2013" "version 0.10" "ConTeXt Flac Helpers"
+.SH NAME
+.B mtx-flac
+.SH SYNOPSIS
+.B mtxrun --script flac [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B ConTeXt Flac Helpers
+.SH OPTIONS
+.TP
+.B --collect
+collect albums in xml file
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/man/man1/mtx-flac.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-flac.man1.pdf
new file mode 100644
index 00000000000..1d1cb8b58cb
Binary files /dev/null and b/Master/texmf-dist/doc/man/man1/mtx-flac.man1.pdf differ
diff --git a/Master/texmf-dist/doc/man/man1/mtx-fonts.1 b/Master/texmf-dist/doc/man/man1/mtx-fonts.1
new file mode 100644
index 00000000000..b576b9de35d
--- /dev/null
+++ b/Master/texmf-dist/doc/man/man1/mtx-fonts.1
@@ -0,0 +1,63 @@
+.TH "mtx-fonts" "1" "01-01-2013" "version 0.21" "ConTeXt Font Database Management"
+.SH NAME
+.B mtx-fonts
+.SH SYNOPSIS
+.B mtxrun --script fonts [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B ConTeXt Font Database Management
+.SH OPTIONS
+.TP
+.B --save
+save open type font in raw table
+.TP
+.B --unpack
+save a tma file in a more readale format
+.TP
+.B --reload
+generate new font database (use --force when in doubt)
+.TP
+.B --reload
+--simple:generate luatex-fonts-names.lua (not for context!)
+.TP
+.B --list
+--name: list installed fonts, filter by name [--pattern]
+.TP
+.B --list
+--spec: list installed fonts, filter by spec [--filter]
+.TP
+.B --list
+--file: list installed fonts, filter by file [--pattern]
+.TP
+.B --pattern=str
+filter files using pattern
+.TP
+.B --filter=list
+key-value pairs
+.TP
+.B --all
+show all found instances (combined with other flags)
+.TP
+.B --info
+give more details
+.TP
+.B --track=list
+enable trackers
+.TP
+.B --statistics
+some info about the database
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/man/man1/mtx-fonts.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-fonts.man1.pdf
new file mode 100644
index 00000000000..b5b1319c13d
Binary files /dev/null and b/Master/texmf-dist/doc/man/man1/mtx-fonts.man1.pdf differ
diff --git a/Master/texmf-dist/doc/man/man1/mtx-grep.1 b/Master/texmf-dist/doc/man/man1/mtx-grep.1
new file mode 100644
index 00000000000..6b86ec75591
--- /dev/null
+++ b/Master/texmf-dist/doc/man/man1/mtx-grep.1
@@ -0,0 +1,36 @@
+.TH "mtx-grep" "1" "01-01-2013" "version 0.10" "Simple Grepper"
+.SH NAME
+.B mtx-grep
+.SH SYNOPSIS
+.B mtxrun --script grep [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B Simple Grepper
+.SH OPTIONS
+.TP
+.B --pattern
+search for pattern (optional)
+.TP
+.B --count
+count matches only
+.TP
+.B --nocomment
+skip lines that start with %% or #
+.TP
+.B --xml
+pattern is lpath expression
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/man/man1/mtx-grep.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-grep.man1.pdf
new file mode 100644
index 00000000000..db1dd5bb518
Binary files /dev/null and b/Master/texmf-dist/doc/man/man1/mtx-grep.man1.pdf differ
diff --git a/Master/texmf-dist/doc/man/man1/mtx-interface.1 b/Master/texmf-dist/doc/man/man1/mtx-interface.1
new file mode 100644
index 00000000000..232451621a6
--- /dev/null
+++ b/Master/texmf-dist/doc/man/man1/mtx-interface.1
@@ -0,0 +1,69 @@
+.TH "mtx-interface" "1" "01-01-2013" "version 0.13" "ConTeXt Interface Related Goodies"
+.SH NAME
+.B mtx-interface
+.SH SYNOPSIS
+.B mtxrun --script interface [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B ConTeXt Interface Related Goodies
+.SH OPTIONS
+.TP
+.B --interfaces
+generate context interface files
+.TP
+.B --messages
+generate context message files
+.TP
+.B --labels
+generate context label files
+.TP
+.B --context
+equals --interfaces --messages --languages
+.TP
+.B --scite
+generate scite interface
+.TP
+.B --bbedit
+generate bbedit interface files
+.TP
+.B --jedit
+generate jedit interface files
+.TP
+.B --textpad
+generate textpad interface files
+.TP
+.B --text
+create text files for commands and environments
+.TP
+.B --raw
+report commands to the console
+.TP
+.B --check
+generate check file
+.TP
+.B --toutf
+replace named characters by utf
+.TP
+.B --preprocess
+preprocess mkvi files to tex files [force,suffix]
+.TP
+.B --suffix
+use given suffix for output files
+.TP
+.B --force
+force action even when in doubt
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/man/man1/mtx-interface.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-interface.man1.pdf
new file mode 100644
index 00000000000..f77c0d123c9
Binary files /dev/null and b/Master/texmf-dist/doc/man/man1/mtx-interface.man1.pdf differ
diff --git a/Master/texmf-dist/doc/man/man1/mtx-metapost.1 b/Master/texmf-dist/doc/man/man1/mtx-metapost.1
new file mode 100644
index 00000000000..9ccaddc9f2d
--- /dev/null
+++ b/Master/texmf-dist/doc/man/man1/mtx-metapost.1
@@ -0,0 +1,39 @@
+.TH "mtx-metapost" "1" "01-01-2013" "version 0.10" "MetaPost to PDF processor"
+.SH NAME
+.B mtx-metapost
+.SH SYNOPSIS
+.B mtxrun --script metapost [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B MetaPost to PDF processor
+.SH OPTIONS
+.TP
+.B --rawmp
+raw metapost run
+.TP
+.B --metafun
+use metafun instead of plain
+.TP
+.B --latex
+force --tex=latex
+.TP
+.B --texexec
+force texexec usage (mkii)
+.TP
+.B --split
+split single result file into pages
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/man/man1/mtx-metapost.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-metapost.man1.pdf
new file mode 100644
index 00000000000..e8a62b94201
--- /dev/null
+++ b/Master/texmf-dist/doc/man/man1/mtx-metapost.man1.pdf
@@ -0,0 +1,110 @@
+%PDF-1.4
+%쏢
+5 0 obj
+<>
+stream
+xUَ6}WܷJIJ&t8cHG=j8#ѽeL{=$%p&֍Ca|sXb(|A)+@r!'!ą)" qM'=ypO8)BK$T#l*I=?Lǵ/O GeEu@ݵeQGv0!IpY@tD$dQ"?oGIz[7Im43zb4$D/!!5@LF_^UjǛO;O`l<,CPޖa6xgnSqȄ틤7{ZMTo!k}f"ӻ0
ŦBs6ymBlLP`E|?&OȪSkR$RjّcĔGGȇWhh}1TZgTlX6ؙPN-f+#l̼buB6x
6|īML*Mg~]u +Ŀ?^&g몪-7zYhU%jk}Uƞ89.].U7x
$U.3/Jt )-7<5]Ngy5\^=,[Te#Bwo~ŗa/l&n)&}XBKb69x.$rqZKmKFN0^%1Zez&!8
+uR'rXꕖZa^r|T(}OCʪ|E-{ #=e>8e0Οx+endstream
+endobj
+6 0 obj
+901
+endobj
+4 0 obj
+<>
+/Contents 5 0 R
+>>
+endobj
+3 0 obj
+<< /Type /Pages /Kids [
+4 0 R
+] /Count 1
+>>
+endobj
+1 0 obj
+<>
+endobj
+7 0 obj
+<>endobj
+11 0 obj
+<>
+endobj
+12 0 obj
+<>
+endobj
+10 0 obj
+<>
+endobj
+9 0 obj
+<>
+endobj
+8 0 obj
+<>
+endobj
+13 0 obj
+<>
+endobj
+14 0 obj
+<>stream
+
+
+
+
+
+2013-04-08T02:39:55+02:00
+2013-04-08T02:39:55+02:00
+groff version 1.22.2
+
+Untitled
+
+
+
+
+
+endstream
+endobj
+2 0 obj
+<>endobj
+xref
+0 15
+0000000000 65535 f
+0000001224 00000 n
+0000003104 00000 n
+0000001165 00000 n
+0000001005 00000 n
+0000000015 00000 n
+0000000986 00000 n
+0000001289 00000 n
+0000001543 00000 n
+0000001478 00000 n
+0000001410 00000 n
+0000001330 00000 n
+0000001360 00000 n
+0000001625 00000 n
+0000001681 00000 n
+trailer
+<< /Size 15 /Root 1 0 R /Info 2 0 R
+/ID [<96EA08B77B0ED8E6BBE37608502BC60A><96EA08B77B0ED8E6BBE37608502BC60A>]
+>>
+startxref
+3258
+%%EOF
diff --git a/Master/texmf-dist/doc/man/man1/mtx-metatex.1 b/Master/texmf-dist/doc/man/man1/mtx-metatex.1
new file mode 100644
index 00000000000..bd67ff4d321
--- /dev/null
+++ b/Master/texmf-dist/doc/man/man1/mtx-metatex.1
@@ -0,0 +1,30 @@
+.TH "mtx-metatex" "1" "01-01-2013" "version 0.10" "MetaTeX Process Management"
+.SH NAME
+.B mtx-metatex
+.SH SYNOPSIS
+.B mtxrun --script metatex [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B MetaTeX Process Management
+.SH OPTIONS
+.TP
+.B --run
+process (one or more) files (default action)
+.TP
+.B --make
+create metatex format(s)
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/man/man1/mtx-metatex.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-metatex.man1.pdf
new file mode 100644
index 00000000000..b62f414af46
Binary files /dev/null and b/Master/texmf-dist/doc/man/man1/mtx-metatex.man1.pdf differ
diff --git a/Master/texmf-dist/doc/man/man1/mtx-modules.1 b/Master/texmf-dist/doc/man/man1/mtx-modules.1
new file mode 100644
index 00000000000..a719c16a077
--- /dev/null
+++ b/Master/texmf-dist/doc/man/man1/mtx-modules.1
@@ -0,0 +1,33 @@
+.TH "mtx-modules" "1" "01-01-2013" "version 1.00" "ConTeXt Module Documentation Generators"
+.SH NAME
+.B mtx-modules
+.SH SYNOPSIS
+.B mtxrun --script modules [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B ConTeXt Module Documentation Generators
+.SH OPTIONS
+.TP
+.B --convert
+convert source files (tex, mkii, mkiv, mp) to 'ted' files
+.TP
+.B --process
+process source files (tex, mkii, mkiv, mp) to 'pdf' files
+.TP
+.B --prep
+use original name with suffix 'prep' appended
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/man/man1/mtx-modules.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-modules.man1.pdf
new file mode 100644
index 00000000000..19ef7232d0f
Binary files /dev/null and b/Master/texmf-dist/doc/man/man1/mtx-modules.man1.pdf differ
diff --git a/Master/texmf-dist/doc/man/man1/mtx-package.1 b/Master/texmf-dist/doc/man/man1/mtx-package.1
new file mode 100644
index 00000000000..af11e6aec01
--- /dev/null
+++ b/Master/texmf-dist/doc/man/man1/mtx-package.1
@@ -0,0 +1,27 @@
+.TH "mtx-package" "1" "01-01-2013" "version 0.10" "Distribution Related Goodies"
+.SH NAME
+.B mtx-package
+.SH SYNOPSIS
+.B mtxrun --script package [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B Distribution Related Goodies
+.SH OPTIONS
+.TP
+.B --merge
+merge 'loadmodule' into merge file
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/man/man1/mtx-package.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-package.man1.pdf
new file mode 100644
index 00000000000..722ca53bc61
Binary files /dev/null and b/Master/texmf-dist/doc/man/man1/mtx-package.man1.pdf differ
diff --git a/Master/texmf-dist/doc/man/man1/mtx-patterns.1 b/Master/texmf-dist/doc/man/man1/mtx-patterns.1
new file mode 100644
index 00000000000..96e3c4d4879
--- /dev/null
+++ b/Master/texmf-dist/doc/man/man1/mtx-patterns.1
@@ -0,0 +1,39 @@
+.TH "mtx-patterns" "1" "01-01-2013" "version 0.20" "ConTeXt Pattern File Management"
+.SH NAME
+.B mtx-patterns
+.SH SYNOPSIS
+.B mtxrun --script patterns [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B ConTeXt Pattern File Management
+.SH OPTIONS
+.TP
+.B --convert
+generate context language files (mnemonic driven, if not given then all)
+.TP
+.B --check
+check pattern file (or those used by context when no file given)
+.TP
+.B --path
+source path where hyph-foo.tex files are stored
+.TP
+.B --destination
+destination path
+.TP
+.B --specification
+additional patterns: e.g.: =cy,hyph-cy,welsh
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/man/man1/mtx-patterns.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-patterns.man1.pdf
new file mode 100644
index 00000000000..20964c47f9e
Binary files /dev/null and b/Master/texmf-dist/doc/man/man1/mtx-patterns.man1.pdf differ
diff --git a/Master/texmf-dist/doc/man/man1/mtx-pdf.1 b/Master/texmf-dist/doc/man/man1/mtx-pdf.1
new file mode 100644
index 00000000000..7ac50df0d63
--- /dev/null
+++ b/Master/texmf-dist/doc/man/man1/mtx-pdf.1
@@ -0,0 +1,33 @@
+.TH "mtx-pdf" "1" "01-01-2013" "version 0.10" "ConTeXt PDF Helpers"
+.SH NAME
+.B mtx-pdf
+.SH SYNOPSIS
+.B mtxrun --script pdf [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B ConTeXt PDF Helpers
+.SH OPTIONS
+.TP
+.B --info
+show some info about the given file
+.TP
+.B --metadata
+show metadata xml blob
+.TP
+.B --fonts
+show used fonts (--detail)
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/man/man1/mtx-pdf.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-pdf.man1.pdf
new file mode 100644
index 00000000000..f5662e8ae4a
Binary files /dev/null and b/Master/texmf-dist/doc/man/man1/mtx-pdf.man1.pdf differ
diff --git a/Master/texmf-dist/doc/man/man1/mtx-profile.1 b/Master/texmf-dist/doc/man/man1/mtx-profile.1
new file mode 100644
index 00000000000..5eba4861aa4
--- /dev/null
+++ b/Master/texmf-dist/doc/man/man1/mtx-profile.1
@@ -0,0 +1,30 @@
+.TH "mtx-profile" "1" "01-01-2013" "version 1.00" "ConTeXt MkIV LuaTeX Profiler"
+.SH NAME
+.B mtx-profile
+.SH SYNOPSIS
+.B mtxrun --script profile [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B ConTeXt MkIV LuaTeX Profiler
+.SH OPTIONS
+.TP
+.B --analyze
+analyze lua calls
+.TP
+.B --trace
+analyze tex calls
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/man/man1/mtx-profile.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-profile.man1.pdf
new file mode 100644
index 00000000000..74f56d7b253
--- /dev/null
+++ b/Master/texmf-dist/doc/man/man1/mtx-profile.man1.pdf
@@ -0,0 +1,117 @@
+%PDF-1.4
+%쏢
+5 0 obj
+<>
+stream
+xUrF+00N)ʇQ@AS7ӃXEr>!JE0h
+(^+]w 8 6FSй19ҒE`51npѼe]Wd!EU&Qo"qpM
+LgaAW/rHSBcaݶ[é8}L0%SgDnx@BycSo4Fێ@x5Dpeγ5O=|(,Y^xZs}s;LO vD:_6B)-IBSM&7SDha.)q( 3O.bx?ۜ;}DQ#)o~O/&-ퟑm!ˠ1?z-酫Rv?fbJW|u{%*(V'`.6=d喂XJwFZӣGĈPwܰ>P S!eٯUUg(/zᚼ*{MKۢ5ϐVU+VmǕ!CO]svډ| ;ECzڻl8J
+F\ͯpHs,FfP@ˑXrA|jH[tJF+&{XyvvԄ詾EfYaI(nW\5ޤc_S.R˞r1|QKLՏYńNc]`>g3͇WU@.ھ>
+/Contents 5 0 R
+>>
+endobj
+3 0 obj
+<< /Type /Pages /Kids [
+4 0 R
+] /Count 1
+>>
+endobj
+1 0 obj
+<>
+endobj
+7 0 obj
+<>endobj
+11 0 obj
+<>
+endobj
+12 0 obj
+<>
+endobj
+10 0 obj
+<>
+endobj
+9 0 obj
+<>
+endobj
+13 0 obj
+<>
+endobj
+8 0 obj
+<>
+endobj
+14 0 obj
+<>
+endobj
+15 0 obj
+<>stream
+
+
+
+
+
+2013-04-08T02:39:54+02:00
+2013-04-08T02:39:54+02:00
+groff version 1.22.2
+
+Untitled
+
+
+
+
+
+endstream
+endobj
+2 0 obj
+<>endobj
+xref
+0 16
+0000000000 65535 f
+0000001111 00000 n
+0000003063 00000 n
+0000001052 00000 n
+0000000892 00000 n
+0000000015 00000 n
+0000000873 00000 n
+0000001176 00000 n
+0000001502 00000 n
+0000001365 00000 n
+0000001297 00000 n
+0000001217 00000 n
+0000001247 00000 n
+0000001446 00000 n
+0000001584 00000 n
+0000001640 00000 n
+trailer
+<< /Size 16 /Root 1 0 R /Info 2 0 R
+/ID [<12D5B0B8D4EEBD69B189A1F1C48BFAD7><12D5B0B8D4EEBD69B189A1F1C48BFAD7>]
+>>
+startxref
+3217
+%%EOF
diff --git a/Master/texmf-dist/doc/man/man1/mtx-rsync.1 b/Master/texmf-dist/doc/man/man1/mtx-rsync.1
new file mode 100644
index 00000000000..5f3bc1fea00
--- /dev/null
+++ b/Master/texmf-dist/doc/man/man1/mtx-rsync.1
@@ -0,0 +1,33 @@
+.TH "mtx-rsync" "1" "01-01-2013" "version 0.10" "Rsync Helpers"
+.SH NAME
+.B mtx-rsync
+.SH SYNOPSIS
+.B mtxrun --script rsync [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B Rsync Helpers
+.SH OPTIONS
+.TP
+.B --job
+use given file as specification
+.TP
+.B --dryrun
+show what would happen
+.TP
+.B --force
+force run
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/man/man1/mtx-rsync.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-rsync.man1.pdf
new file mode 100644
index 00000000000..d9c41f3c033
Binary files /dev/null and b/Master/texmf-dist/doc/man/man1/mtx-rsync.man1.pdf differ
diff --git a/Master/texmf-dist/doc/man/man1/mtx-scite.1 b/Master/texmf-dist/doc/man/man1/mtx-scite.1
new file mode 100644
index 00000000000..118179e9184
--- /dev/null
+++ b/Master/texmf-dist/doc/man/man1/mtx-scite.1
@@ -0,0 +1,27 @@
+.TH "mtx-scite" "1" "01-01-2013" "version 1.00" "Scite Helper Script"
+.SH NAME
+.B mtx-scite
+.SH SYNOPSIS
+.B mtxrun --script scite [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B Scite Helper Script
+.SH OPTIONS
+.TP
+.B --words
+convert spell-*.txt into spell-*.lua
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/man/man1/mtx-scite.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-scite.man1.pdf
new file mode 100644
index 00000000000..28b5b948d02
Binary files /dev/null and b/Master/texmf-dist/doc/man/man1/mtx-scite.man1.pdf differ
diff --git a/Master/texmf-dist/doc/man/man1/mtx-server.1 b/Master/texmf-dist/doc/man/man1/mtx-server.1
new file mode 100644
index 00000000000..18373ad4b1c
--- /dev/null
+++ b/Master/texmf-dist/doc/man/man1/mtx-server.1
@@ -0,0 +1,42 @@
+.TH "mtx-server" "1" "01-01-2013" "version 0.10" "Simple Webserver For Helpers"
+.SH NAME
+.B mtx-server
+.SH SYNOPSIS
+.B mtxrun --script server [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B Simple Webserver For Helpers
+.SH OPTIONS
+.TP
+.B --start
+start server
+.TP
+.B --port
+port to listen to
+.TP
+.B --root
+server root
+.TP
+.B --scripts
+scripts sub path
+.TP
+.B --index
+index file
+.TP
+.B --auto
+start on own path
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/man/man1/mtx-server.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-server.man1.pdf
new file mode 100644
index 00000000000..f6bf45b2fac
--- /dev/null
+++ b/Master/texmf-dist/doc/man/man1/mtx-server.man1.pdf
@@ -0,0 +1,113 @@
+%PDF-1.4
+%쏢
+5 0 obj
+<>
+stream
+xV6}%!$1L6IllRwf<$6xGaaU`^W/6h`(k%E$!}i%8n<c.^Qt"҃g}`ZlBCJ.<&M?5$\ƙ&$p<$m^0Q LbX_l~.l$ƭ#NH6\o\Z%43pNC"NvɝVl(p|l:~}
+1Y(
ft#J`I'RKݢ.^ҚH/Iq"=$6;M04:>OS bx;9qwƏň$of1qȯQn$t[MAyu<}7oh_/o]JHnm٪^?RջKS&;k`QDF0YmZ"]dw{sᶺ·0K|wRgpC&~UG;R=>Ϲv됰a+rε*e~R,{m´>ku}
+{7پ[kJg4e_jJms4q+'&[[s(d@>ټxWil=v@V.hjçp('+asG`fnxPAhVUo#TSJ
+UiAk1ۛp84݃c &d&FH'
vCmy|A%"̮m6Y-aGBrI/!e&NO1%RW\.*3Ի
+bYSNhesH]kU7Vvg݂D(pj? XBY?NYƩ;^$>endstream
+endobj
+6 0 obj
+942
+endobj
+4 0 obj
+<>
+/Contents 5 0 R
+>>
+endobj
+3 0 obj
+<< /Type /Pages /Kids [
+4 0 R
+] /Count 1
+>>
+endobj
+1 0 obj
+<>
+endobj
+7 0 obj
+<>endobj
+11 0 obj
+<>
+endobj
+12 0 obj
+<>
+endobj
+10 0 obj
+<>
+endobj
+9 0 obj
+<>
+endobj
+8 0 obj
+<>
+endobj
+13 0 obj
+<>
+endobj
+14 0 obj
+<>stream
+
+
+
+
+
+2013-04-08T02:39:56+02:00
+2013-04-08T02:39:56+02:00
+groff version 1.22.2
+
+Untitled
+
+
+
+
+
+endstream
+endobj
+2 0 obj
+<>endobj
+xref
+0 15
+0000000000 65535 f
+0000001265 00000 n
+0000003145 00000 n
+0000001206 00000 n
+0000001046 00000 n
+0000000015 00000 n
+0000001027 00000 n
+0000001330 00000 n
+0000001584 00000 n
+0000001519 00000 n
+0000001451 00000 n
+0000001371 00000 n
+0000001401 00000 n
+0000001666 00000 n
+0000001722 00000 n
+trailer
+<< /Size 15 /Root 1 0 R /Info 2 0 R
+/ID [<6167DA2FECF3699F8F1F3F428D8353B0><6167DA2FECF3699F8F1F3F428D8353B0>]
+>>
+startxref
+3299
+%%EOF
diff --git a/Master/texmf-dist/doc/man/man1/mtx-texworks.1 b/Master/texmf-dist/doc/man/man1/mtx-texworks.1
new file mode 100644
index 00000000000..df2d4b84367
--- /dev/null
+++ b/Master/texmf-dist/doc/man/man1/mtx-texworks.1
@@ -0,0 +1,30 @@
+.TH "mtx-texworks" "1" "01-01-2013" "version 1.00" "TeXworks Startup Script"
+.SH NAME
+.B mtx-texworks
+.SH SYNOPSIS
+.B mtxrun --script texworks [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B TeXworks Startup Script
+.SH OPTIONS
+.TP
+.B --start
+[--verbose] start texworks
+.TP
+.B --test
+report what will happen
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/man/man1/mtx-texworks.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-texworks.man1.pdf
new file mode 100644
index 00000000000..360fd07af93
Binary files /dev/null and b/Master/texmf-dist/doc/man/man1/mtx-texworks.man1.pdf differ
diff --git a/Master/texmf-dist/doc/man/man1/mtx-timing.1 b/Master/texmf-dist/doc/man/man1/mtx-timing.1
new file mode 100644
index 00000000000..831ce60eda4
--- /dev/null
+++ b/Master/texmf-dist/doc/man/man1/mtx-timing.1
@@ -0,0 +1,33 @@
+.TH "mtx-timing" "1" "01-01-2013" "version 0.10" "ConTeXt Timing Tools"
+.SH NAME
+.B mtx-timing
+.SH SYNOPSIS
+.B mtxrun --script timing [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B ConTeXt Timing Tools
+.SH OPTIONS
+.TP
+.B --xhtml
+make xhtml file
+.TP
+.B --launch
+launch after conversion
+.TP
+.B --remove
+remove after launching
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/man/man1/mtx-timing.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-timing.man1.pdf
new file mode 100644
index 00000000000..679155e28be
Binary files /dev/null and b/Master/texmf-dist/doc/man/man1/mtx-timing.man1.pdf differ
diff --git a/Master/texmf-dist/doc/man/man1/mtx-tools.1 b/Master/texmf-dist/doc/man/man1/mtx-tools.1
new file mode 100644
index 00000000000..f56b27bde55
--- /dev/null
+++ b/Master/texmf-dist/doc/man/man1/mtx-tools.1
@@ -0,0 +1,63 @@
+.TH "mtx-tools" "1" "01-01-2013" "version 1.01" "Some File Related Goodies"
+.SH NAME
+.B mtx-tools
+.SH SYNOPSIS
+.B mtxrun --script tools [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B Some File Related Goodies
+.SH OPTIONS
+.TP
+.B --disarmutfbomb
+remove utf bomb if present
+.TP
+.B --force
+remove indeed
+.TP
+.B --dirtoxml
+glob directory into xml
+.TP
+.B --pattern
+glob pattern (default: *)
+.TP
+.B --url
+url attribute (no processing)
+.TP
+.B --root
+the root of the globbed path (default: .)
+.TP
+.B --output
+output filename (console by default)
+.TP
+.B --recurse
+recurse into subdirecories
+.TP
+.B --stripname
+take pathpart of given pattern
+.TP
+.B --longname
+set name attributes to full path name
+.TP
+.B --pattern
+glob pattern (default: *)
+.TP
+.B --recurse
+recurse into subdirecories
+.TP
+.B --force
+downcase indeed
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/man/man1/mtx-tools.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-tools.man1.pdf
new file mode 100644
index 00000000000..715534fecd1
Binary files /dev/null and b/Master/texmf-dist/doc/man/man1/mtx-tools.man1.pdf differ
diff --git a/Master/texmf-dist/doc/man/man1/mtx-unzip.1 b/Master/texmf-dist/doc/man/man1/mtx-unzip.1
new file mode 100644
index 00000000000..5e1a369b2f7
--- /dev/null
+++ b/Master/texmf-dist/doc/man/man1/mtx-unzip.1
@@ -0,0 +1,33 @@
+.TH "mtx-unzip" "1" "01-01-2013" "version 0.10" "Simple Unzipper"
+.SH NAME
+.B mtx-unzip
+.SH SYNOPSIS
+.B mtxrun --script unzip [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B Simple Unzipper
+.SH OPTIONS
+.TP
+.B --list
+list files in archive
+.TP
+.B --junk
+flatten unzipped directory structure
+.TP
+.B --extract
+extract files
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/man/man1/mtx-unzip.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-unzip.man1.pdf
new file mode 100644
index 00000000000..551f2e05952
--- /dev/null
+++ b/Master/texmf-dist/doc/man/man1/mtx-unzip.man1.pdf
@@ -0,0 +1,111 @@
+%PDF-1.4
+%쏢
+5 0 obj
+<>
+stream
+xUMs0+ޭp, ,PNMSwNb1i'AMbr7Lf3bj~){5$sz!L!4$ODf>ďN]F!dg9ḟxޠU']ܹq-ʋܧ)'M*n,zJhD03
+ 2<Z$(bp/AU5}.I/p@0H/
+<9]=%(U-2]h. S"~{tcWЏvlK8AMӽep웘~
u_31w2(C}^V>gq떀'&w#4OF]`)s4Y&i6ʫn8Lw_ qd-BO
*b&0IK
K]*Ug'R&W)~fLMXEUE鋌6eӛ=!hC]w0CvnˢT,2:-̡<+
gE{!1U?4|z@|iI
I)Xz!sxPXPnwf8e:}p}h(&z"ʣa,|=i803U~س{Vnf0L]h̘-V9U'$Sw,J9$2ܘ,r7X|4իv;s88$קfS2ƙ+ˉwEzм3GݯvY"@EYcA1|>Pws>
+/Contents 5 0 R
+>>
+endobj
+3 0 obj
+<< /Type /Pages /Kids [
+4 0 R
+] /Count 1
+>>
+endobj
+1 0 obj
+<>
+endobj
+7 0 obj
+<>endobj
+11 0 obj
+<>
+endobj
+12 0 obj
+<>
+endobj
+10 0 obj
+<>
+endobj
+9 0 obj
+<>
+endobj
+8 0 obj
+<>
+endobj
+13 0 obj
+<>
+endobj
+14 0 obj
+<>stream
+
+
+
+
+
+2013-04-08T02:39:51+02:00
+2013-04-08T02:39:51+02:00
+groff version 1.22.2
+
+Untitled
+
+
+
+
+
+endstream
+endobj
+2 0 obj
+<>endobj
+xref
+0 15
+0000000000 65535 f
+0000001108 00000 n
+0000002991 00000 n
+0000001049 00000 n
+0000000889 00000 n
+0000000015 00000 n
+0000000870 00000 n
+0000001173 00000 n
+0000001427 00000 n
+0000001362 00000 n
+0000001294 00000 n
+0000001214 00000 n
+0000001244 00000 n
+0000001509 00000 n
+0000001568 00000 n
+trailer
+<< /Size 15 /Root 1 0 R /Info 2 0 R
+/ID []
+>>
+startxref
+3145
+%%EOF
diff --git a/Master/texmf-dist/doc/man/man1/mtx-update.1 b/Master/texmf-dist/doc/man/man1/mtx-update.1
new file mode 100644
index 00000000000..72e7ce1b5ae
--- /dev/null
+++ b/Master/texmf-dist/doc/man/man1/mtx-update.1
@@ -0,0 +1,78 @@
+.TH "mtx-update" "1" "01-01-2013" "version 0.31" "ConTeXt Minimals Updater"
+.SH NAME
+.B mtx-update
+.SH SYNOPSIS
+.B mtxrun --script update [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B ConTeXt Minimals Updater
+.SH OPTIONS
+.TP
+.B --platform=string
+platform (windows, linux, linux-64, osx-intel, osx-ppc, linux-ppc)
+.TP
+.B --server=string
+repository url (rsync://contextgarden.net)
+.TP
+.B --module=string
+repository url (minimals)
+.TP
+.B --repository=string
+specify version (current, experimental)
+.TP
+.B --context=string
+specify version (current, latest, beta, yyyy.mm.dd)
+.TP
+.B --rsync=string
+rsync binary (rsync)
+.TP
+.B --texroot=string
+installation directory (not guessed for the moment)
+.TP
+.B --engine=string
+tex engine (luatex, pdftex, xetex)
+.TP
+.B --modules=string
+extra modules (can be list or 'all')
+.TP
+.B --fonts=string
+additional fonts (can be list or 'all')
+.TP
+.B --goodies=string
+extra binaries (like scite and texworks)
+.TP
+.B --force
+instead of a dryrun, do the real thing
+.TP
+.B --update
+update minimal tree
+.TP
+.B --make
+also make formats and generate file databases
+.TP
+.B --keep
+don't delete unused or obsolete files
+.TP
+.B --state
+update tree using saved state
+.TP
+.B --cygwin
+adapt drive specs to cygwin
+.TP
+.B --mingw
+assume mingw binaries being used
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/man/man1/mtx-update.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-update.man1.pdf
new file mode 100644
index 00000000000..a21271c505f
Binary files /dev/null and b/Master/texmf-dist/doc/man/man1/mtx-update.man1.pdf differ
diff --git a/Master/texmf-dist/doc/man/man1/mtx-watch.1 b/Master/texmf-dist/doc/man/man1/mtx-watch.1
new file mode 100644
index 00000000000..9f4a0d3b9d7
--- /dev/null
+++ b/Master/texmf-dist/doc/man/man1/mtx-watch.1
@@ -0,0 +1,48 @@
+.TH "mtx-watch" "1" "01-01-2013" "version 1.00" "ConTeXt Request Watchdog"
+.SH NAME
+.B mtx-watch
+.SH SYNOPSIS
+.B mtxrun --script watch [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B ConTeXt Request Watchdog
+.SH OPTIONS
+.TP
+.B --logpath
+optional path for log files
+.TP
+.B --watch
+watch given path [--delay]
+.TP
+.B --pipe
+use pipe instead of execute
+.TP
+.B --delay
+delay between sweeps
+.TP
+.B --automachine
+replace /machine/ in path /servername/
+.TP
+.B --collect
+condense log files
+.TP
+.B --cleanup=delay
+remove files in given path [--force]
+.TP
+.B --showlog
+show log data
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/man/man1/mtx-watch.man1.pdf b/Master/texmf-dist/doc/man/man1/mtx-watch.man1.pdf
new file mode 100644
index 00000000000..fe08191c9ff
Binary files /dev/null and b/Master/texmf-dist/doc/man/man1/mtx-watch.man1.pdf differ
diff --git a/Master/texmf-dist/doc/man/man1/mtxrun.1 b/Master/texmf-dist/doc/man/man1/mtxrun.1
new file mode 100644
index 00000000000..212097ff153
--- /dev/null
+++ b/Master/texmf-dist/doc/man/man1/mtxrun.1
@@ -0,0 +1,147 @@
+.TH "mtxrun" "1" "01-01-2013" "version 1.31" "ConTeXt TDS Runner Tool"
+.SH NAME
+.B mtxrun
+.SH SYNOPSIS
+.B mtxrun [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B ConTeXt TDS Runner Tool
+.SH OPTIONS
+.TP
+.B --script
+run an mtx script (lua prefered method) (--noquotes), no script gives list
+.TP
+.B --execute
+run a script or program (texmfstart method) (--noquotes)
+.TP
+.B --resolve
+resolve prefixed arguments
+.TP
+.B --ctxlua
+run internally (using preloaded libs)
+.TP
+.B --internal
+run script using built in libraries (same as --ctxlua)
+.TP
+.B --locate
+locate given filename in database (default) or system (--first --all --detail)
+.TP
+.B --autotree
+use texmf tree cf. env texmfstart_tree or texmfstarttree
+.TP
+.B --tree=pathtotree
+use given texmf tree (default file: setuptex.tmf)
+.TP
+.B --environment=name
+use given (tmf) environment file
+.TP
+.B --path=runpath
+go to given path before execution
+.TP
+.B --ifchanged=filename
+only execute when given file has changed (md checksum)
+.TP
+.B --iftouched=old,new
+only execute when given file has changed (time stamp)
+.TP
+.B --makestubs
+create stubs for (context related) scripts
+.TP
+.B --removestubs
+remove stubs (context related) scripts
+.TP
+.B --stubpath=binpath
+paths where stubs wil be written
+.TP
+.B --windows
+create windows (mswin) stubs
+.TP
+.B --unix
+create unix (linux) stubs
+.TP
+.B --verbose
+give a bit more info
+.TP
+.B --trackers=list
+enable given trackers
+.TP
+.B --progname=str
+format or backend
+.TP
+.B --edit
+launch editor with found file
+.TP
+.B --launch
+launch files like manuals, assumes os support (--all)
+.TP
+.B --timedrun
+run a script and time its run
+.TP
+.B --autogenerate
+regenerate databases if needed (handy when used to run context in an editor)
+.TP
+.B --usekpse
+use kpse as fallback (when no mkiv and cache installed, often slower)
+.TP
+.B --forcekpse
+force using kpse (handy when no mkiv and cache installed but less functionality)
+.TP
+.B --prefixes
+show supported prefixes
+.TP
+.B --generate
+generate file database
+.TP
+.B --variables
+show configuration variables
+.TP
+.B --configurations
+show configuration order
+.TP
+.B --directives
+show (known) directives
+.TP
+.B --trackers
+show (known) trackers
+.TP
+.B --experiments
+show (known) experiments
+.TP
+.B --expand-braces
+expand complex variable
+.TP
+.B --expand-path
+expand variable (resolve paths)
+.TP
+.B --expand-var
+expand variable (resolve references)
+.TP
+.B --show-path
+show path expansion of ...
+.TP
+.B --var-value
+report value of variable
+.TP
+.B --find-file
+report file location
+.TP
+.B --find-path
+report path of file
+.TP
+.B --pattern=string
+filter variables
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
+
+
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
+
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/man/man1/mtxrun.man1.pdf b/Master/texmf-dist/doc/man/man1/mtxrun.man1.pdf
new file mode 100644
index 00000000000..5ed7141e9f4
Binary files /dev/null and b/Master/texmf-dist/doc/man/man1/mtxrun.man1.pdf differ
diff --git a/Master/texmf-dist/doc/man/man1/pstopdf.1 b/Master/texmf-dist/doc/man/man1/pstopdf.1
index 972f364cb19..71786ce8b79 100644
--- a/Master/texmf-dist/doc/man/man1/pstopdf.1
+++ b/Master/texmf-dist/doc/man/man1/pstopdf.1
@@ -1,75 +1,30 @@
-.TH "PSTOPDF" "1" "December 2006" "pstopdf 2.0" "ConTeXt"
-.de URL
-\\$2 \(laURL: \\$1 \(ra\\$3
-..
-.if \n[.g] .mso www.tmac
-.de EX
-.in +3
-.nf
-.ft CW
-..
-.de EE
-.in -3
-.ft R
-.fi
-..
-
-.SH "NAME"
-pstopdf \- convert EPS to PDF
-
-.SH "SYNOPSIS"
-\fBpstopdf\fP [ \fIOPTION\fP ... ] \fIFILE\fP [ ... ]
-
-.SH "DESCRIPTION"
-
-\fBpstopdf\fP converts EPS (encapsulated PostScript) to PDF.
-
+.TH "pstopdf" "1" "01-01-2013" "version 2.0.1" "PStoPDF"
+.SH NAME
+.B pstopdf
+.SH SYNOPSIS
+.B pstopdf [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B PStoPDF
.SH OPTIONS
.TP
-.B --help
-Print usage and version information.
-.TP
-.B --convert
-Convert EPS to PDF. This option is assumed if none is given.
-.TP
-.BI --method=\fIstring\fP
-What method to use for bounding boxes when converting to PDF.
-Specify one of \fBcrop\fP, \fBbounded\fP (the default), or \fBraw\fP.
-Older versions of ConTeXt used numerical methods (1, 2, or 3).
-.TP
-.BI --resolution=\fIstring\fP
-The resolution to use when when converting to pdf.
-Specify one of \fBlow\fP, \fBnormal\fP, \fBmedium\fP, \fBhigh\fP,
-\fBprinter\fP, \fBprint\fP, \fBscreen\fP, \fBebook\fP, or
-\fBdefault\fP.
-.TP
.B --request
-Handle exa request file.
+handles exa request file
.TP
.B --watch
-Watch folders for conversions (\fIuntested\fP).
-
-.SH EXAMPLES
+watch folders for conversions (untested)
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
-To make \fIcow.pdf\fP:
-.EX
-pstopdf cow.eps
-.EE
-or (one of several equivalents):
-.EX
-pstopdf --convert cow.eps cow.pdf
-.EE
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
-.SH "SEE ALSO"
-.PP
-.BR epstopdf (1),
-.BR mptopdf (1),
-.BR ps2pdf (1),
-.BR texexec (1).
-.PP
-.URL "http://www.contextgarden.net" "ConTeXt wiki" .
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
-.SH "AUTHOR"
-This (incomplete) manual page was written by Sanjoy Mahajan
-. It is in the public domain.
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/man/man1/texexec.1 b/Master/texmf-dist/doc/man/man1/texexec.1
index 19f56dab96b..54213a30776 100644
--- a/Master/texmf-dist/doc/man/man1/texexec.1
+++ b/Master/texmf-dist/doc/man/man1/texexec.1
@@ -1,602 +1,72 @@
-.TH "TEXEXEC" "1" "December 2006" "texexec 6.2" "ConTeXt"
-.de URL
-\\$2 \(laURL: \\$1 \(ra\\$3
-..
-.if \n[.g] .mso www.tmac
-.de EX
-.in +3
-.nf
-.ft CW
-..
-.de EE
-.in -3
-.ft R
-.fi
-..
-
-.SH "NAME"
-texexec \- front end to the ConTeXt typesetting system
-
-.SH "SYNOPSIS"
-\fBtexexec\fP [ \fIOPTION\fP ... ] \fIFILE\fP [ ... ]
-
-.SH "DESCRIPTION"
-
-\fBtexexec\fP, a \fBruby\fP(1) script,
-is the command-line front end to the ConTeXt typesetting
-system, an extensive macro package
-built on the \fBtex\fP(1) family of typesetting programs.
-\fBtexexec\fP provides several facilties:
-.IP \(bu
-Process a ConTeXt source file,
-performing as many runs as
-necessary of \fBtex\fP(1), \fBtexutil\fP(1), and
-MetaPost (\fBmpost\fP(1)). Options control the output
-format, the pages to process, paper size, and so forth.
-.IP \(bu
-Create new ConTeXt formats, useful during installation.
-.IP \(bu
-Post-process existing PDF files, including merging multiple
-files, and extracting and rearranging pages within a file,
-similar to the facilities provided for PostScript files by
-\fBpsnup\fP(1) or for PDF files by \fBpdftk\fP(1).
-.IP \(bu
-Extract or strip documentation from ConTeXt source files
-using \fBtexutil\fP(1).
-.IP \(bu
-Run MetaPost (\fBmpost\fP(1)) to generate figures from MetaPost source.
-.IP \(bu
-Produce proof sheets of figures used in a ConTeXt source file.
-.IP
-.SH "OPTIONS"
-
-All switches are specified in full here but can be abbreviated to the
-shortest unique prefix. Thus, \fB--env\fP works the same as
-\fB--environment\fP. With no options, \fBtexexec\fP assumes that
-the file on the command line is a ConTeXt source file, i.e. a TeX file
-in the ConTeXt dialect, and produces a PDF file using the source file.
-
-.SS "General Options"
-
-.IP "\fB--alone\fP"
-Avoid calling other programs when possible. For
-example, \fB--alone\fP will prevent \fBtexexec\fP from
-using \fBfmtutil\fP(1) to generate formats (this prevention can
-be handy when tracing installation problems).
-.IP "\fB--environments\fP\fI=\fP\fIfile[,file[,...]]\fP"
-Specify ConTeXt environment file(s), separated by commas, to use when
-processing the source file. This option is useful when converting
-from non-ConTeXt file formats without environment or layout settings.
-.IP "\fB--help\fP"
-Produce a summary of switches
-and arguments. A more detailed help is produced by including
-\fB--all\fP.
-.IP "\fB--interface=\fP\fIlanguage\fP"
-Specify the language
-ConTeXt should use to communicate with you.
-Options are
-.IP
-.RS
-.IP "\fBen\fP"
-US English
-.IP "\fBnl\fP"
-Dutch
-.IP "\fBde\fP"
-German
-.IP "\fBuk\fP"
-British English
-.IP "\fBcz\fP"
-Czech
-.IP "\fBit\fP"
-Italian
-.RE
-.IP "\fB--keep\fP"
-Preserve a few of the temporary files generated while processing by
-appending \fI.keep\fP to their name. For example, after
-.EX
-texexec --keep document.tex
-.EE
-you will find (besides \fIdocument.pdf\fP) \fIdocument.log.keep\fP
-and \fIdocument.top.keep\fP. The \fIdocument.top\fP file is where
-\fBtexexec\fP wraps \fIdocument.tex\fP with the proper ConTeXt macro
-commands to set the output format, etc.
-.IP "\fB--once\fP"
-Process a file exactly once. (By default,
-\fBtexexec\fP processes the file as many times as
-necessary to sort out all references, typeset
-\fBMetaPost\fP code, and so forth.)
-.IP "\fB--purge\fP"
-Get rid of most temporary files generated while processing the source
-file. For example,
-.EX
-texexec --purge somefile.tex
-.EE
-will generate \fIsomefile.pdf\fP, cleaning up after itself and leaving
-only one extra file, \fIsomefile.tuo\fP. See also the \fB--purge\fP
-option of
-.BR ctxtools (1)
-.IP "\fB--purgeall\fP"
-Get rid of all temporary files generated while processing the source
-file, including the \fIfilename.tuo\fP file. See also the \fB--purge
---all\fP option combination of
-.BR ctxtools (1)
-.IP "\fB--randomseed=\fP\fINNNN\fP"
-Set the random seed.
-.IP "\fB--result=\fP\fIFILENAME\fP"
-Allows you to change the
-basename of the output file. See
-\fB--mode\fP for an example.
-.IP "\fB--runs=\fP\fINUMBER\fP"
-Specify the number of runs to
-perform on a file. Overrides
-\fBtexexec\fP's calculations.
-.IP "\fB--separation\fP"
-Perform color separations.
-.IP "\fB--silent\fP"
-Suppress a few diagnostic and progress messages.
-.IP "\fB--timeout=\fP\fINNN\fP"
-Abort the run if a subprocess waits for more than \fINNN\fP seconds;
-e.g. while waiting for user input when \fBtex\fP reports an undefined
-control sequence. Useful for automated testing scripts, to make sure
-the runs finish.
-.IP "\fB--usemodules=\fP\fImodule1[,module2,[...]]\fP
-Use the comma-separated list of modules. For example, to typeset
-\fIdocument.tex\fP using the \fIbib\fP and \fIunits\fP modules:
-.EX
-texexec --usemodules=bib,units document.tex
-.EE
-.IP "\fB--verbose\fP"
-Output extra diagnostic information.
-.IP "\fB--version\fP"
-Print the version number.
-.IP
-
-.SS "Processing ConTeXt Source Files"
-
-Including specifying paper sizes, formats, and so forth.
-
-.IP "\fB--arrange\fP"
-Perform page rearrangements, which are used to produce booklets. This
-option tells ConTeXt to the first \fIn\fP-1 runs without taking
-account of arrangements, then on the last run to pay attention to
-the arrangement commands in the source file.
-.IP "\fB--batchmode\fP"
-Process the file in batchmode, which means
-to typeset the whole document even if there are errors. More
-imformation about \f(CWbatchmode\fP can be found in Donald
-E. Knuth's \fITeXbook\fP.
-.IP "\fB--nonstopmode\fP"
-Process the file in nonstopmode, which means
-to typeset the document and report errors, but not to stop at any
-error. It is similar to batchmode but more verbose. More
-imformation about \f(CWnonstopmode\fP can be found in Donald
-E. Knuth's \fITeXbook\fP.
-.IP "\fB--bodyfont=\fP\fIfont\fP"
-The name of a font to preload for use in
-setting the body of the text (OBSOLETE).
-.IP "\fB--centerpage\fP"
-Center the document on the page.
-.IP "\fB--color\fP"
-Turn on color mode. Color mode can also be set by
-commands embedded in the document. These commands
-override the \fB--color\fP option.
-.IP "\fB--convert=\fP\fIFORMAT\fP"
-Convert the input file to
-ConTeXt format from \fIFORMAT\fP before
-processing. In most cases, this conversion will result
-in a TeX file. Currently supported input
-\fIFORMAT\fPs are \fBxml\fP and
-\fBsgml\fP.
-.IP "\fB--dvipdfmx, --dvipdfm, --dpx, --dpm\fP"
-Use the TeX engine (e.g. \fBpdftex\fP or \fBpdfetex\fP)
-to make a DVI file and \fBdvipdfmx\fP(1) to turn it
-into PDF.
-.IP "\fB--dvi, --ps, --dvips\fP"
-Use the TeX engine (e.g. \fBpdftex\fP or \fBpdfetex\fP)
-to make a DVI file and \fBdvips\fP(1) to turn it
-into PostScript. It's counterintuitive that \fB--dvi\fP produces
-a PostScript file in addition to the DVI file. But that's because
-\fB--dvi\fP is shorthand for \fB--dvips\fP; adding the \fB--nobackend\fP
-option prevents \fBtexexec\fP's running \fBdvips\fP(1). See also the
-\fB--engine\fP option.
-.IP "\fB--fast\fP"
-Typeset the document(s) as fast as possible without
-causing problems.
-.IP "\fB--final\fP"
-Perform a final run without skipping anything.
-This option is typically used with \fB--fast\fP.
-.IP "\fB--language=\fP\fILANGUAGE\fP"
-Set the language for
-hyphenation. Can be specified in your source file.
-Options are the same as those for \fB--interface\fP.
-.IP "\fB--mode=\fP\fIMODELIST\fP, \fB--modes=\fP\fIMODELIST\fP"
-Allows you to change the mode used while typesetting the
-source file. The \fIMODELIST\fP is a comma separated list of modes.
-Modes are a conditional-compilation facility
-like \f(CW#ifdef\fP in C. So one source file can be used to produce
-several typeset documents: one for A4 paper, one for
-screen display in full color, one for letter paper, etc. For
-example:
-.IP
-.EX
-\f(CWtexexec --pdf --mode=A4 --result=manual-a manual-t.tex\fP
-\f(CWtexexec --pdf --mode=letter --result=manual-l manual-t.tex\fP
-\f(CWtexexec --pdf --mode=screen --result=manual-s manual-t.tex\fP
-.EE
-.IP
-Here the \fB--mode\fP tells ConTeXt which
-mode directives to use when typesetting the source file. The
-\fB--result\fP option tells ConTeXt
-where to put the output file.
-.IP "\fB--modefile=\fP\fIfile\fP"
-Load this file before most of the usual processing; usually used for
-mode-related material.
-.IP "\fB--noarrange\fP"
-Ignore arrangement commands in the source file.
-.IP "\fB--nobackend\fP"
-Do not run the backend, e.g. \fBdvips\fP(1) or \fBdvipdfmx\fP(1). See
-the \fB--dvips\fP or \fB--dvipdfmx\fP options. Why would you give one
-of those options to choose a backend, yet tell \fBtexexec\fP not to
-run the backend? Because each backend has its own syntax for
-\f(CW\\special\fP calls. Specifying the backend allows the ConTeXt
-macros to use the correct syntax so that when you later run the
-backend to produce PostScript or PDF, the specials will be interpreted
-correctly.
-.IP "\fB--pages=\fP\fIPAGENUMBERLIST\fP"
-Specify the pages or page
-range to appear in the output file.
-\fIPAGENUMBERLIST\fP may be the keyword \fBodd\fP
-or \fBeven\fP; or one or more pages or page ranges separated by commas.
-For example,
-.EX
-\f(CWtexexec --pages=1,7,8-11,14 somefile.tex\fP
-.EE
-.IP "\fB--paperformat=\fP\fIKEY\fP"
-For typesetting multiple pages on a
-single piece of paper. \fIKEY\fP has the form \fBa4a3\fP
-(for printing A4 pages on A3 paper), \fBa5a4\fP
-(for printing A5 pages on A4 paper), or in general \fBaMaN\fP.
-The actual layout of the pages is specified with the
-\fB--printformat\fP option.
-.IP "\fB--pdf, --pdftex\fP"
-Use \fBpdftex\fP(1) to produce a pdf document (the default).
-.IP "\fB--printformat=\fP\fIKEY\fP"
-Specify the layout of the final
-output. \fIKEY\fP can be \fBup\fP, resulting in 2
-pages per sheet, double sided; or \fBdown\fP, resulting
-in 2 rotated pages per sheet, double sided. Use the
-\fB--paperformat\fP option to specify the original page
-and sheet size.
-.IP "\fB--utfbom\fP"
-Turn on UTF-8 encoding.
-.IP "\fB--xetex, --xtx\fP"
-Use \fBxetex\fP(1) to produce a pdf document.
-.IP
-
-.SS "Creating ConTeXt Format Files"
-
-.IP "\fB--make\fP"
-Generate a ConTeXt format file. For example, to make
-\fIcont-en.fmt\fP and have it placed in a default format directory:
-.EX
-texexec --make de
-.EE
-The most common invocation, which is used by scripts that install a new version
-of ConTeXt (see \fBctxtools\fP(1)), uses \fB--all\fP
-so that \fBtexexec\fP makes the usual formats:
-.EX
-texexec --make --all
-.EE
-.IP "\fB--local\fP"
-When searching for TeX or MetaPost formats, look in the current directory
-rather than in the location set by the kpse library. See
-.BR kpathsea (1)
-for more information on path searching.
-.IP "\fB--check\fP"
-Check and report information about the ConTeXt version, the
-distribution, the TeX engine, and the language interfaces/formats.
-
-.SS "Expert options"
-
-You should know what you're doing if you use these options!
-.IP "\fB--alpha"
-Use the TEXMFALPHA environment variable to find and
-run an alpha release of ConTeXt.
-.IP "\fB--beta"
-Use the TEXMFBETA environment variable to find and
-run a beta release of ConTeXt.
-.IP "\fB--distribution\fP\fI=dist\fP"
-Usually one of \fBstandard\fP, \fBweb2c\fP, or \fBmiktex\fP.
-\fBtexexec\fP should figure it out automatically, and you shouldn't
-need to use this option.
-.IP "\fB--engine\fP\fI=texengine\fP"
-Specify the program to do the hard work of typesetting. Currently
-either \fBpdftex\fP (the default), \fBxetex\fP, or \fBaleph\fP.
-The \fBluatex\fP value is experimental. The \fB--engine\fP
-option is not usually needed. Instead, let
-\fBtexexec\fP figure out the setting based on other command-line
-information. See for example the \fB--xetex\fP or \fB--pdf\fP
-switches.
-
-.SS "Postprocess PDF Files"
-
-.IP "\fB--combination=\fP\fIROWS\fP\fB*\fP\fICOLS\fP"
-Specify the number of pages to show on a single page. Use with
-\fB--pdfcombine\fP.
-.IP "\fB--pdfarrange\fP"
-For rearranging pages in PDF files.
-.EX
-\f(CWtexexec --pdfarrange --paperformat=a5a4 --printformat=up foo.pdf\fP
-.EE
-This command creates an A5 booklet from a PDF file
-\fIfoo.pdf\fP. \fB--pdfarrange\fP is used in
-conjunction with the following options.
-.IP "\fB--pdfcopy\fP"
-Copy and perhaps process pages from the pdf file.
-The resulting file is \fItexexec.pdf\fP by default, but you can change
-that using \fB--result\fP. Use the \fB--scale\fP option to magnify or
-demagnify the original pages and the \fB--pages\fP option to select
-the pages to copy. Here is an example using all these options:
-.EX
-texexec --pages=4-7 --pdfcopy --scale=750 --result=one images.pdf
-.EE
-It takes pages 4-7 from \fIimages.pdf\fP, scales them by 75%,
-and copies them to \fIone.pdf\fP.
-.IP "\fB--scale=\fP\fIinteger\fP"
-If the integer is less than 10, then it is taken as an (integer)
-magnification factor. Otherwise, it is taken as a magnification
-factor in TeX terms, i.e. with 1000 meaning full scale.
-.IP "\fB--paperoffset=\fP\fIdimen\fP"
-Specify the space between the
-edge of the pages and the beginning of the text block.
-.IP "\fB--backspace=\fP\fIdimen\fP"
-Specify the inside (gutter) margins.
-.IP "\fB--topspace=\fP\fIdimen\fP"
-Specify the top and bottom margin.
-.IP "\fB--markings\fP"
-Add crop marks.
-.IP "\fB--addempty=\fP\fIPAGES\fP"
-Add empty pages after the pages specified in \fIPAGES\fP. (Useful
-for, among other things, adding blank pages after a table of
-contents.)
-.IP "\fB--textwidth=\fP\fIWIDTH\fP"
-Set the width of
-the original text. Specifying this parameter with a
-single-sided original will allow ConTeXt to adjust
-the page layout for double-sided output, producing much
-more attractive results.
-
-With the \fB--pdfarrange\fP flag, specifying more
-than one file will result in all of the files being
-combined in the final result, allowing you to add title
-pages, decorated part separators, and so forth.
-
-You can also do more complex manipulations, such as
-adding additional text to the page by setting up a
-small file with layout definitions and a simple figure
-insertion loop.
-.IP "\fB--pdfcombine\fP"
-Combine multiple pages. Requires the \fB--combination\fP option.
-.IP "\fB--pdfselect\fP"
-Extract pages from a file. Use in combination with the
-\fB--selection\fP switch, as in
-.EX
-\f(CWtexexec --pdfselect --paperformat=S6
---selection=1,9,14 file-1\fP
-.EE
-which extracts pages 1, 9, and 14 from
-\fIfile-1.pdf\fP, and places them in
-\fItexexec.pdf\fP (the default output filename if
-an output file isn't specified).
-
-See \fB--pdfarrange\fP for other
-options.
-.IP "\fB--selection=\fP\fIPAGES\fP"
-Specify pages to be affected by
-another option. See \fB--pdfarrange\fP and
-\fB--pdfselect\fP for examples.
-
-.SS "XML handling"
-.IP "\fB--filters=\fP\fIfilter1[,filter2[,...]]\fP
-Specify XML filters to use.
-
-.SS "Extract or Strip Out Documentation"
-
-.IP "\fB--listing\fP"
-Produce a typeset version of the source code in
-\fIFILE\fP. You can specify the format of the output
-file. For example, use
-.EX
-\f(CWtexexec --ps --listing readme.now\fP
-.EE
-to produce a PostScript file called
-\fItexexec.ps\fP.
-
-See also \fB--backspace\fP, \fB--topspace\fP, and \fB--result\fP.
-.IP "\fB--module\fP"
-Create documentation for ConTeXt,
-MetaPost (see \fBmpost\fP(1)),
-.BR perl (1),
-and
-.BR ruby (1)
-modules.
-Converts the documentation to ConTeXt format and
-then typesets a documentated version of the source file.
-
-Documentation lines in ConTeXt source files are
-specified by beginning lines with these strings:
-
-\f(CW%C\fP : Copyright information
-
-\f(CW%D\fP : Documentation lines
-
-\f(CW%I\fP : TeXEdit information lines (mostly in Dutch)
-
-\f(CW%M\fP : Macro code needed to processs the documentation
-
-\f(CW%S\fP : Suppressed lines
-
-The same forms can be used for Perl or ruby scripts, except that the \f(CW%\fP
-character (the TeX comment character) is replaced by \f(CW#\fP (the
-Perl comment character).
-
-See also the \fB--documentation\fP option to
-.BR ctxtools (1).
-
-.SS "Process MetaPost Figures"
-
-.IP "\fB--mpsformats=\fP\fIname\fP"
-The name of a MetaPost format file, e.g. \fBmetafun\fP (the default).
-.IP "\fB--mptex\fP"
-Strips out and typesets TeX code embedded in a
-MetaPost file.
-.IP "\fB--nomp\fP"
-Do not run \fBmpost\fP(1), even if needed.
-.IP "\fB--nomprun\fP"
-Do not run \fBmpost\fP(1) on embedded
-MetaPost code.
-
-.SS "Producing Proof Sheets of Figures"
-
-Generate information and proof sheets of one or more (non-EPS)
-graphics files. For example,
-.EX
-texexec --figures *.png *.jpg
-.EE
-scans the current directory for PNG and JPG files
-and extracts useful information about their sizes and types. By
-default, this information is stored in
-.IR rlxtools.rli .
-Then the given figures are made into a proof sheet (by default
-\fItexexec.pdf\fP) according to the method specified by the
-\fB--method\fP option. Note that newer versions of
-.BR pdftex (1)
-do not support TIFF inclusion.
-.IP "\fB--method=\fP\fIALTERNATIVE\fP"
-Specify one of three options to produce the document containing the images
-used in the source file:
-
-\fBa\fP : A proof sheet with additional
-information provided for each figure (the default)
-
-\fBb\fP : A proof sheet with the graphics only
-
-\fBc\fP : One figure per page, with the page
-clipped to the bounding box of the
-figure
-
-See also \fB--paperoffset\fP,
-which allows you to specify an offset to be added to
-the page, as in
-.EX
-texexec --figures --method=c --paperoffset=.5cm *.pdf *.png *.jpg
-.EE
-
-.SH "USAGE"
-
-Each ConTeXt user interface (language) has its own format. The
-following command generates two formats, one using the English
-interface for typesetting in English, and one for Dutch:
-.EX
-\f(CWtexexec --make en nl\fP
-.EE
-
-By default, the language used for typesetting matches the
-user-interface language (set with
-\fB--interface\fP. It is possible to use one
-language for typesetting and another for messages by changing the
-relevant settings in \fIcont-usr.tex\fP. These languages can
-also be changed on the command line with a command such as
-.IP
-.RS
-\f(CWtexexec --make --language=pl,cz,sk en\fP
-.RE
-.IP
-That command generates a ConTeXt format file with an English user
-interface, and the main language set to Polish (\fBpl\fP). Czech
-and Slovak hyphenation patterns are also loaded
-so that Czech and Slovak text included in a source file will be
-typeset properly (\fBcz\fP and \fBsk\fP).
-.IP o
-When the appropriate formats are present, a file can be typeset
-by typing
-.EX
-\f(CWtexexec test\fP
-.EE
-.IP
-\fBtexexec\fP tries to determine what interface it should use to
-typeset \fItest.tex\fP by looking for a line such as
-.IP
-.EX
-\f(CW% interface=en tex=pdftex output=pdftex\fP
-.EE
-.IP
-at the top of the file (i.e., on the very first line). This line is
-equivalent to \fBTeX\fP's format line, ``&\fIFORMAT\fP'').
-.IP
-By default, \fBtexexec\fP will produce a PDF file using \fBpdftex\fP(1). The
-\fB--dvips\fP flag tells \fBtexexec\fP to produce a PostScript
-file instead.
-.IP
-After an error-free run, \fBtexexec\fP will run \fBtexutil\fP(1) to
-determine whether additional runs of \fBtex\fP(1) (or
-\fBpdftex\fP(1)) or any utility programs (e.g., \fBbibtex\fP(1),
-\fBmakeindex\fP(1)) are necessary. You can suppress these
-additional runs by specifying the \fB--once\fP or
-\fB--runs\fP flags:
-.IP
-.EX
-\f(CWtexexec --once test\fP
-\f(CWtexexec --runs=2 test\fP
-.EE
-.IP
-
-.SH EXAMPLES
+.TH "texexec" "1" "01-01-2013" "version 6.2.1" "TeXExec"
+.SH NAME
+.B texexec
+.SH SYNOPSIS
+.B texexec [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B TeXExec
+.SH OPTIONS
+.TP
+.B --make
+make formats
+.TP
+.B --check
+check versions
+.TP
+.B --process
+process file
+.TP
+.B --mptex
+process mp file
+.TP
+.B --mpxtex
+process mpx file
+.TP
+.B --mpgraphic
+process mp file to stand-alone graphics
+.TP
+.B --mpstatic
+process mp/ctx file to stand-alone graphics
+.TP
+.B --listing
+list of file content
+.TP
+.B --figures
+generate overview of figures
+.TP
+.B --modules
+generate module documentation
+.TP
+.B --pdfarrange
+impose pages (booklets)
.TP
-Produce PDF from ConTeXt source (the .tex extension is optional):
-\f(CWtexexec file.tex\fP
+.B --pdfselect
+select pages from file(s)
.TP
-Same as the above but without rerunning for crossreferences, etc.:
-\f(CWtexexec --once file.tex\fP
+.B --pdfcopy
+copy pages from file(s)
.TP
-Produce PostScript from ConTeXt source:
-\f(CWtexexec --ps file.tex\fP
+.B --pdftrim
+trim pages from file(s)
.TP
-Produce file-a4.pdf using conditional compilation (modes):
-\f(CWtexexec --mode=a4 --result=file-a4 file.tex\fP
+.B --pdfcombine
+combine multiple pages
.TP
-Generate format (.fmt) files used by ConTeXt (used during installation):
-\f(CWtexexec --make --all\fP
+.B --pdfsplit
+split file in pages
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
-.SH "INITIALIZATION"
-.IP
-\fBtexexec\fP requires ruby. On Unix and Unix-like systems, no special
-steps have to be taken to get \fBtexexec\fP to work beyond installing
-ruby and having the \fBruby\fP(1) binary in your path.
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
-.SH "SEE ALSO"
-.PP
-\fBbibtex\fP(1), \fBctxtools\fP(1), \fBdvipdfmx\fP(1), \fBdvips\fP(1),
-\fBfmtutil\fP(1), \fBmakeindex\fP(1), \fBmpost\fP(1),
-\fBmptopdf\fP(1), \fBpdftex\fP(1), \fBpdftk\fP(1), \fBruby\fP(1),
-\fBpsnup\fP(1), \fBtex\fP(1), \fBtexfont\fP(1), \fBtexmfstart\fP(1),
-\fBtexshow\fP(1),
-\fBtexutil\fP(1), \fBxetex\fP(1).
-.PP
-The texexec manual
-.IR mtexexec.pdf ,
-available from
-.URL "http://www.pragma-ade.com/dir/general/manuals/" "PRAGMA ADE" .
-.PP
-Donald E. Knuth's \fIThe TeXbook\fP.
-.PP
-.URL "http://www.contextgarden.net" "ConTeXt wiki" .
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
-.SH "AUTHOR"
-This manpage was written by Tobias Burnus
- and C.M. Connelly
- and updated by Sanjoy Mahajan .
-It is based on the
-.I mtexexec.pdf
-manual written by Hans Hagen .
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/doc/man/man1/texmfstart.1 b/Master/texmf-dist/doc/man/man1/texmfstart.1
index e99ab230bd1..212097ff153 100644
--- a/Master/texmf-dist/doc/man/man1/texmfstart.1
+++ b/Master/texmf-dist/doc/man/man1/texmfstart.1
@@ -1,362 +1,147 @@
-.TH "TEXMFSTART" "1" "December 2006" "texmfstart 2.0" "ConTeXt"
-.de URL
-\\$2 \(laURL: \\$1 \(ra\\$3
-..
-.if \n[.g] .mso www.tmac
-.de EX
-.in +3
-.nf
-.ft CW
-..
-.de EE
-.in -3
-.ft R
-.fi
-..
-
-.SH "NAME"
-texmfstart \- run ConTeXt scripts, make ConTeXt wrapper scripts, view documents
-
-.SH "SYNOPSIS"
-\fB texmfstart\fP [ \fIoptions ...\fP ] [ \fIfilename\fP ] [ \fIarguments ...\fP ]
-
-.SH "DESCRIPTION"
-ConTeXt is a typesetting system based on the
-.BR tex (1)
-family of programs.
-.B texmfstart
-is a ConTeXt meta-script that can run subordinate
-scripts (subscripts?) such as
-.BR texexec (1),
-.BR ctxtools (1),
-or
-.BR pdftools (1).
-It can also generate short wrapper scripts to simplify common uses.
-These scripts are often called
-.I stubs
-in the ConTeXt documentation. The options control
-.BR texmfstart 's
-behaviour, and the arguments are passed
-to the program identified by
-.IR filename .
-
-If the filename is a document, then
-.B texmfstart
-will start a viewer for that document. For example:
-.EX
-texmfstart showcase.pdf
-.EE
-will start an appropriate viewer for
-.IR showcase.pdf .
-See the
-.B EXAMPLES
-section.
-
+.TH "mtxrun" "1" "01-01-2013" "version 1.31" "ConTeXt TDS Runner Tool"
+.SH NAME
+.B mtxrun
+.SH SYNOPSIS
+.B mtxrun [
+.I OPTIONS ...
+.B ] [
+.I FILENAMES
+.B ]
+.SH DESCRIPTION
+.B ConTeXt TDS Runner Tool
.SH OPTIONS
-
-.SS General:
.TP
-.B --help, --version
-print version information, usage, and examples.
+.B --script
+run an mtx script (lua prefered method) (--noquotes), no script gives list
.TP
-.B --verbose
-print status and progress information, for example what commands are
-being executed.
+.B --execute
+run a script or program (texmfstart method) (--noquotes)
.TP
-.B --clear
-don't pass info about locations to child processes.
-
-.SS Running a program:
+.B --resolve
+resolve prefixed arguments
.TP
-.B --arguments=\fIstr\fP
-an alternative for providing the arguments to be passed. For example,
-.EX
-texmfstart --arguments=b.tex texexec
-.EE
-will pass
-.I b.tex
-as the argument to
-.BR texexec .
+.B --ctxlua
+run internally (using preloaded libs)
.TP
-.B --report
-dry run: report what command would be run, but do not run it
+.B --internal
+run script using built in libraries (same as --ctxlua)
.TP
.B --locate
-dry run: like \f(CW--report\fP but doesn't print the trailing newline.
+locate given filename in database (default) or system (--first --all --detail)
.TP
-.B --browser
-view the document in a web browser (for Windows).
+.B --autotree
+use texmf tree cf. env texmfstart_tree or texmfstarttree
.TP
-.B --file=\fIfilename\fP
-an alternative way to specify the file (the program to run or document
-to open).
+.B --tree=pathtotree
+use given texmf tree (default file: setuptex.tmf)
.TP
-.B --direct
-run a program without searching for its location (assumes that the
-program is on the PATH).
+.B --environment=name
+use given (tmf) environment file
.TP
-.B --execute
-use the
-.BR ruby (1)
-.I exec
-function instead of its
-.I system
-function.
-.TP
-.B --program=\fIstr\fP
-the program space where
-.BR kpsewhich (1)
-will search (default: context). This information is given to
-.B kpsewhich
-as its \f(CW-progname\fP option. Usually you don't need this option.
-
-.SS Creating startup scripts:
-.TP
-.B --make
-create a wrapper script or batch file to run the given file.
-The wrapper scripts are put in the current path, which usually means
-the current directory. If
-\fIall\fP is given as the file, e.g.
-.EX
-texmfstart --make all
-.EE
-then make all the ConTeXt wrapper scripts (the stubs).
+.B --path=runpath
+go to given path before execution
.TP
-.B --windows
-when making a wrapper script (stub), create a Windows batch (.bat) file.
-Usually you
-do not need to specify this option, as
-.B texmfstart
-will figure out what operating system you are using.
-.TP
-.B --linux
-when making a wrapper script, create a Unix shell script. Usually you
-do not need to specify this option, as
-.B texmfstart
-will figure out what operating system you are using.
-.TP
-.B --stubpath=\fIpath\fP
-specify where to put the wrapper scripts (stubs).
-.TP
-.B --indirect
-always use
-.I texmfstart
-in the wrapper script (stub).
-
-.SS Document viewing:
+.B --ifchanged=filename
+only execute when given file has changed (md checksum)
.TP
-.B --page=\fInumber\fP
-open the document at this page.
-
-.SS Environments and paths:
+.B --iftouched=old,new
+only execute when given file has changed (time stamp)
.TP
-.B --path=\fIstr\fP
-change to the specified path.
+.B --makestubs
+create stubs for (context related) scripts
.TP
-.B --tree=\fIstr\fP
-use the given TEXMF tree.
+.B --removestubs
+remove stubs (context related) scripts
.TP
-.B --autotree
-automatically determine the TEXMF tree to use (the default).
+.B --stubpath=binpath
+paths where stubs wil be written
.TP
-.B --environment=\fIstr\fP
-use the given environment file. Its syntax is given in the
-.I mtexmfstart.pdf
-manual.
+.B --windows
+create windows (mswin) stubs
.TP
-.B --showenv
-print the environment variables known at runtime
-
-.SS Conditional execution:
+.B --unix
+create unix (linux) stubs
.TP
-.B --iftouched=\fIfile1,file2\fP
-run only when the given files have different timestamps.
+.B --verbose
+give a bit more info
.TP
-.B --ifchanged=\fIstr\fP
-run only when the given file has changed (based on its last-computed MD5
-checksum).
-
-.SS Special features:
+.B --trackers=list
+enable given trackers
+.TP
+.B --progname=str
+format or backend
.TP
.B --edit
-open the given file in an editor.
-
-.SH "FILENAME PREFIXES"
-.SS
-Optional prefixes determine the method used to search for the specified file:
+launch editor with found file
.TP
-.I bin:filename
-expanded name based on the PATH environment variable
+.B --launch
+launch files like manuals, assumes os support (--all)
.TP
-.I kpse:filename
-expanded name based on
-.BR kpsewhich (1)
-result
+.B --timedrun
+run a script and time its run
.TP
-.I rel:filename
-expanded name relative to the current directory
+.B --autogenerate
+regenerate databases if needed (handy when used to run context in an editor)
.TP
-.I env:name
-expanded pathname based on environment variable
-.I name
+.B --usekpse
+use kpse as fallback (when no mkiv and cache installed, often slower)
.TP
-.I path:filename
-path part of filename as located by
-.BR kpsewhich (1)
-
-.SH EXAMPLES
-.TP
-\f(CWtexmfstart texexec.rb file.tex\fP
-Locate the
-.I texexec.rb
-script and run it with
-.I file.tex
-as its argument. In other words, make
-.I file.pdf
-from
-.IR file.tex .
-If
-.BR texexec (1)
-is properly installed on your system,
-this common invocation can be shortened to
-.EX
-\f(CWtexexec file.tex\fP
-.EE
-.TP
-\f(CWtexmfstart texexec file.tex\fP
-Locate the
-.BR texexec (1)
-program (currently a
-.BR ruby (1)
-script,
-.IR texexec.rb )
-and run it with
-.I file.tex
-as its argument, producing
-.I file.pdf.
-This invocation can be shortened to
-.EX
-texexec file.tex
-.EE
-.TP
-\f(CWtexmfstart ctxtools --updatecontext\fP
-Run the
-.BR ctxtools (1)
-script, updating the ConTeXt installation. This
-invocation is equivalent to
-.EX
-ctxtools --updatecontext
-.EE
-.TP
-\f(CWtexmfstart pstopdf --method=3 cow.eps\fP
-Convert
-.I cow.eps
-to PDF using method 3 of
-.BR pstopdf (1).
-This invocation is equivalent to
-.EX
-pstopdf --method=3 cow.eps
-.EE
-.TP
-\f(CWtexmfstart --make --stubpath=/usr/local/bin texexec\fP
-Make a wrapper script (stub), either a shell script
-.I /usr/local/bin/texexec
-on Unix, or a batch file \fI\\usr\\local\\bin\\texexec.bat\fP
-on Windows. On Unix (and maybe on Windows?), you need to make
-the script executable; see
-.BR chmod (1).
-.TP
-\f(CWtexmfstart --edit kpse:cont-sys.tex\fP
-Locate and edit the \fIcont-sys.tex\fP configuration file.
-.TP
-\f(CWtexmfstart --ifchanged=whatever.mp texexec --mpgraphic whatever.mp\fP
-Rerun
-.B texexec
-if
-.I whatever.mp
-has changed since the last use of
-.IR --ifchanged .
-.TP
-\f(CWtexmfstart --ifchanged=whatever.mp bin:echo rerun MetaPost\fP
-If the
-.I whatever.mp
-source file has changed since the last use of
-.IR --ifchanged ,
-then use the
-.BR echo (1)
-command to tell the user to rerun MetaPost
-.RB "(see " mpost (1)).
-This example shows that
-.B texmfstart
-can be used to run any script, not just ConTeXt scripts. The
-\f(CWbin:\fP prefix tells
-.B texmfstart
-not to search for
-.I echo
-in the TEXMF tree(s), but to assume that it's an executable somewhere
-on the PATH.
-.TP
-\f(CWtexmfstart --ifchanged=whatever.mp --direct echo rerun MetaPost\fP
-This invocation has the same effect as the preceding example, but
-using \f(CW--direct\fP instead of the \f(CWbin:\fP prefix, again to tell
-.B texmfstart
-not to search for the
-.I echo
-command.
-
-.SH FILES
+.B --forcekpse
+force using kpse (handy when no mkiv and cache installed but less functionality)
.TP
-.I file.md5
-MD5 checksum file used for the \f(CW--ifchanged\fP option.
-
-.SH ENVIRONMENT
-.TP
-PATH
-For expanding filenames given with a
-.I bin
-prefix.
-.TP
-TEXMFSTART_EDITOR, EDITOR, editor
-Editor to use with
-.IR --edit .
-The environment variables are looked up in that order, with the first
-setting found taking priority.
+.B --prefixes
+show supported prefixes
+.TP
+.B --generate
+generate file database
+.TP
+.B --variables
+show configuration variables
+.TP
+.B --configurations
+show configuration order
+.TP
+.B --directives
+show (known) directives
+.TP
+.B --trackers
+show (known) trackers
+.TP
+.B --experiments
+show (known) experiments
+.TP
+.B --expand-braces
+expand complex variable
+.TP
+.B --expand-path
+expand variable (resolve paths)
+.TP
+.B --expand-var
+expand variable (resolve references)
+.TP
+.B --show-path
+show path expansion of ...
+.TP
+.B --var-value
+report value of variable
+.TP
+.B --find-file
+report file location
+.TP
+.B --find-path
+report path of file
+.TP
+.B --pattern=string
+filter variables
+.SH AUTHOR
+More information about ConTeXt and the tools that come with it can be found at:
-.SH "SEE ALSO"
-.PP
-.BR ctxtools (1),
-.BR kpsewhich (1),
-.BR makempy (1),
-.BR mpost (1),
-.BR pdftools (1),
-.BR pstopdf (1),
-.BR texexec (1),
-.BR texfont (1),
-.BR texutil (1).
-.PP
-.URL "http://www.contextgarden.net" "ConTeXt wiki" .
-.PP
-The
-.B texmfstart
-manual,
-.IR mtexmfstart.pdf ,
-available from
-.URL "http://www.pragma-ade.com/dir/general/manuals/" "PRAGMA ADE" .
-.SH BUGS
-On Unix, opening a PDF document first tries
-.B pdfopen
-then
-.BR acroread ,
-neither of which may be present on your system.
+.B "maillist:"
+ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
-The \f(CW--report\fP option doesn't work if you specify a filename
-prefix (i.e. it does a real run instead of a dry run).
+.B "webpage:"
+http://www.pragma-ade.nl / http://tex.aanhet.net
-.SH "AUTHOR"
-ConTeXt is written and maintained by
-.URL "http://www.pragma-ade.com" "Hans Hagen" .
-This man page, which is in the public domain, was written by Sanjoy
-Mahajan based on the
-.I mtexmfstart.pdf
-manual.
+.B "wiki:"
+http://contextgarden.net
diff --git a/Master/texmf-dist/fonts/map/pdftex/context/koeieletters.map b/Master/texmf-dist/fonts/map/pdftex/context/koeieletters.map
deleted file mode 100644
index c3e177c176e..00000000000
--- a/Master/texmf-dist/fonts/map/pdftex/context/koeieletters.map
+++ /dev/null
@@ -1,8 +0,0 @@
-koeieletters koeieletters " koeielettersEnc ReEncodeFont " chem_setting_scale :
- chem_setting_scale := scale ;
- chem_init_all ;
- fi ;
- chem_rotation := 1 ;
- chem_adjacent := 0 ;
- chem_substituent := 0 ;
- chem_direction := 0 ;
- chem_stack_n := 0 ;
- chem_doing_pb := false ;
- chem_shift := origin ;
-enddef ;
-
-def chem_stop_structure =
- currentpicture := currentpicture shifted - chem_shift ;
- % axis here
- if chem_setting_fixedwidth :
- chem_setting_l := - xpart llcorner currentpicture ;
- chem_setting_r := xpart urcorner currentpicture ;
+ chem_r_path[$] :=
+ if chem_star[$] :
+ chem_b_path[$]
+ else :
+ (
+ for i=0 upto chem_num0-1 :
+ (unitvector point i of chem_b_path[$])
+ shifted point i of chem_b_path[$] --
+ endfor
+ cycle
+ )
+ fi ;
+
+ chem_r_path.lft[$] :=
+ (
+ for i=0 upto chem_num0-1 :
+ if chem_front[$] :
+ up
+ scaled .5
+ shifted point i of chem_b_path[$]
+ elseif chem_star[$] :
+ point i of chem_b_path[$]
+ else :
+ point i+1 of chem_b_path[$]
+ rotatedabout(point i of chem_b_path[$],180)
+ fi --
+ endfor
+ cycle
+ ) ;
+ chem_r_path.rt[$] :=
+ (
+ for i=0 upto chem_num0-1 :
+ if chem_front[$] :
+ down
+ scaled .5
+ shifted point i of chem_b_path[$]
+ elseif chem_star[$] :
+ point i+2 of chem_b_path[$]
+ else :
+ point i-1 of chem_b_path[$]
+ rotatedabout(point i of chem_b_path[$],180)
+ fi --
+ endfor
+ cycle
+ ) ;
+
+enddef ;
+
+% The following is used only once:
+def chem_init_all =
+begingroup
+ save a, b, c, d, e ; numeric a, b, c, d, e ;
+ save lft, rt ; path lft, rt ;
+
+ % tetrahedrial angle
+ a := 2angle(1,sqrt 2) ;
+
+ % solve for chair
+ 2b = 180 - .5a ;
+ 4c = 180 - .5a ;
+ d + e = 360 - 2a ;
+ d = 5e ; % this is the one tunable parameter which fixes the perspective.
+ z2 = z1 shifted dir(90+a+d) ;
+ z3 = z2 shifted dir(270-a) ;
+ z4 = z3 shifted dir(90+a) ;
+ z6 = z1 shifted dir(90+a) ;
+ z5 = z6 shifted dir(270-a) ;
+ z4 = z1 xyscaled (-1,-1) ;
+ z5 = z2 xyscaled (-1,-1) ;
+
+ save indx ; numeric indx ; indx = 2 ; % starting value doesn't matter, really.
+ % polygons
+ three := incr indx ; % 3 (these numbers don't matter - they are just indices)
+ four := incr indx ; % 4
+ five := incr indx ; % 5
+ six := incr indx ; % 6
+ seven := incr indx ; % 7
+ eight := incr indx ; % 8
+ nine := incr indx ; % 9
+
+ chem_init_some(three,3) ;
+ chem_init_some(four, 4) ;
+ chem_init_some(five, 5) ;
+ chem_init_some(six, 6) ;
+ chem_init_some(seven,7) ;
+ chem_init_some(eight,8) ;
+ chem_init_some(nine, 9) ;
+
+ % star-form
+ one := incr indx ; % 10
+ carbon := incr indx ; % 11
+ alkyl := incr indx ; % 12
+ newmanstagger := incr indx ; % 13
+ newmaneclipsed := incr indx ; % 14
+
+ chem_star[one] := true ;
+ chem_star[carbon] := true ; chem_tetra[carbon] := true ;
+ chem_star[alkyl] := true ; chem_tetra[alkyl] := true ;
+ chem_star[newmanstagger] := true ; chem_tetra[newmanstagger] := true ;
+ chem_star[newmaneclipsed] := true ; chem_tetra[newmaneclipsed] := true ;
+ chem_stacked[newmanstagger] := true ;
+ chem_stacked[newmaneclipsed] := true ;
+ chem_init_some(one, 8) ;
+ chem_init_some(carbon, dir(0)--dir(360-a)--dir(180-.5a+b)--dir(180-.5a)) ;
+ chem_init_some(alkyl, dir(0)--dir(360-a)--dir(360-a-90)--dir(90)) ;
+ chem_init_some(newmanstagger, dir(30)--dir(270)--dir(150)--dir(330)--dir(210)--dir(90)) ;
+ chem_init_some(newmaneclipsed, dir(30)--dir(270)--dir(150)--dir(0)--dir(240)--dir(120)) ;
+
+ % front views
+ fivefront := incr indx ; % 15
+ sixfront := incr indx ; % 16
+ chair := incr indx ; % 17
+ boat := incr indx ; % 18
+
+ chem_front[fivefront] := true ; chem_front_b[fivefront] := 3 ;
+ chem_front[sixfront] := true ; chem_front_b[sixfront] := 3 ;
+ chem_init_some(fivefront,5) ;
+ chem_init_some(sixfront, 6) ;
+ % chair
+ chem_front[chair] := true ; chem_front_b[chair] := 4 ;
+ chem_init_some(chair, z1--z2--z3--z4--z5--z6) ;
+ lft := dir(90-a)--down--dir(90+a+d)--down--dir(90+a)--down ;
+ rt := up--dir(270+a)--up--dir(270-a)--up--dir(90+e) ;
+ chem_r_path.lft[chair] :=
+ for i=0 upto 5 : point i of lft shifted point i of chem_b_path[chair] -- endfor
+ cycle ;
+ chem_r_path.rt[chair] :=
+ for i=0 upto 5 : point i of rt shifted point i of chem_b_path[chair] -- endfor
+ cycle ;
+ % boat
+ chem_front[boat] := true ; chem_front_b[boat] := 4 ;
+ chem_init_some(boat,
+ for i=1 upto 4 : point i-1 of chem_b_path[sixfront] -- endfor
+ point 2 of chem_b_path[sixfront] yscaled .5 --
+ point 1 of chem_b_path[sixfront] yscaled .5
+ ) ;
+ lft := dir(30+.5a)--dir(330+.5a)--dir(210-.5a)--dir(150-.5a)--dir(120)--dir(60) ;
+ rt := dir(30-.5a)--dir(330-.5a)--dir(210+.5a)--dir(150+.5a)--dir(120+a)--dir(60-a) ;
+ chem_r_path.lft[boat] :=
+ for i=0 upto 5 : point i of lft shifted point i of chem_b_path[boat] -- endfor
+ cycle ;
+ chem_r_path.rt[boat] :=
+ for i=0 upto 5 : point i of rt shifted point i of chem_b_path[boat] -- endfor
+ cycle ;
+endgroup
+enddef ;
+
+chem_init_all ; % WHY does this not work unless defined and then called?
+
+
+% Like most often in ConTeXt, we will trap but then silently ignore mistaken use,
+% unless of course the error be too harmful...
+
+% \startchemical
+
+def chem_start_structure(expr i, l, r, t, b, rotation, unit, factor, offset, axis, rulethickness, axiscolor) =
+ save chem_setting_l, chem_setting_r, chem_setting_t, chem_setting_b ;
+
+ chem_emwidth := unit ;
+ chem_b_length := factor * unit ;
+ if numeric l :
+ chem_setting_l := -l ;
+ fi
+ if numeric r :
+ chem_setting_r := r ;
+ fi
+ if numeric t :
+ chem_setting_t := t ;
+ fi
+ if numeric b :
+ chem_setting_b := -b ;
+ fi
+ chem_setting_rotation := rotation ;
+ chem_setting_offset := offset ;
+ chem_setting_axis := if boolean axis : axis else : (axis<>0) fi ;
+ chem_axis_rulethickness := .75*(rulethickness) ; % axis 50% thinner than frame and bonds.
+ chem_axis_color := image(draw origin withcolor axiscolor) ; % so we handle all color models
+
+ chem_reset ;
+enddef ;
+
+% \stopchemical
+
+vardef chem_stop_structure =
+ % Make sure that all of the saved stack has been restored... (this was a gotcha!)
+ forever :
+ exitif chem_stack_n=0 ;
+ chem_restore ;
+ endfor
+
+ currentpicture := (currentpicture shifted -chem_origin) rotated chem_setting_rotation ;
+
+ save l, r, b, t ;
+ l := min(xpart llcorner currentpicture, xpart lrcorner currentpicture) ;
+ r := max(xpart llcorner currentpicture, xpart lrcorner currentpicture) ;
+ b := min(ypart llcorner currentpicture, ypart ulcorner currentpicture) ;
+ t := max(ypart llcorner currentpicture, ypart ulcorner currentpicture) ;
+
+ if unknown chem_setting_l : chem_setting_l := l ; fi
+ if unknown chem_setting_r : chem_setting_r := r ; fi
+ if unknown chem_setting_b : chem_setting_b := b ; fi
+ if unknown chem_setting_t : chem_setting_t := t ; fi
+
+ if chem_setting_axis : % put it behind the picture
+ chem_pic := currentpicture ; currentpicture := nullpicture ;
+ chem_num0 := .5chem_b_length ;
+ chem_num1 := .2chem_num0 ;
+ % draw the axes to the bounding box of the entire structure,
+ % not necessarily the bounding box of the final figure
+ draw (l,0) -- (r,0)
+ withpen pencircle scaled chem_axis_rulethickness withcolor colorpart(chem_axis_color) ;
+ draw (0,b) -- (0,t)
+ withpen pencircle scaled chem_axis_rulethickness withcolor colorpart(chem_axis_color) ;
+ for i = 0 step chem_num0 until r :
+ draw (i,-chem_num1) -- (i,chem_num1)
+ withpen pencircle scaled chem_axis_rulethickness withcolor colorpart(chem_axis_color) ;
+ endfor
+ for i = 0 step -chem_num0 until l :
+ draw (i,-chem_num1) -- (i,chem_num1)
+ withpen pencircle scaled chem_axis_rulethickness withcolor colorpart(chem_axis_color) ;
+ endfor
+ for i = 0 step chem_num0 until t :
+ draw (-chem_num1,i) -- (chem_num1,i)
+ withpen pencircle scaled chem_axis_rulethickness withcolor colorpart(chem_axis_color) ;
+ endfor
+ for i = 0 step -chem_num0 until b :
+ draw (-chem_num1,i) -- (chem_num1,i)
+ withpen pencircle scaled chem_axis_rulethickness withcolor colorpart(chem_axis_color) ;
+ endfor
+ addto currentpicture also chem_pic ;
fi ;
- if chem_setting_fixedheight :
- chem_setting_t := ypart urcorner currentpicture ;
- chem_setting_b := - ypart llcorner currentpicture ;
+ if chem_trace_boundingbox :
+ fill boundingbox currentpicture withcolor blue withtransparency(1,.25) ;
fi ;
- chem_setting_bbox :=
- (-chem_setting_l,-chem_setting_b) -- ( chem_setting_r,-chem_setting_b) --
- ( chem_setting_r, chem_setting_t) -- (-chem_setting_l, chem_setting_t) -- cycle ;
- % maybe put it behind the picture
- if chem_setting_axis :
- save stp ; stp := chem_base_width/ 2 * chem_setting_scale ;
- save siz ; siz := chem_base_width/10 * chem_setting_scale ;
- draw (-chem_setting_l,0) -- (chem_setting_r,0) withcolor blue ;
- draw (0,-chem_setting_b) -- (0,chem_setting_t) withcolor blue ;
- for i = 0 step stp until chem_setting_r : draw (i,-siz) -- (i,siz) withcolor blue ; endfor ;
- for i = 0 step -stp until -chem_setting_l : draw (i,-siz) -- (i,siz) withcolor blue ; endfor ;
- for i = 0 step stp until chem_setting_t : draw (-siz,i) -- (siz,i) withcolor blue ; endfor ;
- for i = 0 step -stp until -chem_setting_b : draw (-siz,i) -- (siz,i) withcolor blue ; endfor ;
- draw chem_setting_bbox withcolor blue ;
+ setbounds currentpicture to
+ ((chem_setting_l,chem_setting_b) -- (chem_setting_r,chem_setting_b) --
+ (chem_setting_r,chem_setting_t) -- (chem_setting_l,chem_setting_t) -- cycle) ;
+ if chem_trace_boundingbox :
+ fill boundingbox currentpicture withcolor red withtransparency(1,.25) ;
fi ;
- setbounds currentpicture to chem_setting_bbox ;
enddef ;
-def chem_start_component = enddef ;
-def chem_stop_component = enddef ;
+% \chemical
+
+vardef chem_start_component = enddef ;
+vardef chem_stop_component = enddef ;
-def chem_pb =
-% draw boundingbox currentpicture withpen pencircle scaled 1mm withcolor blue ;
-% draw origin withpen pencircle scaled 2mm withcolor blue ;
+vardef chem_pb = % PB :
+ if chem_trace_nesting :
+ draw boundingbox currentpicture
+ withpen pencircle scaled 1mm withcolor colorpart(chem_axis_color) ;
+ draw origin withpen pencircle scaled 2mm withcolor colorpart(chem_axis_color) ;
+ fi ;
chem_doing_pb := true ;
enddef ;
-def chem_pe =
-% draw boundingbox currentpicture withpen pencircle scaled .5mm withcolor red ;
-% draw origin withpen pencircle scaled 1mm withcolor red ;
- currentpicture := currentpicture shifted - chem_shift ;
-% draw origin withpen pencircle scaled .5mm withcolor green ;
- chem_shift := origin ;
+vardef chem_pe = % PE
+ if chem_trace_nesting :
+ draw boundingbox currentpicture withpen pencircle scaled .5mm withcolor red ;
+ draw origin withpen pencircle scaled 1mm withcolor red ;
+ fi ;
+ currentpicture := currentpicture shifted -chem_origin ;
+ if chem_trace_nesting :
+ draw origin withpen pencircle scaled .5mm withcolor green ;
+ fi ;
+ chem_origin := origin ;
chem_doing_pb := false ;
enddef ;
-vardef chem_do (expr p) =
- if chem_doing_pb :
+vardef chem_do (expr pos) =
+ if (unknown chem_doing_pb) or (not chem_doing_pb) :
+ pos
+ else :
chem_doing_pb := false ;
-% save pp ; pair pp ; pp := point 1 of ((origin -- p) enlonged chem_picture_offset) ;
-% currentpicture := currentpicture shifted - pp ;
-% chem_shift := chem_shift - center pp ;
- currentpicture := currentpicture shifted - p ;
- chem_shift := chem_shift - p ;
+ currentpicture := currentpicture shifted -pos ;
+ chem_origin := chem_origin shifted -pos ;
origin % nullpicture
- else :
- p
fi
enddef ;
-vardef chem_b (expr n, f, t, r, c) =
- chem_draw (n, chem_b_path[n], f, t, r, c) ;
-enddef ;
-vardef chem_sb (expr n, f, t, r, c) =
- chem_draw (n, chem_sb_path[n], f, t, r, c) ;
+picture chem_stack_p[] ;
+pair chem_stack_origin[], chem_stack_mirror[] ;
+numeric chem_stack_rotation[] ;
+string chem_stack_previous[] ;
+
+vardef chem_save = % SAVE
+ chem_stack_p [incr chem_stack_n] := currentpicture ;
+ chem_stack_origin [ chem_stack_n] := chem_origin ; chem_origin := origin ;
+ chem_stack_rotation[ chem_stack_n] := chem_rotation ;
+ chem_stack_mirror [ chem_stack_n] := chem_mirror ;
+ chem_stack_previous[ chem_stack_n] := chem_previous ;
+ currentpicture := nullpicture ;
enddef ;
-vardef chem_s (expr n, f, t, r, c) =
- chem_draw (n, chem_s_path[n], f, t, r, c) ;
+vardef chem_restore = % RESTORE
+ if chem_stack_n>0 :
+ currentpicture := currentpicture shifted -chem_origin ;
+ addto chem_stack_p [chem_stack_n] also currentpicture ;
+ currentpicture := chem_stack_p [chem_stack_n] ;
+ chem_stack_p[chem_stack_n] := nullpicture ;
+ chem_origin := chem_stack_origin [chem_stack_n] ;
+ chem_rotation := chem_stack_rotation[chem_stack_n] ;
+ chem_mirror := chem_stack_mirror [chem_stack_n] ;
+ chem_previous := chem_stack_previous[chem_stack_n] ;
+ chem_stack_n := chem_stack_n - 1 ;
+ fi ;
enddef ;
-vardef chem_ss (expr n, f, t, r, c) =
- chem_draw (n, chem_ss_path[n], f, t, r, c) ;
-enddef ;
+% chem_adj and chem_sub are to be followed by chem_set(n) which does all the work...
-vardef chem_mid (expr n, r, c) =
- chem_draw_fixed (n, chem_midt_path[n], r, c) ;
- chem_draw_fixed (n, chem_midb_path[n], r, c) ;
+vardef chem_adj (suffix $) (expr d, s) = % ADJ
+ % scale s is ignored (for now?)
+ if not chem_front[$] :
+ chem_substituent := 0 ;
+ chem_substituent.lft := 0 ;
+ chem_substituent.rt := 0 ;
+ chem_adjacent := d ;
+ fi
enddef ;
-vardef chem_mids (expr n, r, c) =
- chem_draw_fixed (n, chem_midst_path[n], r, c) ;
- chem_draw_fixed (n, chem_midsb_path[n], r, c) ;
+vardef chem_lsub (suffix $) (expr d, s) = % LSUB
+ chem_sub.lft($,d,s) ;
enddef ;
-vardef chem_mss (expr n, f, t, r, c) =
- chem_draw (n, chem_mss_path[n], f, t, r, c) ;
+vardef chem_rsub (suffix $) (expr d, s) = % RSUB
+ chem_sub.rt ($,d,s) ;
enddef ;
-vardef chem_pss (expr n, f, t, r, c) =
- chem_draw (n, chem_pss_path[n], f, t, r, c) ;
+vardef chem_sub@# (suffix $) (expr d, s) = % SUB
+ % scale s is ignored (for now?)
+ chem_adjacent := 0 ;
+ chem_substituent := 0 ;
+ chem_substituent.lft := 0 ;
+ chem_substituent.rt := 0 ;
+ % then :
+ chem_substituent@# := d ;
enddef ;
-vardef chem_msb (expr n, f, t, r, c) =
- chem_draw (n, chem_msb_path[n], f, t, r, c) ;
+def chem_transformed (suffix $) = % not vardef!
+ scaled chem_b_length
+ if not chem_front[$] :
+ if chem_mirror<>origin : reflectedabout(origin,chem_mirror) fi
+ rotated chem_rotation
+ fi
enddef ;
-vardef chem_psb (expr n, f, t, r, c) =
- chem_draw (n, chem_psb_path[n], f, t, r, c) ;
+vardef chem_draw (expr what, r, c) (text extra) =
+ draw what
+ withpen pencircle scaled r
+ withcolor c %\MPcolor{c}
+ extra ;
enddef ;
-vardef chem_eb (expr n, f, t, r, c) =
- chem_draw (n, chem_eb_path[n], f, t, r, c) ;
+vardef chem_fill (expr what, r, c) (text extra) =
+ fill what
+ withpen pencircle scaled r
+ withcolor c %\MPcolor{c}
+ extra ;
enddef ;
-vardef chem_db (expr n, f, t, r, c) =
- if n = 1 :
- chem_draw (n, chem_msb_path [n], f, t, r, c) ;
- chem_draw (n, chem_psb_path [n], f, t, r, c) ;
- else :
- chem_draw (n, chem_dbl_path [n], f, t, r, c) ;
- chem_draw (n, chem_dbr_path [n], f, t, r, c) ;
- fi ;
+vardef chem_drawarrow (expr what, r, c) (text extra) =
+ drawarrow what
+ withpen pencircle scaled r
+ withcolor c %\MPcolor{c}
+ extra ;
enddef ;
-vardef chem_er (expr n, f, t, r, c) =
- chem_draw (n, chem_rl_path[n], f, t, r, c) ;
- chem_draw (n, chem_rr_path[n], f, t, r, c) ;
-enddef ;
+vardef chem_set (suffix $) =
+ forsuffixes P = scantokens chem_previous :
-vardef chem_dr (expr n, f, t, r, c) =
- chem_draw (n, chem_srl_path[n], f, t, r, c) ;
- chem_draw (n, chem_srr_path[n], f, t, r, c) ;
-enddef ;
+ % This is a fairly complicated optimization and ajustement. It took some
+ % thinking to get right, so beware!
-vardef chem_ad (expr n, f, t, r, c) =
- chem_draw_arrow(n, chem_ad_path[n], f, t, r, c) ;
-enddef ;
+ if (chem_adjacent<>0) and chem_star[P] and chem_star[$] :
+ % nop
+ chem_adjacent := 0 ;
+ elseif (chem_adjacent<>0) and (chem_front[P] or chem_front[$]) :
+ % not allowed for FRONT
+ chem_adjacent := 0 ;
+ elseif chem_adjacent<>0 :
+ chem_substituent := 0 ;
+ chem_substituent.lft := 0 ;
+ chem_substituent.rt := 0 ;
+ % move to the bond midpoint of the first structure
+ chem_pair0 := center (
+ if chem_star[P] :
+ origin -- point (chem_adjacent-1)
+ else :
+ subpath (chem_adjacent-1,chem_adjacent)
+ fi
+ of chem_b_path[P]
+ ) chem_transformed(P) ;
+ % find the closest opposite bond of the second structure
+ chem_pair1 := chem_pair0 rotated if chem_star[P] : 90 else : 180 fi ;
+ chem_num0 := abs(chem_pair1) ;
+ chem_num1 := if chem_tetra[$] : 1 else : length chem_b_path[$] fi ;
+ % only consider even indices (cardinal points) for ONE
+ chem_num2 := if chem_star[$] and not chem_tetra[$] : 2 else : 1 fi ;
+ for i=0 step chem_num2 until chem_num1 :
+ chem_pair2 := (
+ (
+ unitvector
+ center (
+ if chem_star[$] :
+ origin -- point i
+ else :
+ subpath (i,i+1)
+ fi
+ of chem_b_path[$])
+ )
+ scaled chem_num0
+ ) chem_transformed($) ;
+ if i=0 :
+ chem_pair3 := chem_pair2 ;
+ chem_num3 := 0 ;
+ elseif (abs(chem_pair1 shifted -chem_pair2)) < (abs(chem_pair1 shifted -chem_pair3)) :
+ chem_pair3 := chem_pair2 ;
+ chem_num3 := i ;
+ fi
+ endfor
+ if chem_star[$] :
+ chem_pair4 := chem_pair0 shifted
+ -((point (chem_adjacent-1) of chem_b_path[P]) chem_transformed(P)) ;
+ fi
+ % adjust the bond angles
+ chem_rotation := (chem_rotation + angle(chem_pair1)-angle(chem_pair3)) mod 360 ;
+ if not chem_star[$] :
+ chem_pair4 :=
+ if chem_star[P] :
+ (point chem_num3
+ else :
+ center(subpath (chem_num3,chem_num3+1)
+ fi
+ of chem_b_path[$])
+ chem_transformed($) ;
+ fi
+ if not chem_star[P] :
+ chem_pair4 := chem_pair4 shifted -chem_pair0 ;
+ fi
+ currentpicture := currentpicture shifted chem_pair4 ;
+ chem_origin := chem_origin shifted chem_pair4 ;
+ chem_adjacent := 0 ;
+ fi ;
-vardef chem_au (expr n, f, t, r, c) =
- chem_draw_arrow(n, chem_au_path[n], f, t, r, c)
+ % Insure that only one, if any, will be nonzero
+ if ((chem_substituent <> 0) and (chem_substituent.lft <> 0)) or
+ ((chem_substituent <> 0) and (chem_substituent.rt <> 0)) or
+ ((chem_substituent.lft <> 0) and (chem_substituent.rt <> 0)) :
+ chem_substituent := 0 ;
+ chem_substituent.lft := 0 ;
+ chem_substituent.rt := 0 ;
+ fi
+ if (chem_substituent <> 0) or (chem_substituent.lft <> 0) or (chem_substituent.rt <> 0) :
+ % move origin to radical endpoint of the first structure
+ if chem_substituent.lft > 0 :
+ chem_pair0 := point chem_substituent.lft-1 of chem_r_path.lft[P] ;
+ chem_substituent := chem_substituent.lft ;
+ chem_substituent.lft := 0 ;
+ elseif chem_substituent.rt > 0 :
+ chem_pair0 := point chem_substituent.rt-1 of chem_r_path.rt[P] ;
+ chem_substituent := chem_substituent.rt ;
+ chem_substituent.rt := 0 ;
+ else :
+ chem_pair0 := point chem_substituent-1 of chem_r_path[P] ;
+ fi
+ chem_pair1 := chem_pair0 if not chem_star[P] :
+ shifted -(point chem_substituent-1 of chem_b_path[P]) fi ;
+ chem_t := identity chem_transformed(P) ;
+ chem_pair0 := chem_pair0 transformed chem_t ; % radical
+ chem_pair1 := chem_pair1 transformed chem_t ; % recentered (see below)
+ currentpicture := currentpicture shifted -chem_pair0 ;
+ chem_origin := chem_origin shifted -chem_pair0 ;
+ if (not (chem_star[P] and chem_star[$])) or chem_tetra[P] or chem_tetra[$] :
+ if chem_tetra[P] and chem_tetra[$] and ((chem_substituent=1) or (chem_substituent=2)):
+ chem_rotation := (chem_rotation + 180) mod 360 ; % trans-alkane
+ chem_pair2 := (point .5 of chem_b_path[$]) ; % bisector, not chem_transformed
+ if chem_mirror=origin :
+ chem_mirror := chem_pair2 ;
+ else :
+ chem_num0 := angle(chem_mirror)-angle(chem_pair2) ;
+ if (chem_num0>0) and (chem_num0> 180) :
+ chem_num0 := 360 - chem_num0 ;
+ elseif (chem_num0<0) and (chem_num0<-180) :
+ chem_num0 := -360 - chem_num0 ;
+ fi
+ chem_rotation := (chem_rotation + 2chem_num0) mod 360 ;
+ chem_mirror := origin ;
+ fi
+ fi
+ chem_t := identity chem_transformed($) ;
+ chem_pair1 := chem_pair1 rotated 180 ; % opposite direction of radical bond
+ % find the closest node
+ chem_num0 := abs(chem_pair1) ; % distance
+ % search to find the nearest node of $; only consider 1 and 2 for CARBON,ALKYL
+ chem_num1 := if chem_tetra[$] : 1 else : length chem_b_path[$] fi ;
+ % only consider even indices (cardinal points) for ONE
+ chem_num2 := if chem_star[$] and not chem_tetra[$] : 2 else : 1 fi ;
+ for i=0 step chem_num2 until chem_num1 :
+ chem_pair2 := (unitvector(point i of chem_b_path[$]) scaled chem_num0)
+ transformed chem_t ;
+ if i=0 :
+ chem_pair3 := chem_pair2 ;
+ chem_num3 := 0 ;
+ elseif (abs(chem_pair1 shifted -chem_pair2)) <
+ (abs(chem_pair1 shifted -chem_pair3)) :
+ chem_pair3 := chem_pair2 ;
+ chem_num3 := i ;
+ fi
+ endfor
+ if not chem_front[$] : % adjust rotation
+ chem_rotation := (chem_rotation + angle(chem_pair1)-angle(chem_pair3)) mod 360 ;
+ fi ;
+ chem_t := identity chem_transformed($) ;
+ chem_pair4 := (point chem_num3 of chem_b_path[$]) transformed chem_t ;
+ if not chem_star[$] :
+ currentpicture := currentpicture shifted chem_pair4 ;
+ chem_origin := chem_origin shifted chem_pair4 ;
+ fi
+ fi
+ chem_substituent := 0 ;
+ fi ;
+ endfor
+ chem_previous := str $ ;
enddef ;
-vardef chem_r (expr n, f, t, r, c) =
- if n < 0 :
- chem_draw_vertical (n, chem_r_path[n], f, t, r, c) ;
+% line (f_rom, t_o, r_ule, c_olor)
+
+vardef chem_b@# (suffix $) (expr f, t, r, c) = % B
+ if chem_star[$] :
+ chem_r@#($,f,t,r,c) ;
+ elseif length(str @#)>0 :
+ chem_sb@#($,f,t,r,c) ;
else :
- chem_draw (n, chem_r_path[n], f, t, r, c) ;
- fi ;
+ chem_draw(
+ (subpath (f-1,t) of chem_b_path[$]) chem_transformed($),
+ r,c,) ;
+ fi
enddef ;
-vardef chem_rd (expr n, f, t, r, c) =
- chem_dashed_normal (n, chem_r_path[n], f, t, r, c)
+vardef chem_sb@# (suffix $) (expr f, t, r, c) = % SB
+ if chem_star[$] :
+ chem_sr@#($,f,t,r,c) ;
+ else :
+ %chem_draw(
+ % (subpath (f-1,t) of chem_b_path[$]) chem_transformed($),
+ % r,c,dashed chem_sb_dash@# scaled chem_b_length) ;
+ chem_t := identity chem_transformed($) ;
+ for i=f upto t :
+ chem_draw(
+ (subpath (chem_sb_pair@# shifted (i-1,i-1)) of chem_b_path[$])
+ transformed chem_t,
+ r,c,) ;
+ endfor
+ fi
enddef ;
-vardef chem_mrd (expr n, f, t, r, c) =
- chem_dashed_normal (n, chem_mr_path[n], f, t, r, c)
+vardef chem_sd@# (suffix $) (expr f, t, r, c) = % SD
+ if chem_star[$] :
+ chem_rd@#($,f,t,r,c) ;
+ else :
+ chem_t := identity chem_transformed($) ;
+ for i=f upto t :
+ chem_draw(
+ (subpath (chem_sb_pair@# shifted (i-1,i-1)) of chem_b_path[$])
+ transformed chem_t,
+ r,c,dashed evenly) ;
+ endfor
+ fi
enddef ;
-vardef chem_prd (expr n, f, t, r, c) =
- chem_dashed_normal (n, chem_pr_path[n], f, t, r, c)
+vardef chem_r_fragment@# (suffix $) (expr i) =
+ (
+ if chem_star[$] :
+ origin
+ else :
+ point i-1 of chem_b_path[$]
+ fi --
+ point i-1 of chem_r_path@#[$]
+ ) % no ;
enddef ;
-vardef chem_br (expr n, f, t, r, c) =
- chem_fill (n, chem_br_path[n], f, t, r, c )
+vardef chem_r@# (suffix $) (expr f, t, r, c) = % R
+ if length(str @#)>0 :
+ chem_sr@#($,f,t,r,c) ;
+ else :
+ chem_sr.b($,f,t,r,c) ;
+ fi
enddef ;
-vardef chem_rb (expr n, f, t, r, c) =
- chem_fill (n, chem_rb_path[n], f, t, r, c)
+vardef chem_er@# (suffix $) (expr f, t, r, c) = % ER
+ if length(str @#)>0:
+ chem_dr@#($,f,t,r,c) ;
+ else :
+ chem_dr.b($,f,t,r,c) ;
+ fi
enddef ;
-vardef chem_mrb (expr n, f, t, r, c) =
- chem_fill (n, chem_mrb_path[n], f, t, r, c)
+vardef chem_dr@# (suffix $) (expr f, t, r, c) = % DR
+ if not chem_front[$] :
+ chem_t := identity chem_transformed($) ;
+ for i=f upto t :
+ chem_path0 := (subpath chem_sb_pair@# of chem_r_fragment($,i)) ;
+ chem_draw(
+ (chem_path0 paralleled chem_dbl_offset) transformed chem_t,
+ r,c,) ;
+ chem_draw(
+ (chem_path0 paralleled -chem_dbl_offset) transformed chem_t,
+ r,c,) ;
+ endfor
+ fi
enddef ;
-vardef chem_prb (expr n, f, t, r, c) =
- chem_fill (n, chem_prb_path[n], f, t, r, c)
+vardef chem_lr@# (suffix $) (expr f, t, r, c) = % LR
+ if length(str @#)>0 :
+ chem_lsr@#($,f,t,r,c) ;
+ else :
+ chem_lsr.b($,f,t,r,c) ;
+ fi
enddef ;
-vardef chem_mr (expr n, f, t, r, c) =
- if n < 0 :
- chem_draw_vertical(n, chem_mr_path[n], f, t, r, c)
+vardef chem_rr@# (suffix $) (expr f, t, r, c) = % RR
+ if length(str @#)>0 :
+ chem_rsr@#($,f,t,r,c) ;
else :
- chem_draw (n, chem_mr_path[n], f, t, r, c)
+ chem_rsr.b($,f,t,r,c) ;
fi
enddef ;
-vardef chem_pr (expr n, f, t, r, c) =
- if n < 0 :
- chem_draw_vertical(n, chem_pr_path[n], f, t, r, c)
- else :
- chem_draw (n, chem_pr_path[n], f, t, r, c)
+vardef chem_eb@# (suffix $) (expr f, t, r, c) = % EB
+ if not chem_star[$] :
+ %chem_draw(
+ % ((subpath (f-1,t) of chem_b_path[$]) paralleled -2chem_dbl_offset)
+ % chem_transformed($),
+ % r,c,dashed chem_sb_dash scaled chem_b_length) ;
+ for i=f upto t :
+ chem_t := identity chem_transformed($) ;
+ chem_draw(
+ ((subpath (chem_sb_pair@# shifted (i-1,i-1)) of chem_b_path[$])
+ paralleled -2chem_dbl_offset) transformed chem_t,
+ r,c,) ;
+ endfor
fi
enddef ;
-vardef chem_sr (expr n, f, t, r, c) =
- chem_draw (n, chem_sr_path[n], f, t, r, c)
+vardef chem_ad@# (suffix $) (expr f, t, r, c) = % AD
+ if not chem_star[$] :
+ chem_t := identity chem_transformed($) ;
+ for i=f upto t :
+ chem_drawarrow(
+ ((subpath (chem_sb_pair@# shifted (i-1,i-1)) of chem_b_path[$])
+ paralleled 2chem_dbl_offset) transformed chem_t,
+ r,c,) ;
+ endfor
+ fi
enddef ;
-vardef chem_msr (expr n, f, t, r, c) =
- chem_draw (n, chem_msr_path[n], f, t, r, c)
+vardef chem_au@# (suffix $) (expr f, t, r, c) = % AU
+ if not chem_star[$] :
+ chem_t := identity chem_transformed($) ;
+ for i=f upto t :
+ chem_drawarrow(
+ reverse(
+ (subpath (chem_sb_pair@# shifted (i-1,i-1)) of chem_b_path[$])
+ paralleled 2chem_dbl_offset) transformed chem_t,
+ r,c,) ;
+ endfor
+ fi
enddef ;
-vardef chem_psr (expr n, f, t, r, c) =
- chem_draw (n, chem_psr_path[n], f, t, r, c)
+vardef chem_es@# (suffix $) (expr f, t, r, c) = % ES
+ if chem_star[$] :
+ chem_t := identity chem_transformed($) ;
+ for i=f upto t :
+ chem_draw(
+ ((point i-1 of chem_r_path[$]) scaled (xpart chem_sb_pair)) transformed chem_t,
+ chem_dot_factor*r,c,) ;
+ endfor
+ fi
enddef ;
-vardef chem_c (expr n, f, t, r, c) =
- chem_draw (n, chem_c_path[n], f, t, r, c)
+vardef chem_ed@# (suffix $) (expr f, t, r, c) = % ED
+ chem_t := identity chem_transformed($) ;
+ for i=f upto t :
+ if chem_star[$] :
+ chem_path0 := subpath chem_sb_pair of chem_r_fragment($,i) ;
+ chem_draw(
+ (point 0 of (chem_path0 paralleled -chem_dbl_offset)) transformed chem_t,
+ chem_dot_factor*r,c,) ;
+ chem_draw(
+ (point 0 of (chem_path0 paralleled chem_dbl_offset)) transformed chem_t,
+ chem_dot_factor*r,c,) ;
+ else :
+ chem_draw(
+ ((subpath (chem_sb_pair shifted (i-1,i-1)) of chem_b_path[$])
+ paralleled -2chem_dbl_offset) transformed chem_t,
+ r,c,dashed evenly) ;
+ fi
+ endfor
+enddef ;
+
+vardef chem_ep@# (suffix $) (expr f, t, r, c) = % EP
+ if chem_star[$] :
+ chem_t := identity chem_transformed($) ;
+ for i=f upto t :
+ chem_path0 := subpath chem_sb_pair of chem_r_fragment($,i) ;
+ chem_draw(
+ (point 0 of (chem_path0 paralleled -chem_dbl_offset) --
+ point 0 of (chem_path0 paralleled chem_dbl_offset)) transformed chem_t,
+ r,c,) ;
+ endfor
+ fi
enddef ;
-vardef chem_cc (expr n, f, t, r, c) =
- chem_draw (n, chem_cc_path[n], f, f, r, c)
+vardef chem_et@# (suffix $) (expr f, t, r, c) = % ET
+ if chem_star[$] :
+ chem_t := identity chem_transformed($) ;
+ for i=f upto t :
+ chem_path0 := subpath chem_sb_pair of chem_r_fragment($,i) ;
+ chem_draw(
+ (point 0 of (chem_path0 paralleled -2chem_dbl_offset)) transformed chem_t,
+ chem_dot_factor*r,c,) ;
+ chem_draw(
+ (point 0 of chem_path0) transformed chem_t,
+ chem_dot_factor*r,c,) ;
+ chem_draw(
+ (point 0 of (chem_path0 paralleled 2chem_dbl_offset)) transformed chem_t,
+ chem_dot_factor*r,c,) ;
+ endfor
+ fi
enddef ;
-vardef chem_cd (expr n, f, t, r, c) =
- chem_dashed_connected (n, chem_c_path[n], f, t, r, c)
+vardef chem_db@# (suffix $) (expr f, t, r, c) = % DB
+ if chem_star[$] :
+ chem_dr@#($,f,t,r,c) ;
+ elseif not chem_front[$] :
+ chem_t := identity chem_transformed($) ;
+ %chem_draw(
+ % ((subpath (f-1,t) of chem_b_path[$]) paralleled -chem_dbl_offset)
+ % transformed chem_t,
+ % r,c,dashed chem_sb_dash@# scaled chem_b_length) ;
+ %chem_draw(
+ % ((subpath (f-1,t) of chem_b_path[$]) paralleled chem_dbl_offset)
+ % transformed chem_t,
+ % r,c,dashed chem_sb_dash@# scaled chem_b_length) ;
+ for i=f upto t :
+ chem_path0 := subpath (chem_sb_pair@# shifted (i-1,i-1)) of chem_b_path[$] ;
+ chem_draw(
+ (chem_path0 paralleled -chem_dbl_offset) transformed chem_t,
+ r,c,) ;
+ chem_draw(
+ (chem_path0 paralleled chem_dbl_offset) transformed chem_t,
+ r,c,) ;
+ % todo : this should be cut-off where it overlaps a neighboring standard bond.
+ endfor
+ fi
enddef ;
-vardef chem_ccd (expr n, f, t, r, c) =
- chem_dashed_normal (n, chem_cc_path[n], f, f, r, c)
+vardef chem_tb@# (suffix $) (expr f, t, r, c) = % TB
+ if chem_star[$] :
+ chem_t := identity chem_transformed($) ;
+ for i=f upto t :
+ chem_path0 := subpath chem_sb_pair@# of chem_r_fragment($,i) ;
+ chem_draw(
+ (chem_path0 paralleled -2chem_dbl_offset) transformed chem_t,
+ r,c,) ;
+ chem_draw(
+ chem_path0 transformed chem_t,
+ r,c,) ;
+ chem_draw(
+ (chem_path0 paralleled 2chem_dbl_offset) transformed chem_t,
+ r,c,) ;
+ endfor
+ fi
enddef ;
-vardef chem_rn (expr n, i, t) =
- chem_rt (n,i,t) ;
+vardef chem_sr@# (suffix $) (expr f, t, r, c) = % SR
+ chem_t := identity chem_transformed($) ;
+ if chem_stacked[$] :
+ chem_num0 := length chem_b_path[$] ; chem_num1 := floor(.5chem_num0) ;
+ for i=f upto t :
+ chem_draw(
+ (subpath (if i>chem_num1: .5,ypart fi chem_sb_pair@#) of chem_r_fragment($,i))
+ transformed chem_t,
+ r,c,) ;
+ endfor
+ else :
+ for i=f upto t :
+ chem_draw(
+ (subpath chem_sb_pair@# of chem_r_fragment($,i))
+ transformed chem_t,
+ r,c,) ;
+ endfor
+ fi
enddef ;
-vardef chem_rtn (expr n, i, t) =
- chem_rtt(n,i,t) ;
+vardef chem_rd@# (suffix $) (expr f, t, r, c) = % RD
+ chem_t := identity chem_transformed($) ;
+ if chem_stacked[$] :
+ chem_num0 := length chem_b_path[$] ; chem_num1 := floor(.5chem_num0) ;
+ for i=f upto t :
+ chem_draw(
+ (subpath (if i>chem_num1: .5,ypart fi chem_sb_pair@#) of chem_r_fragment($,i))
+ transformed chem_t,
+ r,c,dashed evenly) ;
+ endfor
+ else :
+ for i=f upto t :
+ chem_draw(
+ (subpath chem_sb_pair@# of chem_r_fragment($,i))
+ transformed chem_t,
+ r,c,dashed evenly) ;
+ endfor
+ fi
enddef ;
-vardef chem_rbn (expr n, i, t) =
- chem_rbt(n,i,t) ;
+vardef chem_rh@# (suffix $) (expr f, t, r, c) = % RH
+ chem_t := identity chem_transformed($) ;
+ for i=f upto t :
+ chem_draw(
+ (subpath chem_sb_pair@# of chem_r_fragment($,i))
+ transformed chem_t,
+ chem_dot_factor*r,c,dashed withdots scaled ((.5chem_b_length/3)/5bp)) ;
+ % not symmetric - needs to be tweaked...
+ endfor
+enddef ;
+
+vardef chem_lrh@# (suffix $) (expr f, t, r, c) = % LRH
+ chem_t := identity chem_transformed($) ;
+ for i=f upto t :
+ chem_draw(
+ (subpath chem_sb_pair@# of chem_r_fragment.lft($,i))
+ transformed chem_t,
+ chem_dot_factor*r,c,dashed withdots scaled ((.5chem_b_length/3)/5bp)) ;
+ % not symmetric - needs to be tweaked...
+ endfor
+enddef ;
+
+vardef chem_rrh@# (suffix $) (expr f, t, r, c) = % RRH
+ chem_t := identity chem_transformed($) ;
+ for i=f upto t :
+ chem_draw(
+ (subpath chem_sb_pair@# of chem_r_fragment.rt($,i))
+ transformed chem_t,
+ chem_dot_factor*r,c,dashed withdots scaled ((.5chem_b_length/3)/5bp)) ;
+ % not symmetric - needs to be tweaked...
+ endfor
+enddef ;
+
+vardef chem_hb@# (suffix $) (expr f, t, r, c) = % HB
+ if chem_star[$] :
+ chem_rh@#($,f,t,r,c)
+ fi
enddef ;
-vardef chem_tb (expr n, f, t, r, c) = % one
- chem_draw (n, chem_msb_path[n], f, t, r, c) ;
- chem_draw (n, chem_sb_path [n], f, t, r, c) ;
- chem_draw (n, chem_psb_path[n], f, t, r, c) ;
+vardef chem_bb@# (suffix $) (expr f, t, r, c) = % BB
+ if chem_star[$] :
+ chem_rb@#($,f,t,r,c) ;
+ elseif chem_front[$] :
+ chem_t := identity chem_transformed($) ;
+ chem_draw(
+ (subpath (f-1,t) of chem_b_path[$]) transformed chem_t,
+ r,c,) ;
+ chem_num0 := length chem_b_path[$] ; % total number of bonds
+ chem_num1 := chem_front_b[$] ; % number of bonds to be made bold
+ % bold bonds within f and t
+ chem_num2 := if f<0 :((f+1) mod chem_num0) + chem_num0 else : ((f-1) mod chem_num0) + 1 fi ;
+ chem_num3 := if t<0 :((t+1) mod chem_num0) + chem_num0 else : ((t-1) mod chem_num0) + 1 fi ;
+ if chem_num31) :
+ chem_path0 := subpath (if chem_num2>2 : chem_num2-1 else : 1 fi,
+ if chem_num3=chem_num1 :
+ chem_fill(
+ (point chem_num1 of chem_b_path[$] --
+ point chem_num1-1 of chem_b_path[$] shifted (0,-chem_dbl_offset) --
+ point chem_num1-1 of chem_b_path[$] shifted (0, chem_dbl_offset) --
+ cycle) transformed chem_t,
+ r,c,) ;
+ fi
+ fi
+ fi
enddef ;
-vardef chem_ep (expr n, f, t, r, c) = % one
- chem_draw (n, chem_e_path[n], f, t, r, c) ;
+vardef chem_rb@# (suffix $) (expr f, t, r, c) = % RB
+ chem_t := identity chem_transformed($) ;
+ for i=f upto t :
+ chem_path0 := subpath chem_sb_pair@# of chem_r_fragment($,i) ;
+ chem_fill(
+ (point 0 of chem_path0 --
+ point 1 of chem_path0
+ rotatedaround(point 0 of chem_path0, -chem_bb_angle) --
+ point 1 of chem_path0
+ rotatedaround(point 0 of chem_path0, chem_bb_angle) --
+ cycle) transformed chem_t,
+ r,c,) ;
+ endfor
+enddef ;
+
+vardef chem_lrb@# (suffix $) (expr f, t, r, c) = % LRB
+ if not chem_star[$] :
+ chem_t := identity chem_transformed($) ;
+ for i=f upto t :
+ chem_path0 := subpath chem_sb_pair@# of chem_r_fragment.lft($,i) ;
+ chem_fill(
+ (point 0 of chem_path0 --
+ point 1 of chem_path0
+ rotatedaround(point 0 of chem_path0, -chem_bb_angle) --
+ point 1 of chem_path0
+ rotatedaround(point 0 of chem_path0, chem_bb_angle) --
+ cycle) transformed chem_t,
+ r,c,) ;
+ endfor
+ fi
enddef ;
-vardef chem_es (expr n, f, t, r, c) = % one
- chem_draw_dot (n, center chem_e_path[n], f, t, r, c) ;
+vardef chem_rrb@# (suffix $) (expr f, t, r, c) = % RRB
+ if not chem_star[$] :
+ chem_t := identity chem_transformed($) ;
+ for i=f upto t :
+ chem_path0 := subpath chem_sb_pair@# of chem_r_fragment.rt($,i) ;
+ chem_fill(
+ (point 0 of chem_path0 --
+ point 1 of chem_path0
+ rotatedaround(point 0 of chem_path0, -chem_bb_angle) --
+ point 1 of chem_path0
+ rotatedaround(point 0 of chem_path0, chem_bb_angle) --
+ cycle) transformed chem_t,
+ r,c,) ;
+ endfor
+ fi
enddef ;
-vardef chem_ed (expr n, f, t, r, c) = % one
- chem_draw_dot (n, point 0 of chem_e_path[n], f, t, r, c) ;
- chem_draw_dot (n, point 1 of chem_e_path[n], f, t, r, c) ;
+vardef chem_lsr@# (suffix $) (expr f, t, r, c) = % LSR
+ if not chem_star[$] :
+ chem_t := identity chem_transformed($) ;
+ for i=f upto t :
+ chem_draw(
+ (subpath chem_sb_pair@# of chem_r_fragment.lft($,i)) transformed chem_t,
+ r,c,) ;
+ endfor
+ fi
enddef ;
-vardef chem_et (expr n, f, t, r, c) = % one
- chem_draw_dot (n, point 0 of chem_e_path[n], f, t, r, c) ;
- chem_draw_dot (n, center chem_e_path[n], f, t, r, c) ;
- chem_draw_dot (n, point 1 of chem_e_path[n], f, t, r, c) ;
+vardef chem_rsr@# (suffix $) (expr f, t, r, c) = % RSR
+ if not chem_star[$] :
+ chem_t := identity chem_transformed($) ;
+ for i=f upto t :
+ chem_draw(
+ (subpath chem_sb_pair@# of chem_r_fragment.rt($,i)) transformed chem_t,
+ r,c,) ;
+ endfor
+ fi
enddef ;
-vardef chem_sd (expr n, f, t, r, c) = % one
- chem_draw (n, chem_ddt_path[n], f, t, r, c) ;
- chem_draw (n, chem_ddb_path[n], f, t, r, c) ;
+vardef chem_lrd@# (suffix $) (expr f, t, r, c) = % LRD
+ if not chem_star[$] :
+ chem_t := identity chem_transformed($) ;
+ for i=f upto t :
+ chem_draw(
+ (subpath chem_sb_pair@# of chem_r_fragment.lft($,i)) transformed chem_t,
+ r,c,dashed evenly) ;
+ endfor
+ fi
enddef ;
-vardef chem_rdd (expr n, f, t, r, c) = % one
- chem_draw (n, chem_ldt_path[n], f, t, r, c) ;
- chem_draw (n, chem_ldb_path[n], f, t, r, c) ;
- chem_draw (n, chem_psb_path[n], f, t, r, c) ;
+vardef chem_rrd@# (suffix $) (expr f, t, r, c) = % RRD
+ if not chem_star[$] :
+ chem_t := identity chem_transformed($) ;
+ for i=f upto t :
+ chem_draw(
+ (subpath chem_sb_pair@# of chem_r_fragment.rt($,i)) transformed chem_t,
+ r,c,dashed evenly) ;
+ endfor
+ fi
enddef ;
-vardef chem_ldd (expr n, f, t, r, c) = % one
- chem_draw (n, chem_msb_path[n], f, t, r, c) ;
- chem_draw (n, chem_rdt_path[n], f, t, r, c) ;
- chem_draw (n, chem_rdb_path[n], f, t, r, c) ;
+vardef chem_s@# (suffix $) (expr f, t, r, c) = % S
+ if length(str @#)>0 :
+ chem_ss@#($,f,t,r,c) ;
+ else :
+ chem_ss.b($,f,t,r,c) ;
+ fi
enddef ;
-vardef chem_hb (expr n, f, t, r, c) = % one
- chem_draw_dot (n, point 0 of chem_sb_path[n], f, t, r, c) ;
- chem_draw_dot (n, center chem_sb_path[n], f, t, r, c) ;
- chem_draw_dot (n, point 1 of chem_sb_path[n], f, t, r, c) ;
+vardef chem_ss@# (suffix $) (expr f, t, r, c) = % SS
+ if not (chem_star[$] or chem_front[$]) :
+ chem_draw(
+ subpath chem_sb_pair@# of (point f-2 of chem_b_path[$] -- point t of chem_b_path[$])
+ chem_transformed($),
+ r,c,) ;
+ fi
enddef ;
-vardef chem_bb (expr n, f, t, r, c) = % one
- if n < 0 :
- chem_fill (n, chem_bb_path[n], 1, 1, r, c) ;
- chem_b (n, f, t, r, c) ;
+vardef chem_mid@# (suffix $) (expr f, t, r, c) = % MID
+ if length(str @#)>0 :
+ chem_mids@#($,f,t,r,c) ;
else :
- chem_fill (n, chem_bb_path[n], f, t, r, c) ;
- fi ;
+ chem_mids.b($,f,t,r,c) ;
+ fi
enddef ;
-vardef chem_oe (expr n, f, t, r, c) = % one
- chem_draw (n, chem_oe_path[n], f, t, r, c) ;
+vardef chem_mids@# (suffix $) (expr f, t, r, c) = % MIDS
+ if not (chem_star[$] or chem_front[$]) :
+ chem_t := identity chem_transformed($) ;
+ for i=f upto t :
+ chem_draw(
+ (subpath chem_sb_pair@# of (origin -- point i-1 of chem_b_path[$]))
+ transformed chem_t,
+ r,c,) ;
+ endfor
+ fi
enddef ;
-vardef chem_bd (expr n, f, t, r, c) = % one
- for i=0 upto 5 :
- chem_draw (n, subpath (2i,2i+1) of chem_bd_path[n], f, t, r, c) ;
- endfor ;
+vardef chem_cd (suffix $) (expr r, c) = % CD
+ chem_draw(
+ chem_c_path[$] chem_transformed($),
+ r,c,dashed evenly) ;
enddef ;
-vardef chem_bw (expr n, f, t, r, c) = % one
- chem_draw (n, chem_bw_path[n], f, t, r, c) ;
+vardef chem_c (suffix $) (expr r, c) = % C
+ chem_draw(
+ chem_c_path[$] chem_transformed($),
+ r,c,) ;
enddef ;
-vardef chem_z_zero@#(text t) =
- chem_text@#(t, chem_do(origin)) ;
+vardef chem_ccd (suffix $) (expr f, t, r, c) = % CCD
+ chem_num0 := ypart((origin--center(subpath (f-2,f-1) of chem_b_path[$]))
+ intersectiontimes chem_c_path[$]) ;
+ chem_num1 := ypart((origin--center(subpath (t-1,t) of chem_b_path[$]))
+ intersectiontimes chem_c_path[$]) ;
+ if chem_num1>chem_num0 :
+ chem_num0 := chem_num0 + length chem_c_path[$] ;
+ fi
+ chem_draw(
+ subpath (chem_num1,chem_num0) of chem_c_path[$] chem_transformed($),
+ r,c,dashed evenly) ;
+enddef ;
+
+vardef chem_cc (suffix $) (expr f, t, r, c) = % CC
+ chem_num0 := ypart((origin--center(subpath (f-2,f-1) of chem_b_path[$]))
+ intersectiontimes chem_c_path[$]) ;
+ chem_num1 := ypart((origin--center(subpath (t-1,t) of chem_b_path[$]))
+ intersectiontimes chem_c_path[$]) ;
+ if chem_num1>chem_num0 :
+ chem_num0 := chem_num0 + length chem_c_path[$] ;
+ fi
+ chem_draw(
+ subpath (chem_num1,chem_num0) of chem_c_path[$] chem_transformed($),
+ r,c,) ;
+enddef ;
+
+vardef chem_ldb@# (suffix $) (expr f, t, r, c) = % LD
+ if chem_star[$] :
+ chem_t := identity chem_transformed($) ;
+ for i=f upto t :
+ chem_path0 := subpath chem_sb_pair@# of chem_r_fragment($,i) ;
+ chem_draw(
+ chem_path0 transformed chem_t,
+ r,c,) ;
+ chem_draw(
+ (chem_path0 paralleled 2chem_dbl_offset) transformed chem_t,
+ r,c,) ;
+ endfor
+ fi
enddef ;
-vardef chem_cz_zero@#(text t) =
- chem_text@#(t, chem_do(origin)) ;
+vardef chem_rdb@# (suffix $) (expr f, t, r, c) = % LD
+ if chem_star[$] :
+ chem_t := identity chem_transformed($) ;
+ for i=f upto t :
+ chem_path0 := subpath chem_sb_pair@# of chem_r_fragment($,i) ;
+ chem_draw(
+ chem_path0 transformed chem_t,
+ r,c,) ;
+ chem_draw(
+ (chem_path0 paralleled -2chem_dbl_offset) transformed chem_t,
+ r,c,) ;
+ endfor
+ fi
enddef ;
-vardef chem_z@#(expr n, p) (text t) =
- if p = 0 :
- chem_text@#(t, chem_do(origin)) ;
- else :
- chem_text@#(t, chem_do(chem_b_zero[n] rotated chem_ang(n,p))) ;
- fi ;
+vardef chem_ldd@# (suffix $) (expr f, t, r, c) = % LDD
+ if chem_star[$] :
+ chem_t := identity chem_transformed($) ;
+ for i=f upto t :
+ chem_path0 := subpath chem_sb_pair@# of chem_r_fragment($,i) ;
+ chem_draw(
+ chem_path0 transformed chem_t,
+ r,c,) ;
+ chem_draw(
+ (chem_path0 paralleled 2chem_dbl_offset) transformed chem_t,
+ r,c,dashed evenly) ;
+ endfor
+ fi
enddef ;
-vardef chem_cz@#(expr n, p) (text t) =
- if n = 1 :
- chem_c_text(t, chem_do(chem_crz_zero[n] rotated chem_ang(n,p))) ;
- else :
- chem_text@#(t, chem_do(chem_b_zero[n] rotated chem_ang(n,p))) ;
- fi ;
+vardef chem_rdd@# (suffix $) (expr f, t, r, c) = % RDD
+ if chem_star[$] :
+ chem_t := identity chem_transformed($) ;
+ for i=f upto t :
+ chem_path0 := subpath chem_sb_pair@# of chem_r_fragment($,i) ;
+ chem_draw(
+ chem_path0 transformed chem_t,
+ r,c,) ;
+ chem_draw(
+ (chem_path0 paralleled -2chem_dbl_offset) transformed chem_t,
+ r,c,dashed evenly) ;
+ endfor
+ fi
enddef ;
-vardef chem_midz@#(expr n, p) (text t) =
- chem_text@#(t, chem_do(chem_mid_zero[n] rotated chem_ang(n,p))) ;
+vardef chem_oe@# (suffix $) (expr f, t, r, c) = % OE
+ if chem_star[$] :
+ chem_t := identity chem_transformed($) ;
+ for i=f upto t :
+ chem_path0 := subpath chem_sb_pair@# of chem_r_fragment($,i) ;
+ chem_path1 := chem_path0 paralleled -.5chem_dbl_offset ;
+ chem_path2 := chem_path0 paralleled .5chem_dbl_offset ;
+ chem_draw(
+ ( point 0 of chem_path0 --
+ .2[point 0 of chem_path0, point infinity of chem_path0]..
+ .3[point 0 of chem_path1, point infinity of chem_path1]..
+ .4[point 0 of chem_path0, point infinity of chem_path0]..
+ .5[point 0 of chem_path2, point infinity of chem_path2]..
+ .6[point 0 of chem_path0, point infinity of chem_path0]..
+ .7[point 0 of chem_path1, point infinity of chem_path1]..
+ .8[point 0 of chem_path0, point infinity of chem_path0]--
+ point infinity of chem_path0) transformed chem_t,
+ r,c,) ;
+ endfor
+ fi
enddef ;
-vardef chem_rz@#(expr n, p) (text t) =
- if n < 0 :
- % quite special
- chem_text@#(t, chem_do(chem_r_zero[n] shifted (chem_b_zero[n] rotated chem_ang(n,p)))) ;
- else :
- chem_text@#(t, chem_do(chem_r_zero[n] rotated chem_ang(n,p))) ;
- fi ;
+vardef chem_bw@# (suffix $) (expr f, t, r, c) = % BW
+ if chem_star[$] :
+ chem_t := identity chem_transformed($) ;
+ for i=f upto t :
+ chem_path0 := subpath chem_sb_pair@# of chem_r_fragment($,i) ;
+ chem_path1 := chem_path0 paralleled -.5chem_dbl_offset ;
+ chem_path2 := chem_path0 paralleled .5chem_dbl_offset ;
+ chem_draw(
+ ( point 0 of chem_path0..
+ .1[point 0 of chem_path1, point infinity of chem_path1]..
+ .2[point 0 of chem_path0, point infinity of chem_path0]..
+ .3[point 0 of chem_path2, point infinity of chem_path2]..
+ .4[point 0 of chem_path0, point infinity of chem_path0]..
+ .5[point 0 of chem_path1, point infinity of chem_path1]..
+ .6[point 0 of chem_path0, point infinity of chem_path0]..
+ .7[point 0 of chem_path2, point infinity of chem_path2]..
+ .8[point 0 of chem_path0, point infinity of chem_path0]..
+ .9[point 0 of chem_path1, point infinity of chem_path1]..
+ point infinity of chem_path0) transformed chem_t,
+ r,c,) ;
+ endfor
+ fi
enddef ;
-vardef chem_crz@#(expr n, p) (text tx) =
- chem_text(tx, chem_do(chem_crz_zero[n] rotated chem_ang(n,p))) ;
+vardef chem_bd@# (suffix $) (expr f, t, r, c) = % BD
+ if chem_star[$] : chem_rbd#@($,f,t,r,c) ; fi
enddef ;
-vardef chem_mrz@#(expr n, p) (text t) =
- if n < 0 :
- % quite special
- chem_text@#(t, chem_do(chem_mr_zero[n] shifted (chem_b_zero[n] rotated chem_ang(n,p)))) ;
- else :
- chem_text@#(t, chem_do(chem_mr_zero[n] rotated chem_ang(n,p))) ;
- fi ;
+vardef chem_rbd@# (suffix $) (expr f, t, r, c) = % RBD
+ chem_t := identity chem_transformed($) ;
+ for i=f upto t :
+ chem_path0 := subpath chem_sb_pair@# of chem_r_fragment($,i) ;
+ if chem_bd_wedge :
+ chem_path1 := chem_path0 rotated -chem_bb_angle ;
+ chem_path2 := chem_path0 rotated chem_bb_angle ;
+ else :
+ chem_path1 := chem_path0 paralleled -chem_dbl_offset ;
+ chem_path2 := chem_path0 paralleled chem_dbl_offset ;
+ fi
+ for j=0 upto 3 :
+ chem_draw(
+ (point (j/3) of chem_path1 -- point (j/3) of chem_path2) transformed chem_t,
+ 2r,c,) ;
+ endfor
+ endfor
+enddef ;
+
+vardef chem_lrbd@# (suffix $) (expr f, t, r, c) = % LRBD
+ if not chem_star[$] :
+ chem_t := identity chem_transformed($) ;
+ for i=f upto t :
+ chem_path0 := subpath chem_sb_pair@# of chem_r_fragment.lft($,i) ;
+ if chem_bd_wedge :
+ chem_path1 := chem_path0 rotated -chem_bb_angle ;
+ chem_path2 := chem_path0 rotated chem_bb_angle ;
+ else :
+ chem_path1 := chem_path0 paralleled -.5chem_dbl_offset ;
+ chem_path2 := chem_path0 paralleled .5chem_dbl_offset ;
+ fi
+ for j=0 upto 3 :
+ chem_draw(
+ (point (j/3) of chem_path1 -- point (j/3) of chem_path2) transformed chem_t,
+ 2r,c,) ;
+ endfor
+ endfor
+ fi
enddef ;
-vardef chem_prz@#(expr n, p) (text t) =
- if n < 0 :
- % quite special
- chem_text@#(t, chem_do(chem_pr_zero[n] shifted (chem_b_zero[n] rotated chem_ang(n,p)))) ;
- else :
- chem_text@#(t, chem_do(chem_pr_zero[n] rotated chem_ang(n,p))) ;
- fi ;
+vardef chem_rrbd@# (suffix $) (expr f, t, r, c) = % RRBD
+ if not chem_star[$] :
+ chem_t := identity chem_transformed($) ;
+ for i=f upto t :
+ chem_path0 := subpath chem_sb_pair@# of chem_r_fragment.rt($,i) ;
+ if chem_bd_wedge :
+ chem_path1 := chem_path0 rotated -chem_bb_angle ;
+ chem_path2 := chem_path0 rotated chem_bb_angle ;
+ else :
+ chem_path1 := chem_path0 paralleled -.5chem_dbl_offset ;
+ chem_path2 := chem_path0 paralleled .5chem_dbl_offset ;
+ fi
+ for j=0 upto 3 :
+ chem_draw(
+ (point (j/3) of chem_path1 -- point (j/3) of chem_path2) transformed chem_t,
+ 2r,c,) ;
+ endfor
+ endfor
+ fi
enddef ;
-vardef chem_rt@#(expr n, p) (text t) =
- chem_text@#(t, chem_do(chem_rt_zero[n] rotated chem_ang(n,p))) ;
+% text, number (no alignment on number);
+
+vardef chem_z@#(suffix $) (expr p) (text t) = % Z
+ draw chem_text@#
+ (t,chem_do(
+ if p=0 :
+ origin
+ else :
+ (point p-1 of chem_b_path[$]) chem_transformed($)
+ fi
+ )) ;
enddef ;
-vardef chem_rtt@#(expr n, p) (text t) =
- chem_text@#(t, chem_do(chem_rtt_zero[n] rotated chem_ang(n,p))) ;
+vardef chem_cz@#(suffix $) (expr p) (text t) = chem_z@#($,p,t) ; enddef ; % CZ ?
+
+vardef chem_midz@#(suffix $) (expr p) (text t) = % MIDZ
+ if not (chem_star[$] or chem_front[$]) :
+ draw chem_text@#
+ (t,chem_do(
+ (xpart chem_sb_pair, 0) scaled (xpart point 0 of chem_b_path[$])
+ chem_transformed($)
+ )) ;
+ fi
enddef ;
-vardef chem_rbt@#(expr n, p) (text t) =
- chem_text@#(t, chem_do(chem_rbt_zero[n] rotated chem_ang(n,p))) ;
+vardef chem_rz@#(suffix $) (expr p) (text t) = % RZ
+ draw chem_text@#
+ (t, chem_do((point p-1 of chem_r_path[$]) chem_transformed($))) ;
enddef ;
-vardef chem_zt@#(expr n, p) (text t) =
- if n = 1 :
- chem_text@#(t, chem_do(chem_rt_zero[n] rotated chem_ang(n,p))) ;
- else :
- chem_text@#(t, chem_do(chem_n_zero[n] rotated chem_ang(n,p))) ;
- fi ;
+vardef chem_lrz@#(suffix $) (expr p) (text t) = % LRZ
+ if not chem_star[$] :
+ draw chem_text@#
+ (t,
+ chem_do((point p-1 of chem_r_path.lft[$]) chem_transformed($))) ;
+ fi
enddef ;
-vardef chem_zn@#(expr n, p) (text t) =
- if n = 1 :
- chem_text@#(t, chem_do(chem_rt_zero[n] rotated chem_ang(n,p))) ;
- else :
- chem_text@#(t, chem_do(chem_n_zero[n] rotated chem_ang(n,p))) ;
- fi ;
+vardef chem_rrz@#(suffix $) (expr p) (text t) = % RRZ
+ if not chem_star[$] :
+ draw chem_text@#
+ (t, chem_do((point p-1 of chem_r_path.rt[$]) chem_transformed($))) ;
+ fi
enddef ;
-vardef chem_zbt@#(expr n, p) (text t) =
- chem_text@#(t, chem_do(chem_rtt_zero[n] rotated chem_ang(n,p))) ;
+vardef chem_zn@#(suffix $) (expr p) (text t) = % ZN
+ chem_zt($,p,t) ;
enddef ;
-vardef chem_zbn@#(expr n, p) (text t) =
- chem_text@#(t, chem_do(chem_rtt_zero[n] rotated chem_ang(n,p))) ;
+vardef chem_zt@#(suffix $) (expr p) (text t) = % ZT
+ draw chem_text@#(t,chem_do ((point p-1 of chem_b_path[$]) chem_transformed($)
+ scaled chem_text_min)) ;
enddef ;
-vardef chem_ztt@#(expr n, p) (text t) =
- chem_text@#(t, chem_do(chem_rbt_zero[n] rotated chem_ang(n,p))) ;
+vardef chem_zln@#(suffix $) (expr p) (text t) = % ZLN
+ chem_zlt($,p,t) ;
enddef ;
-vardef chem_ztn@#(expr n, p) (text t) =
- chem_text@#(t, chem_do(chem_rbt_zero[n] rotated chem_ang(n,p))) ;
+vardef chem_zlt@#(suffix $) (expr p) (text t) = % ZLT
+ draw chem_text@#(t, chem_do((point p-1.5 of chem_b_path[$]) chem_transformed($)
+ scaled chem_text_min)) ;
enddef ;
-vardef chem_symbol(expr t) =
- draw textext(t) ;
+vardef chem_zrn@#(suffix $) (expr p) (text t) = % ZRN
+ chem_zrt($,p,t) ;
enddef ;
-vardef chem_text@#(expr txt, z) = % adapted copy of thelabel@
- save p ; picture p ;
- p := textext(txt) ;
- p := p
- if (mfun_labtype@# >= 10) : shifted (0,ypart center p) fi
- shifted (z + chem_text_offset*mfun_laboff@# - (mfun_labxf@#*lrcorner p + mfun_labyf@#*ulcorner p + (1-mfun_labxf@#-mfun_labyf@#)*llcorner p)) ;
- if chem_text_trace :
- draw z withpen pencircle scaled 2pt withcolor red ;
- draw boundingbox p withpen pencircle scaled 1pt withcolor red ;
- fi ;
- draw p
+vardef chem_zrt@#(suffix $) (expr p) (text t) = % ZRT
+ draw chem_text@#(t, chem_do((point p-0.5 of chem_b_path[$]) chem_transformed($)
+ scaled chem_text_min)) ;
enddef ;
-vardef chem_c_text(expr txt, z) = % adapted copy of thelabel@
- save p ; picture p ; p := textext(txt) ;
- save b ; path b ; b := (boundingbox p) shifted z ;
- save a ; pair a ; a := (origin--z) intersection_point b ;
- if intersection_found :
- draw p shifted (z enlonged arclength(a -- center b)) ;
- else :
- draw p shifted z ;
+vardef chem_crz@#(suffix $) (expr p) (text t) = % CRZ ????
+ if chem_star[$] :
+ draw chem_text@#(t, chem_do((point p-1 of chem_b_path[$] enlonged chem_center_offset)
+ chem_transformed($))) ;
fi
-% draw b withcolor green ;
-% draw a withcolor red ;
enddef ;
-vardef chem_ang (expr n, d) =
- ((-1 * (d-1) * chem_angle[n]) + (-chem_rotation+1) * 90 + chem_start[n]) % no ;
+vardef chem_rn@#(suffix $) (expr i, t) = % RN
+ chem_rt($,i,t) ;
enddef ;
-vardef chem_rot (expr n, d) =
- chem_rotation := d ;
+vardef chem_rt@#(suffix $) (expr p) (text t) = % RT
+ draw chem_text@#(t, chem_do((center chem_r_fragment($,p)) chem_transformed($))) ;
enddef ;
-vardef chem_adj (expr n, d) =
- chem_adjacent := d ;
+vardef chem_lrn@#(suffix $) (expr i, t) = % LRN
+ chem_lrt($,i,t) ;
enddef ;
-vardef chem_sub (expr n, d) =
- chem_substituent := d ;
+vardef chem_lrt@#(suffix $) (expr p) (text t) = % LRT
+ draw chem_text@#(t, chem_do((center chem_r_fragment.lft($,p)) chem_transformed($))) ;
enddef ;
-vardef chem_dir (expr n, d) =
- if n = 1 :
- chem_direction_p := (origin - 2*center(chem_b_path[n] rotated chem_ang(n,d+1))) ;
- currentpicture := currentpicture shifted chem_direction_p ;
- chem_shift := chem_shift + chem_direction_p ;
- fi ;
+vardef chem_rrn@# (suffix $) (expr i, t) = % RRN
+ chem_rrt($,i,t) ;
enddef ;
-vardef chem_mov (expr n, d) =
- if d = 0 :
- currentpicture := currentpicture shifted - chem_shift ;
- chem_shift := origin ;
- else :
- chem_move_p := (origin - 2*center(chem_b_path[n] rotated chem_ang(n,d+chem_initialmov[n]))) ;
- currentpicture := currentpicture shifted chem_move_p ;
- chem_shift := chem_shift + chem_move_p ;
- fi ;
+vardef chem_rrt@#(suffix $) (expr p) (text t) = % RRT
+ draw chem_text@#(t, chem_do((center chem_r_fragment.rt($,p)) chem_transformed($))) ;
enddef ;
-vardef chem_off (expr n, d) =
- if (d = 1) or (d = 2) or (d = 8) : % positive
- currentpicture := currentpicture shifted (-chem_setting_offset,0) ;
- chem_shift := chem_shift + (-chem_setting_offset,0)
- elseif (d = 4) or (d = 5) or (d = 6) : % negative
- currentpicture := currentpicture shifted ( chem_setting_offset,0) ;
- chem_shift := chem_shift + ( chem_setting_offset,0)
- fi ;
+vardef chem_symbol(expr t) = draw textext(t) ; enddef ;
+
+vardef chem_align@#(expr pic) =
+ pic
+ if (mfun_labtype@# >= 10) :
+ shifted (0,ypart center pic)
+ fi
+ shifted (-(mfun_labxf@#*lrcorner pic + mfun_labyf@#*ulcorner pic + (1-mfun_labxf@#-mfun_labyf@#)*llcorner pic))
enddef ;
-vardef chem_set(expr n, m) =
- if chem_adjacent > 0 :
- chem_adjacent_d := xpart chem_b_zero[n] + xpart chem_b_zero[m] ;
- if chem_adjacent = 1 : chem_adjacent_p := (-chem_adjacent_d, 0) ;
- elseif chem_adjacent = 2 : chem_adjacent_p := (0, -chem_adjacent_d) ;
- elseif chem_adjacent = 3 : chem_adjacent_p := ( chem_adjacent_d, 0) ;
- elseif chem_adjacent = 4 : chem_adjacent_p := (0, chem_adjacent_d) ;
- else : chem_adjacent_p := origin ;
- fi ;
- currentpicture := currentpicture shifted chem_adjacent_p ;
- chem_shift := chem_shift + chem_adjacent_p ;
- chem_adjacent := 0 ;
- fi ;
- if chem_substituent > 0 :
- if m = 1 :
- chem_substituent_d := xpart chem_crz_zero[n] + chem_substituent_offset ;
+vardef chem_text@#(expr txt, z) =
+ chem_pic := textext(txt) ;
+ if length(str @#)=0 :
+ chem_pic := chem_align(chem_pic) ;
+ elseif (str @#) = "auto" :
+ if z<>origin :
+ chem_num0 := abs(angle(z rotated chem_setting_rotation)) ;
+ if chem_num0<=60 :
+ chem_pic := chem_align.rt (chem_pic) xshifted chem_text_offset ;
+ elseif chem_num0>=120 :
+ chem_pic := chem_align.lft(chem_pic) xshifted -chem_text_offset ;
+ else :
+ chem_pic := chem_align (chem_pic) ;
+ fi
+ else :
+ chem_pic := chem_align (chem_pic) ;
+ fi
else :
- chem_substituent_d := xpart chem_crz_zero[n] + xpart chem_b_zero[m] ;
- fi ;
- if chem_substituent = 1 : chem_substituent_p := (-chem_substituent_d, 0) ; % - ?
- elseif chem_substituent = 2 : chem_substituent_p := (0, chem_substituent_d) ;
- elseif chem_substituent = 3 : chem_substituent_p := ( chem_substituent_d, 0) ;
- elseif chem_substituent = 4 : chem_substituent_p := (0, -chem_substituent_d) ;
- else : chem_substituent_p := origin ;
- fi ;
- currentpicture := currentpicture shifted chem_substituent_p ;
- chem_shift := chem_shift + chem_substituent_p ;
- chem_substituent := 0 ;
- fi ;
- chem_rotation := chem_initialrot[m] ;
+ chem_pic := chem_align@#(chem_pic) shifted (chem_text_offset*mfun_laboff@#) ;
+ fi
+ chem_pic := (chem_pic rotated -chem_setting_rotation) shifted z ;
+
+ if chem_trace_text :
+ draw z withpen pencircle scaled 2pt withcolor red ;
+ draw boundingbox chem_pic withpen pencircle scaled 1pt withcolor red ;
+ fi
+
+ chem_pic
enddef ;
-vardef chem_draw (expr n, path_fragment, from_point, to_point, linewidth, linecolor) =
- for i:=from_point upto to_point:
- draw (path_fragment rotated chem_ang(n,i)) withpen pencircle scaled linewidth withcolor linecolor ;
- endfor ;
+% transform
+
+% rotations and reflections
+
+vardef chem_rot (suffix $) (expr d, s) = % ROT
+ if not chem_front[$] :
+ if d=0 :
+ chem_rotation := 0
+ else :
+ chem_num0 := if chem_stacked[$] : 3 else : 0 fi ;
+ chem_num1 := .5(angle(point d+chem_num0 of chem_b_path[$]) -
+ angle(point d+chem_num0-1 of chem_b_path[$])) ;
+ chem_rotation := (chem_rotation + s*chem_num1) mod 360 ;
+ fi
+ fi
enddef ;
-vardef chem_fill (expr n, path_fragment, from_point, to_point, linewidth, linecolor) =
- for i:=from_point upto to_point:
- fill (path_fragment rotated chem_ang(n,i)) withpen pencircle scaled 0 withcolor linecolor ;
- endfor ;
+vardef chem_mir (suffix $) (expr d, s) = % MIR
+ % We take the scale factor s to multiply the rotation, but only ONCE.
+ % For example: CARBON,.5MIR12 will give a rotation by 104°
+ if not chem_front[$] :
+ if d=0 : % inversion
+ if chem_mirror=origin :
+ chem_rotation := (chem_rotation + 180*s) mod 360 ;
+ else :
+ chem_mirror := chem_mirror rotated 90 ;
+ fi
+ else :
+ chem_pair0 := (point d-1 of chem_b_path[$]) scaled s ; % not chem_transformed
+ if chem_mirror=origin :
+ chem_mirror := chem_pair0 ;
+ else :
+ chem_num0 := angle(chem_mirror)-angle(chem_pair0) ;
+ if (chem_num0>0) and (chem_num0> 180) :
+ chem_num0 := 360 - chem_num0 ;
+ elseif (chem_num0<0) and (chem_num0<-180) :
+ chem_num0 := -360 - chem_num0 ;
+ fi
+ chem_num0 := chem_num0 * s ;
+ chem_rotation := (chem_rotation + 2chem_num0) mod 360 ;
+ chem_mirror := origin ;
+ fi
+ fi
+ fi
enddef ;
-vardef chem_dashed_normal (expr n, path_fragment, from_point, to_point, linewidth, linecolor) =
- for i:=from_point upto to_point:
- draw (path_fragment rotated chem_ang(n,i)) withpen pencircle scaled linewidth withcolor linecolor dashed evenly ;
- endfor ;
+% translations
+
+vardef chem_dir (suffix $) (expr d, s) = % DIR (same as MOV(d-1)MOV(d+1))
+ if not chem_front[$] :
+ if d=0 :
+ currentpicture := currentpicture shifted -chem_origin ;
+ chem_origin := origin ;
+ else :
+ chem_pair0 :=
+ (((point d-2 of chem_b_path[$]) shifted (point d of chem_b_path[$])) scaled s)
+ chem_transformed($) ;
+ currentpicture := currentpicture shifted -chem_pair0 ;
+ chem_origin := chem_origin shifted -chem_pair0 ;
+ fi
+ fi
+enddef ;
+
+vardef chem_mov (suffix $) (expr d, s) = % MOV
+ if d=0 :
+ currentpicture := currentpicture shifted -chem_origin ;
+ chem_origin := origin ;
+ else :
+ chem_pair0 := ((point d-1 of chem_b_path[$]) scaled s) chem_transformed($) ;
+ currentpicture := currentpicture shifted -chem_pair0 ;
+ chem_origin := chem_origin shifted -chem_pair0 ;
+ fi ;
enddef ;
-vardef chem_dashed_connected (expr n, path_fragment, from_point, to_point, linewidth, linecolor) =
- draw for i:=from_point upto to_point:
- (path_fragment rotated chem_ang(n,i)) if i < to_point : -- fi
- endfor withpen pencircle scaled linewidth withcolor linecolor dashed evenly ;
+vardef chem_mark (suffix $) (expr d, s) = % MARK
+ % scale s is ignored
+ if d<>0 :
+ chem_mark_pair[d] := -chem_origin ;
+ fi
enddef ;
-vardef chem_draw_dot (expr n, path_fragment, from_point, to_point, linewidth, linecolor) =
- for i:=from_point upto to_point:
- draw (path_fragment rotated chem_ang(n,i)) withpen pencircle scaled (chem_dot_factor*linewidth) withcolor linecolor ;
- endfor ;
+vardef chem_marked (expr d) =
+ if d=0 :
+ chem_origin
+ elseif known chem_mark_pair[d] :
+ chem_mark_pair[d] shifted chem_origin
+ else :
+ origin
+ fi
enddef ;
-vardef chem_draw_fixed (expr n, path_fragment, linewidth, linecolor) =
- draw (path_fragment rotated chem_ang(n,1)) withpen pencircle scaled linewidth withcolor linecolor ;
+vardef chem_number@#(suffix $) (expr p) (text t) = chem_label@#($,p,t) enddef ; % NUMBER
+vardef chem_label@# (suffix $) (expr p) (text t) = % LABEL
+ draw chem_text@#(t,chem_do(chem_marked(p))) ;
enddef ;
-vardef chem_draw_arrow (expr n, path_fragment, from_point, to_point, linewidth, linecolor) =
- for i:=from_point upto to_point:
- drawarrow (path_fragment rotated chem_ang(n,i)) withpen pencircle scaled linewidth withcolor linecolor ;
- endfor ;
+vardef chem_move (suffix $) (expr d, s) = % MOVE
+ chem_pair0 := chem_marked(d) scaled s ;
+ currentpicture := currentpicture shifted -chem_pair0 ;
+ chem_origin := chem_origin shifted -chem_pair0 ;
enddef ;
-vardef chem_draw_vertical (expr n, path_fragment, from_point, to_point, linewidth, linecolor) =
- % quite special
- for i:=from_point upto to_point:
- draw (path_fragment shifted (chem_b_zero[n] rotated chem_ang(n,i))) withpen pencircle scaled linewidth withcolor linecolor ;
- endfor ;
+vardef chem_diff (suffix $) (expr d, s) = % DIFF
+ chem_pair0 := (chem_marked(d) shifted -chem_origin) scaled s ;
+ currentpicture := currentpicture shifted -chem_pair0 ;
+ chem_origin := chem_origin shifted -chem_pair0 ;
enddef ;
-picture chem_stack_p[] ;
-pair chem_stack_shift[] ;
-
-vardef chem_save =
- chem_stack_n := chem_stack_n + 1 ;
- chem_stack_p[chem_stack_n] := currentpicture ;
- chem_stack_shift[chem_stack_n] := chem_shift ;
- chem_shift := origin ;
-% chem_adjacent := 0 ;
-% chem_substituent := 0 ;
-% chem_rotation := 1 ;
- currentpicture := nullpicture ;
+vardef chem_line (suffix $) (expr f, t, r, c) = % LINE
+ draw if f=t : origin else : chem_marked(f) fi -- chem_marked(t)
+ % no chem_transformed
+ withpen pencircle scaled r
+ withcolor c %\MPcolor{c}
enddef ;
-vardef chem_restore =
- if chem_stack_n > 0 :
- currentpicture := currentpicture shifted - chem_shift ;
- addto chem_stack_p[chem_stack_n] also currentpicture ;
- currentpicture := chem_stack_p[chem_stack_n] ;
- chem_stack_p[chem_stack_n] := nullpicture ;
- chem_shift := chem_stack_shift[chem_stack_n] ;
- chem_stack_n := chem_stack_n - 1 ;
- fi ;
+vardef chem_dash (suffix $) (expr f, t, r, c) = % DASH
+ draw if f=t : origin else : chem_marked(f) fi -- chem_marked(t)
+ % no chem_transformed
+ withpen pencircle scaled r
+ withcolor c %\MPcolor{c}
+ dashed evenly ;
enddef ;
-def chem_init_some(expr n, ratio, start, initialrot, initialmov) =
- chem_width [n] := ratio * chem_base_width * chem_setting_scale ;
- chem_angle [n] := 360/abs(n) ;
- chem_start [n] := start ;
- chem_initialrot[n] := initialrot ;
- chem_initialmov[n] := initialmov ;
- chem_b_zero [n] := (chem_width[n],0) rotated (chem_angle[n]/2) ;
- chem_n_zero [n] := (chem_text_min*chem_width[n],0) rotated (chem_angle[n]/2) ;
- chem_r_max [n] := chem_radical_max*chem_b_zero[n] ;
- chem_r_path [n] := chem_b_zero[n] -- chem_r_max[n] ;
- chem_mr_path [n] := chem_r_path [n] rotatedaround(chem_b_zero[n], (180-chem_angle[n])/2) ;
- chem_pr_path [n] := chem_r_path [n] rotatedaround(chem_b_zero[n],-(180-chem_angle[n])/2) ;
- chem_r_zero [n] := point 1 of chem_r_path [n] ;
- chem_mr_zero [n] := point 1 of chem_mr_path[n] ;
- chem_pr_zero [n] := point 1 of chem_pr_path[n] ;
- chem_crz_zero [n] := point 1 of (chem_r_path[n] enlonged chem_center_offset) ;
- chem_au_path [n] := subpath (0.2,0.8) of (chem_r_max[n] -- (chem_r_max[n] rotated chem_angle[n])) ;
- chem_ad_path [n] := reverse(chem_au_path[n]) ;
- chem_rt_zero [n] := (((chem_radical_max+chem_radical_min)/2)*chem_width[n],0) rotated (chem_angle[n]/2) ;
- chem_rtt_zero [n] := chem_rt_zero[n] rotated + 10 ;
- chem_rbt_zero [n] := chem_rt_zero[n] rotated - 10 ;
- chem_b_path [n] := reverse(chem_b_zero[n] -- (chem_b_zero[n] rotated -chem_angle[n])) ;
- chem_bx_path [n] := reverse(chem_b_zero[n] -- (chem_b_zero[n] rotated -chem_angle[n])) ; % ?
- chem_sb_path [n] := subpath (0.25,0.75) of chem_b_path[n] ;
- chem_s_path [n] := point 0 of chem_b_path[n] -- point 0 of (chem_b_path[n] rotated (2chem_angle[n])) ;
- chem_ss_path [n] := subpath (0.25,0.75) of (chem_s_path[n]) ;
- chem_pss_path [n] := subpath (0.00,0.75) of (chem_s_path[n]) ;
- chem_mss_path [n] := subpath (0.25,1.00) of (chem_s_path[n]) ;
- chem_mid_zero [n] := origin shifted (-.25chem_width[n],0) ;
- chem_midst_path[n] := chem_mid_zero[n] -- (chem_width[n],0) rotated ( chem_angle[n] + chem_angle[n]/2) ;
- chem_midsb_path[n] := chem_mid_zero[n] -- (chem_width[n],0) rotated (-chem_angle[n] - chem_angle[n]/2) ;
- chem_midt_path [n] := subpath (0.25,1.00) of chem_midst_path [n] ;
- chem_midb_path [n] := subpath (0.25,1.00) of chem_midsb_path [n] ;
- chem_msb_path [n] := subpath (0.00,0.75) of chem_b_path[n] ;
- chem_psb_path [n] := subpath (0.25,1.00) of chem_b_path[n] ;
- chem_dbl_path [n] := chem_sb_path[n] shifted - (0.05[origin,center chem_sb_path[n]]) ; % parallel
- chem_dbr_path [n] := chem_sb_path[n] shifted + (0.05[origin,center chem_sb_path[n]]) ;
- chem_eb_path [n] := chem_sb_path[n] shifted - (0.25[origin,center chem_sb_path[n]]) ;
- chem_sr_path [n] := chem_radical_min*chem_b_zero[n] -- chem_r_max[n] ;
- chem_rl_path [n] := chem_r_path[n] paralleled (chem_base_width/20) ;
- chem_rr_path [n] := chem_r_path[n] paralleled -(chem_base_width/20) ;
- chem_srl_path [n] := chem_sr_path[n] paralleled (chem_base_width/20) ;
- chem_srr_path [n] := chem_sr_path[n] paralleled -(chem_base_width/20) ;
- chem_br_path [n] := point 1 of chem_sb_path[n] --
- point 0 of chem_sb_path[n] rotatedaround(point 1 of chem_sb_path[n], -4) --
- point 0 of chem_sb_path[n] rotatedaround(point 1 of chem_sb_path[n], 4) -- cycle ;
- chem_rb_path [n] := chem_b_zero[n] -- chem_r_max[n] rotated -2 -- chem_r_max[n] -- chem_r_max[n] rotated 2 -- cycle ;
- chem_mrb_path [n] := chem_rb_path[n] rotatedaround(chem_b_zero[n], (180-chem_angle[n])/2) ;
- chem_prb_path [n] := chem_rb_path[n] rotatedaround(chem_b_zero[n],-(180-chem_angle[n])/2) ;
- chem_msr_path [n] := chem_sr_path[n] rotatedaround(chem_b_zero[n], (180-chem_angle[n])/2) ;
- chem_psr_path [n] := chem_sr_path[n] rotatedaround(chem_b_zero[n],-(180-chem_angle[n])/2) ;
- % not yet ok:
-% chem_c_path [n] := subpath (30/45, -30/45) of (fullcircle scaled (1.25*chem_circle_radius*chem_width[n]));
-% chem_cc_path [n] := subpath (30/45,8-30/45) of (fullcircle rotated 90 scaled (1.25*chem_circle_radius*chem_width[n]));
- chem_c_path [n] := subpath (30/45, -30/45) of (fullcircle scaled (chem_width[n]));
- chem_cc_path [n] := subpath (30/45,8-30/45) of (fullcircle rotated 90 scaled (chem_width[n]));
-enddef ;
-
-def chem_init_three = chem_init_some(3,30/52 ,-60,1,2) ; enddef ; % 60
-def chem_init_four = chem_init_some(4,30/42.5, 0,1,0) ; enddef ; % 45
-def chem_init_five = chem_init_some(5,30/35 , 0,1,0) ; enddef ; % 36
-def chem_init_six = chem_init_some(6, 1 , 0,1,0) ; enddef ; % 30
-def chem_init_eight = chem_init_some(8,30/22.5, 0,1,0) ; enddef ; % 22.5
-
-% bb R -R R Z -RZ +RZ
-
-def chem_init_some_front(expr n, ratio, start, initialrot, initialmov) =
- chem_init_some(n, ratio, start, initialrot, initialmov) ;
- chem_bb_path [n] := chem_b_path[n] rotated -chem_angle[n] -- chem_b_path[n] -- chem_b_path[n] rotated chem_angle[n] --
- (reverse(chem_b_path[n] shortened (chem_base_width/20))) paralleled (chem_base_width/20) --
- cycle ;
- chem_r_max [n] := chem_radical_max*chem_b_zero[n] ;
- chem_mr_path [n] := origin -- origin shifted (0,-.25chem_base_width) ;
- chem_pr_path [n] := origin -- origin shifted (0, .25*chem_base_width) ;
- chem_r_path [n] := point 1 of chem_mr_path[n] -- point 1 of chem_pr_path[n] ;
- chem_mr_zero [n] := point 1 of chem_mr_path[n] ;
- chem_pr_zero [n] := point 1 of chem_pr_path[n] ;
-enddef ;
-
-def chem_init_five_front = chem_init_some_front(-5,30/35,0,2,0) ; enddef ; % 36
-def chem_init_six_front = chem_init_some_front(-6, 1 ,0,2,0) ; enddef ; % 30
-
-vardef chem_init_one =
- chem_width [1] := .75 * chem_base_width * chem_setting_scale ;
- chem_angle [1] := 360/8 ;
- chem_start [1] := 0 ;
- chem_initialrot[1] := 1 ;
- chem_initialmov[1] := 1 ;
- chem_b_zero [1] := (1.75*chem_width[1],0) ;
- chem_r_min [1] := chem_radical_min*chem_b_zero[1] ;
- chem_r_max [1] := chem_radical_max*chem_b_zero[1] ;
- chem_r_path [1] := (.5*chem_width[1],0) -- (1.25*chem_width[1],0) ;
- chem_r_zero [1] := point 1 of chem_r_path [1] ;
- chem_b_path [1] := chem_r_path[1] rotated + (chem_angle[1]) ; % used for move here
- chem_b_zero [1] := chem_r_zero[1] ;
- chem_crz_zero [1] := chem_r_zero[1] enlonged chem_center_offset ;
- chem_e_path [1] := (.5*chem_width[1],-.25*chem_width[1]) -- (.5*chem_width[1],.25*chem_width[1]) ;
- chem_sb_path [1] := chem_r_path [1] ;
- chem_msb_path [1] := chem_r_path [1] shifted (0,-.1chem_width[1]) ;
- chem_psb_path [1] := chem_r_path [1] shifted (0, .1chem_width[1]) ;
- chem_ddt_path [1] := subpath(0,.4) of chem_r_path [1] ;
- chem_ddb_path [1] := subpath(.6,1) of chem_r_path [1] ;
- chem_ldt_path [1] := chem_ddt_path [1] shifted (0,-.1chem_width[1]) ; % parallel
- chem_ldb_path [1] := chem_ddb_path [1] shifted (0,-.1chem_width[1]) ;
- chem_rdt_path [1] := chem_ddt_path [1] shifted (0, .1chem_width[1]) ;
- chem_rdb_path [1] := chem_ddb_path [1] shifted (0, .1chem_width[1]) ;
- save pr ; pair pr[] ;
- pr0 := point 0 of chem_r_path[1] ;
- pr1 := point 1 of chem_r_path[1] ;
- chem_bb_path [1] := pr0 -- (pr1 rotatedaround(pr0,-chem_bb_angle)) -- (pr1 rotatedaround(pr0,chem_bb_angle)) -- cycle ;
- chem_oe_path [1] := ((-20,0)--(10,0){up}..(20,10)..(30,0)..(40,-10)..(50.0,0)..(60,10)..(70,0)..(80,-10)..{up}(90,0)--(120,0))
- xsized (.75*chem_width[1]) shifted pr0 ;
- chem_rt_zero [1] := point .5 of chem_r_path[1] ;
- chem_rtt_zero [1] := chem_rt_zero[1] rotated + (chem_angle[1]/2) ;
- chem_rbt_zero [1] := chem_rt_zero[1] rotated - (chem_angle[1]/2) ;
- % added by Alan Braslau (adapted to use shared variables):
- save p ; pair p[] ;
- p0 := pr1 rotatedaround(pr0, -chem_bd_angle) ;
- p1 := pr1 rotatedaround(pr0, +chem_bd_angle) ;
- p2 := p0 shifted - pr1 ;
- p3 := p1 shifted - pr1 ;
- chem_bd_path [1] :=
- p0 -- p1 for i=chem_bd_n downto 0 :
- -- p2 shifted (i/chem_bd_n)[pr1,pr0]
- -- p3 shifted (i/chem_bd_n)[pr1,pr0]
- endfor ;
- chem_bw_path [1] :=
- for i=0 upto chem_bw_n - 1 :
- ((i) /chem_bw_n)[pr0,pr1] .. ((i+.25)/chem_bw_n)[pr0,pr1] shifted p2 ..
- ((i+.50)/chem_bw_n)[pr0,pr1] .. ((i+.75)/chem_bw_n)[pr0,pr1] shifted -p2 ..
- endfor pr1 ;
+vardef chem_arrow (suffix $) (expr f, t, r, c) = % ARROW
+ drawarrow if f=t : origin else : chem_marked(f) fi -- chem_marked(t)
+ % no chem_transformed
+ withpen pencircle scaled r
+ withcolor c %\MPcolor{c}
enddef ;
-def chem_init_all =
- chem_init_one ;
- chem_init_three ;
- chem_init_four ;
- chem_init_five ;
- chem_init_six ;
- chem_init_eight ;
- chem_init_five_front ;
- chem_init_six_front ;
+
+vardef chem_rm (suffix $) (expr d, s) = % RM
+ if (not chem_front[$]) and (d<>0) :
+ chem_pair0 := ((point d-1 of chem_r_path[$]) scaled s) chem_transformed($) ;
+ currentpicture := currentpicture shifted -chem_pair0 ;
+ chem_origin := chem_origin shifted -chem_pair0 ;
+ fi ;
enddef ;
-chem_init_all ;
+vardef chem_off (suffix $) (expr d, s) = % OFF
+ if d=0 :
+ currentpicture := currentpicture shifted -chem_origin ;
+ chem_origin := origin ;
+ else :
+ chem_pair0 := (unitvector(point d-1 of chem_b_path[one])) scaled chem_setting_offset*s ;
+ % not chem_transformed
+ currentpicture := currentpicture shifted -chem_pair0 ;
+ chem_origin := chem_origin shifted -chem_pair0 ;
+ fi ;
+enddef ;
diff --git a/Master/texmf-dist/metapost/context/base/mp-core.mpiv b/Master/texmf-dist/metapost/context/base/mp-core.mpiv
index 1934e304024..3dba4a004e7 100644
--- a/Master/texmf-dist/metapost/context/base/mp-core.mpiv
+++ b/Master/texmf-dist/metapost/context/base/mp-core.mpiv
@@ -5,7 +5,7 @@
%D subtitle=background macros,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
%C
%C This module is part of the \CONTEXT\ macro||package and is
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
diff --git a/Master/texmf-dist/metapost/context/base/mp-crop.mpiv b/Master/texmf-dist/metapost/context/base/mp-crop.mpiv
index 6360757e5b0..00bcdcb4454 100644
--- a/Master/texmf-dist/metapost/context/base/mp-crop.mpiv
+++ b/Master/texmf-dist/metapost/context/base/mp-crop.mpiv
@@ -5,7 +5,7 @@
%D subtitle=Cropmarks,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
%C
%C This module is part of the \CONTEXT\ macro||package and is
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
@@ -15,20 +15,20 @@ if known context_crop : endinput ; fi ;
boolean context_crop ; context_crop := true ;
-vardef crop_marks_lines (expr box, length, offset, nx, ny) =
- save p ; picture p ; save w, h, x, y ; numeric w, h, x, y ;
+vardef crop_marks_lines (expr box, len, offset, nx, ny) =
+ save p ; picture p ; save w, h, x, y ; numeric w, h, x, y ;
p := image (
x := if nx = 0 : 1 else : nx - 1 fi ;
y := if ny = 0 : 1 else : ny - 1 fi ;
w := bbwidth (box) / x ;
h := bbheight(box) / y ;
for i=0 upto y :
- draw ((llcorner box) -- (llcorner box) shifted (-length,0)) shifted (-offset,i*h) ;
- draw ((lrcorner box) -- (lrcorner box) shifted ( length,0)) shifted ( offset,i*h) ;
+ draw ((llcorner box) -- (llcorner box) shifted (-len,0)) shifted (-offset,i*h) ;
+ draw ((lrcorner box) -- (lrcorner box) shifted ( len,0)) shifted ( offset,i*h) ;
endfor ;
for i=0 upto x :
- draw ((llcorner box) -- (llcorner box) shifted (0,-length)) shifted (i*w,-offset) ;
- draw ((ulcorner box) -- (ulcorner box) shifted (0, length)) shifted (i*w, offset) ;
+ draw ((llcorner box) -- (llcorner box) shifted (0,-len)) shifted (i*w,-offset) ;
+ draw ((ulcorner box) -- (ulcorner box) shifted (0, len)) shifted (i*w, offset) ;
endfor ;
) ;
setbounds p to box ;
diff --git a/Master/texmf-dist/metapost/context/base/mp-figs.mpiv b/Master/texmf-dist/metapost/context/base/mp-figs.mpiv
index c65808f6d05..aac7c5ad219 100644
--- a/Master/texmf-dist/metapost/context/base/mp-figs.mpiv
+++ b/Master/texmf-dist/metapost/context/base/mp-figs.mpiv
@@ -5,7 +5,7 @@
%D subtitle=figures,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
%C
%C This module is part of the \CONTEXT\ macro||package and is
%C therefore copyrighted by \PRAGMA. See licen-en.pdf for
diff --git a/Master/texmf-dist/metapost/context/base/mp-form.mpiv b/Master/texmf-dist/metapost/context/base/mp-form.mpiv
index d0519b4f24c..b58792e1a01 100644
--- a/Master/texmf-dist/metapost/context/base/mp-form.mpiv
+++ b/Master/texmf-dist/metapost/context/base/mp-form.mpiv
@@ -5,7 +5,7 @@
%D subtitle=form support,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
%C
%C This module is part of the \CONTEXT\ macro||package and is
%C therefore copyrighted by \PRAGMA. See licen-en.pdf for
diff --git a/Master/texmf-dist/metapost/context/base/mp-func.mpiv b/Master/texmf-dist/metapost/context/base/mp-func.mpiv
index 1d289b606b1..58df711f2f3 100644
--- a/Master/texmf-dist/metapost/context/base/mp-func.mpiv
+++ b/Master/texmf-dist/metapost/context/base/mp-func.mpiv
@@ -5,7 +5,7 @@
%D subtitle=function hacks,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
%C
%C This module is part of the \CONTEXT\ macro||package and is
%C therefore copyrighted by \PRAGMA. See licen-en.pdf for
diff --git a/Master/texmf-dist/metapost/context/base/mp-grap.mpiv b/Master/texmf-dist/metapost/context/base/mp-grap.mpiv
new file mode 100644
index 00000000000..6b1f2311f88
--- /dev/null
+++ b/Master/texmf-dist/metapost/context/base/mp-grap.mpiv
@@ -0,0 +1,526 @@
+%D \module
+%D [ file=mp-grap.mpiv,
+%D version=2012.10.16, % 2008.09.08 and earlier,
+%D title=\CONTEXT\ \METAPOST\ graphics,
+%D subtitle=graph packagesupport,
+%D author=Hans Hagen \& Alan Braslau,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See licen-en.pdf for
+%C details.
+
+if known context_grap : endinput ; fi
+
+boolean context_grap ; context_grap := true ;
+
+% Instead we could include graph here and then clean it up as well as use private
+% variables in the grap_ namespace. After all, graph is frozen.
+
+input graph.mp ;
+
+vardef roundd(expr x, d) =
+ if abs d > 4 :
+ if d > 0 :
+ x
+ else :
+ 0
+ fi
+ elseif d > 0 :
+ save i ; i = floor x ;
+ i + round(Ten_to[d]*(x-i))/Ten_to[d]
+ else :
+ round(x/Ten_to[-d])*Ten_to[-d]
+ fi
+enddef ;
+
+Ten_to0 = 1 ;
+Ten_to1 = 10 ;
+Ten_to2 = 100 ;
+Ten_to3 = 1000 ;
+Ten_to4 = 10000 ;
+
+def sFe_base = enddef ;
+
+if unknown Fe_plus :
+ picture Fe_plus ; Fe_plus := textext("+") ; % btex + etex ;
+fi ;
+
+vardef format (expr f,x) = dofmt_.Feform_(f,x) enddef ;
+vardef Mformat (expr f,x) = dofmt_.Meform (f,x) enddef ;
+vardef formatstr (expr f,x) = dofmt_.Feform_(f,x) enddef ;
+vardef Mformatstr(expr f,x) = dofmt_.Meform(f,x) enddef ;
+
+vardef escaped_format(expr s) =
+ "" for n=1 upto length(s) : &
+ if ASCII substring (n,n+1) of s = 37 :
+ "@"
+ else :
+ substring (n,n+1) of s
+ fi
+ endfor
+enddef ;
+
+vardef dofmt_@#(expr f, x) =
+ textext("\MPgraphformat{" & escaped_format(f) & "}{" & (if string x : x else: decimal x fi) & "}")
+ % textext(mfun_format_number(escaped_format(f),x))
+enddef ;
+
+% note that suffix @# is ignored above...
+
+vardef strfmt(expr f, x) =
+ "\MPgraphformat{" & escaped_format(f) & "}{" & (if string x : x else: decimal x fi) & "}"
+enddef ;
+
+% We redefine autogrid from graph.mp adding the possibility of differing X and Y
+% formats. Autoform is defined in graph.mp (by default "%g").
+
+% graph.mp: string Autoform; Autoform = "%g";
+% graph.mp:
+% graph.mp: vardef autogrid(suffix tx, ty) text w =
+% graph.mp: Gneedgr_:=false;
+% graph.mp: if str tx<>"": for x=auto.x: tx(Autoform,x) w; endfor fi
+% graph.mp: if str ty<>"": for y=auto.y: ty(Autoform,y) w; endfor fi
+% graph.mp: enddef;
+
+% string Autoform_X ; Autoform_X := "@.0e" ;
+% string Autoform_Y ; Autoform_Y := "@.0e" ;
+
+vardef autogrid(suffix tx, ty) text w =
+ Gneedgr_ := false ;
+ if str tx <> "" :
+ for x=auto.x :
+ tx (
+ if string Autoform_X :
+ if Autoform_X <> "" :
+ Autoform_X
+ else :
+ Autoform
+ fi
+ else :
+ Autoform
+ fi,
+ x
+ ) w ;
+ endfor
+ fi
+ if str ty <> "" :
+ for y=auto.y :
+ ty (
+ if string Autoform_Y :
+ if Autoform_Y <> "" :
+ Autoform_Y
+ else :
+ Autoform
+ fi
+ else :
+ Autoform
+ fi,
+ y
+ ) w ;
+ endfor
+ fi
+enddef ;
+
+% A couple of extensions:
+
+% Define a function plotsymbol() returning a picture: 10 different shapes,
+% unfilled outline, interior filled with different shades of the background.
+% This allows overlapping points on a plot to be more distinguishable.
+
+% grap_symsize := fontsize defaultfont ; % can be redefined
+%
+% dynamic version:
+
+vardef grap_symsize =
+ % fontsize defaultfont
+ % .8ExHeight
+ .35BodyFontSize
+enddef ;
+
+path grap_sym[] ; % (internal) symbol path
+
+grap_sym[0] := (0,0) ; % point
+grap_sym[1] := fullcircle ; % circle
+grap_sym[2] := (up -- down) scaled .5 ; % vertical bar
+
+for i = 3 upto 9 : % polygons
+ grap_sym[i] :=
+ for j = 0 upto i-1 :
+ (up scaled .5) rotated (360j/i) --
+ endfor cycle ;
+endfor
+
+grap_sym[12] := grap_sym[2] rotated +90 ; % horizontal line
+grap_sym[22] := grap_sym[2] rotated +45 ; % backslash
+grap_sym[32] := grap_sym[2] rotated -45 ; % slash
+grap_sym[13] := grap_sym[3] rotated 180 ; % down triangle
+grap_sym[23] := grap_sym[3] rotated -90 ; % right triangle
+grap_sym[33] := grap_sym[3] rotated +90 ; % left triangle
+grap_sym[14] := grap_sym[4] rotated +45 ; % square
+grap_sym[15] := grap_sym[5] rotated 180 ; % down pentagon
+grap_sym[16] := grap_sym[6] rotated +90 ; % turned hexagon
+grap_sym[17] := grap_sym[7] rotated 180 ;
+grap_sym[18] := grap_sym[8] rotated +22.5 ;
+
+numeric l ;
+
+for j = 5 upto 9 :
+ l := length(grap_sym[j]) ;
+ pair p[] ;
+ for i = 0 upto l :
+ p[i] = whatever [point i of grap_sym[j],
+ point (i+2 mod l) of grap_sym[j]] ;
+ p[i] = whatever [point (i+1 mod l) of grap_sym[j],
+ point (i+l-1 mod l) of grap_sym[j]] ;
+ endfor
+ grap_sym[20+j] := for i = 0 upto l : point i of grap_sym[j]--p[i]--endfor cycle ;
+endfor
+
+path s ; s := grap_sym[4] ;
+path q ; q := s scaled .25 ;
+numeric l ; l := length(s) ;
+
+pair p[] ;
+
+grap_sym[24] := for i = 0 upto l-1 :
+ hide(
+ p[i] = whatever [point i of s, point (i+1 mod l) of s] ;
+ p[i] = whatever [point i of q, point (i-1+l mod l) of q] ;
+ p[i+l] = whatever [point i of s, point (i+1 mod l) of s] ;
+ p[i+l] = whatever [point i+1 of q, point (i+2 mod l) of q] ;
+ )
+ point i of q -- p[i] -- p[i+l] --
+endfor cycle ;
+
+grap_sym[34] := grap_sym[24] rotated 45 ;
+
+% usage: gdraw p plot plotsymbol(1,red,1) ; % a filled red circle
+% usage: gdraw p plot plotsymbol(4,blue,0) ; % a blue square
+% usage: gdraw p plot plotsymbol(14,green,0.5) ; % a 50% filled green diamond
+
+def plotsymbol(expr n,c,f) = % (number,color,color|number)
+ if known grap_sym[n] :
+ image(
+ path p ; p := grap_sym[n] scaled grap_symsize ;
+ undraw p withpen currentpen scaled 2 ;
+ if cycle p : fill p withcolor
+ if color f and known f :
+ f
+ elseif numeric f and known f and color c and known c :
+ f[background,c]
+ elseif numeric f and known f :
+ f[background,black]
+ else :
+ background
+ fi ;
+ fi
+ draw p if color c and known c : withcolor c fi ;
+ )
+ else :
+ nullpicture
+ fi
+enddef ;
+
+% The following extensions are not specific to graph and could be moved to metafun...
+
+% convert a polygon path to a smooth path (useful, e.g. as a guide to the eye)
+
+def smoothpath (suffix $) =
+ if path $ :
+ (for i=0 upto length $ :
+ if i>0 : .. fi
+ (point i of $)
+ endfor )
+ fi
+enddef ;
+
+% return a path of a function func(x) with abcissa running from f to t over n intervals
+
+def makefunctionpath (expr f, t, n) (text func) =
+ (for x=f step ((t-f)/n) until t :
+ if x<>f : .. fi
+ (x, func)
+ endfor )
+enddef ;
+
+% shift a path, point by point
+%
+% example:
+%
+% p1 := addnoisetopath(p0,(.1normaldeviate,.1normaldeviate)) ;
+
+vardef addnoisetopath (suffix p) (text t) =
+ if path p :
+ hide(pair p_i)
+ (for i=0 upto length p :
+ if i>0 : -- fi
+ hide(p_i := point i of p; x := xpart p_i; y := ypart p_i)z shifted t
+ endfor)
+ fi
+enddef ;
+
+% return a new path of a function func(x) using the same abcissa as an existing path
+
+vardef functionpath (suffix p) (text t) =
+ (for i=0 upto length p :
+ if i>0 : .. fi
+ (hide(x := xpart(point i of p))x,t)
+ endfor )
+enddef ;
+
+% least-squares "fit" to a polynomial
+%
+% example:
+%
+% path p[] ;
+% numeric a[] ; a0 := 1 ; a1 := .1 ; a2 := .01 ; a3 := .001 ; a4 := 0.0001 ;
+% p0 := makefunctionpath(0,5,10,polynomial_function(a,4,x)) ;
+% p1 := addnoisetopath(p0,(0,.001normaldeviate)) ;
+% gdraw p0 ;
+% gdraw p1 plot plotsymbol(1,black,.5) ;
+%
+% numeric b[] ;
+% polynomial_fit(p1, b, 4, 1) ;
+% gdraw functionpath(p1,polynomial_function(b,4,x)) ;
+%
+% numeric c[] ;
+% linear_fit(p1, c, 1) ;
+% gdraw functionpath(p1,linear_function(c,x)) dashed evenly ;
+
+% a polynomial function:
+%
+% y = a0 + a1 * x + a2 * x^2 + ... + a[n] * x^n
+
+vardef polynomial_function (suffix $) (expr n, x) =
+ (for j=0 upto n : + $[j]*(x**j) endfor) % no ;
+enddef ;
+
+% find the determinant of a (n+1)*(n+1) matrix; indices run from 0 to n
+
+vardef det (suffix $) (expr n) =
+ hide(
+ numeric determinant ; determinant := 1 ;
+ save jj ; numeric jj ;
+ for k=0 upto n :
+ if $[k][k]=0 :
+ jj := -1 ;
+ for j=0 upto n :
+ if $[k][j]<>0 :
+ jj := j ;
+ exitif true ;
+ fi
+ endfor
+ if jj<0 :
+ determinant := 0 ;
+ exitif true ;
+ fi
+ for j=k upto n : % interchange the columns
+ temp := $[j][jj] ;
+ $[j][jj] := $[j][k] ;
+ $[j][k] := temp ;
+ endfor
+ determinant = -determinant ;
+ fi
+ exitif determinant=0 ;
+ determinant := determinant * $[k][k] ;
+ if k 0 : t else : 1 fi ; % weight
+ x1 := w ;
+ for j=0 upto 2n :
+ sumx[j] := sumx[j] + x1 ;
+ x1 := x1 * x ;
+ endfor
+ y1 := y * w ;
+ for j=0 upto n :
+ sumy[j] := sumy[j] + y1 ;
+ y1 := y1 * x ;
+ endfor
+ fit_chi_squared := fit_chi_squared + y*y*w ;
+ endfor
+ % construct matrices and calculate the polynomial coefficients
+ save m ; numeric m[][] ;
+ for j=0 upto n :
+ for k=0 upto n :
+ m[j][k] := sumx[j+k] ;
+ endfor
+ endfor
+ save delta ; numeric delta ;
+ delta := det(m,n) ; % this destroys the matrix m[][], which is OK
+ if delta = 0 :
+ fit_chi_squared := 0 ;
+ for j=0 upto n :
+ $[j] := 0 ;
+ endfor
+ else :
+ for i=0 upto n :
+ for j=0 upto n :
+ for k=0 upto n :
+ m[j][k] := sumx[j+k] ;
+ endfor
+ m[j][i] := sumy[j] ;
+ endfor
+ $[i] := det(m,n) / delta ; % matrix m[][] gets destroyed...
+ endfor
+ for j=0 upto n :
+ fit_chi_squared := fit_chi_squared - 2sumy[j]*$[j] ;
+ for k=0 upto n :
+ fit_chi_squared := fit_chi_squared + $[j]*$[k]*sumx[j+k] ;
+ endfor
+ endfor
+ % normalize by the number of degrees of freedom
+ fit_chi_squared := fit_chi_squared / (length(p) - n) ;
+ fi
+ fi
+enddef ;
+
+% y = a0 + a1 * x
+%
+% of course a line is just a polynomial of order 1
+
+vardef linear_function (suffix $) (expr x) = polynomial_function($,1,x) enddef ;
+vardef linear_fit (suffix p, $) (text t) = polynomial_fit(p, $, 1, t) ; enddef ;
+
+% and a constant is polynomial of order 0
+
+vardef constant_function (suffix $) (expr x) = polynomial_function($,0,x) enddef ;
+vardef constant_fit (suffix p, $) (text t) = polynomial_fit(p, $, 0, t) ; enddef ;
+
+% y = a1 * exp(a0*x)
+%
+% exp and ln defined in metafun
+
+vardef exponential_function (suffix $) (expr x) = $1*exp($0*x) enddef ;
+
+% since we take a log, this only works for positive ordinates
+
+vardef exponential_fit (suffix p, $) (text t) =
+ save a ; numeric a[] ;
+ save q ; path q ; % fit to the log of the ordinate
+ for i=0 upto length p :
+ if ypart(point i of p)>0 :
+ augment.q(xpart(point i of p),ln(ypart(point i of p))) ;
+ fi
+ endfor
+ linear_fit(q,a,t) ;
+ $0 := a1 ;
+ $1 := exp(a0) ;
+enddef ;
+
+% y = a1 * x**a0
+
+vardef power_law_function (suffix $) (expr x) = $1*(x**$0) enddef ;
+
+% since we take logs, this only works for positive abcissae and ordinates
+
+vardef power_law_fit (suffix p, $) (text t) =
+ save a ; numeric a[] ;
+ save q ; path q ; % fit to the logs of the abcissae and ordinates
+ for i=0 upto length p :
+ if (xpart(point i of p)>0) and (ypart(point i of p)>0) :
+ augment.q(ln(xpart(point i of p)),ln(ypart(point i of p))) ;
+ fi
+ endfor
+ linear_fit(q,a,t) ;
+ $0 := a1 ;
+ $1 := exp(a0) ;
+enddef ;
+
+% gaussian: y = a2 * exp(-ln(2)*((x-a0)/a1)^2)
+%
+% a1 is the hwhm; sigma := a1/sqrt(2ln(2)) or a1/1.17741
+
+numeric lntwo ; lntwo := ln(2) ; % brrr, why not inline it
+
+vardef gaussian_function (suffix $) (expr x) =
+ if $1 = 0 :
+ if x = $0 : $2 else : 0 fi
+ else :
+ $2 * exp(-lntwo*(((x-$0)/$1)**2))
+ fi
+ if known $3 :
+ + $3
+ fi
+enddef ;
+
+% since we take a log, this only works for positive ordinates
+
+vardef gaussian_fit (suffix p, $) (text t) =
+ save a ; numeric a[] ;
+ save q ; path q ; % fit to the log of the ordinate
+ for i=0 upto length p :
+ if ypart(point i of p)>0 :
+ augment.q(xpart(point i of p), ln(ypart(point i of p))) ;
+ fi
+ endfor
+ polynomial_fit(q,a,2,if t > 0 : ln(t) else : 0 fi) ;
+ $1 := sqrt(-lntwo/a2) ;
+ $0 := -.5a1/a2 ;
+ $2 := exp(a0-.25*a1*a1/a2) ;
+ $3 := 0 ; % polynomial_fit will NOT work with a non-zero background!
+enddef ;
+
+% lorentzian: y = a2 / (1 + ((x - a0)/a1)^2)
+
+vardef lorentzian_function (suffix $) (expr x) =
+ if $1 = 0 :
+ if x = $0 : $2 else : 0 fi
+ else :
+ $2 / (1 + ((x - $0)/$1)**2)
+ fi
+ if known $3 :
+ + $3
+ fi
+enddef ;
+
+vardef lorentzian_fit (suffix p, $) (text t) =
+ save a ; numeric a[] ;
+ save q ; path q ; % fit to the inverse of the ordinate
+ for i=0 upto length p :
+ if ypart(point i of p)<>0 :
+ augment.q(xpart(point i of p), 1/ypart(point i of p)) ;
+ fi
+ endfor
+ polynomial_fit(q,a,2,if t <> 0 : 1/(t) else : 0 fi) ;
+ $0 := -.5a1/a2 ;
+ $2 := 1/(a0-.25a1*a1/a2) ;
+ $1 := sqrt((a0-.25a1*a1/a2)/a2) ;
+ $3 := 0 ; % polynomial_fit will NOT work with a non-zero background!
+enddef ;
diff --git a/Master/texmf-dist/metapost/context/base/mp-grid.mpiv b/Master/texmf-dist/metapost/context/base/mp-grid.mpiv
index cc5c2b76eb2..b9243b1b96e 100644
--- a/Master/texmf-dist/metapost/context/base/mp-grid.mpiv
+++ b/Master/texmf-dist/metapost/context/base/mp-grid.mpiv
@@ -5,7 +5,7 @@
%D subtitle=grid support,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
%C
%C This module is part of the \CONTEXT\ macro||package and is
%C therefore copyrighted by \PRAGMA. See licen-en.pdf for
diff --git a/Master/texmf-dist/metapost/context/base/mp-grph.mpiv b/Master/texmf-dist/metapost/context/base/mp-grph.mpiv
index a8868033bbe..30c49e6e04a 100644
--- a/Master/texmf-dist/metapost/context/base/mp-grph.mpiv
+++ b/Master/texmf-dist/metapost/context/base/mp-grph.mpiv
@@ -5,7 +5,7 @@
%D subtitle=graphic text support,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
%C
%C This module is part of the \CONTEXT\ macro||package and is
%C therefore copyrighted by \PRAGMA. See licen-en.pdf for
diff --git a/Master/texmf-dist/metapost/context/base/mp-mlib.mpiv b/Master/texmf-dist/metapost/context/base/mp-mlib.mpiv
index 71985cef836..9a20429241e 100644
--- a/Master/texmf-dist/metapost/context/base/mp-mlib.mpiv
+++ b/Master/texmf-dist/metapost/context/base/mp-mlib.mpiv
@@ -5,7 +5,7 @@
%D subtitle=plugins,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
%C
%C This module is part of the \CONTEXT\ macro||package and is
%C therefore copyrighted by \PRAGMA. See licen-en.pdf for
@@ -99,7 +99,20 @@ newinternal textextoffset ; textextoffset := 0 ;
numeric mfun_tt_w[], mfun_tt_h[], mfun_tt_d[] ; % we can consider using colors (less hash space)
numeric mfun_tt_n ; mfun_tt_n := 0 ;
picture mfun_tt_p ; mfun_tt_p := nullpicture ;
-boolean mfun_trial_run ; mfun_trial_run := false ;
+
+if unknown mfun_trial_run :
+ boolean mfun_trial_run ;
+ mfun_trial_run := false ;
+else :
+ % already defined before the format is loaded
+fi ;
+
+if unknown mfun_first_run :
+ boolean mfun_first_run ;
+ mfun_first_run := true ;
+else :
+ % already defined before the format is loaded
+fi ;
def mfun_reset_tex_texts =
mfun_tt_n := 0 ;
@@ -110,8 +123,8 @@ def mfun_flush_tex_texts =
addto currentpicture also mfun_tt_p
enddef ;
-extra_endfig := "mfun_flush_tex_texts;" & extra_endfig;
-extra_beginfig := extra_beginfig & "mfun_reset_tex_texts;";
+extra_endfig := "mfun_flush_tex_texts ;" & extra_endfig ;
+extra_beginfig := extra_beginfig & "mfun_reset_tex_texts ;" ;
% We collect and flush them all, as we can also have temporary textexts
% that gets never really flushed but are used for calculations. So, we
@@ -255,7 +268,7 @@ vardef thetextext@#(expr p,z) =
fi
enddef ;
-vardef textext@#(expr p) = % no draw hers
+vardef textext@#(expr p) = % no draw here
thetextext@#(p,origin)
enddef ;
@@ -565,7 +578,10 @@ def bitmapimage(expr xresolution, yresolution, data) =
)
enddef ;
-% TODO:
+% Experimental:
+%
+% property p ; p = properties(withcolor (1,1,0,0)) ;
+% fill fullcircle scaled 20cm withproperties p ;
let property = picture ;
@@ -573,24 +589,33 @@ vardef properties(text t) =
image(draw unitcircle t)
enddef ;
-def withproperties expr p =
- if colormodel p = 3 :
- withcolor greypart p
- elseif colormodel p = 5 :
- withcolor (redpart p,greenpart p,bluepart p)
- elseif colormodel p = 7 :
- withcolor (cyanpart p,magentapart p,yellowpart p,blackpart p)
- fi
- % todo, when available in mp:
- %
- % withprescript prescript p
- % withpostscript postscript p
- %
- % todo, penpart
-enddef ;
+if metapostversion < 1.770 :
-% property p ; p = properties(withcolor (1,1,0,1)) ;
-% fill fullcircle scaled 20cm withproperties p ;
+ def withproperties expr p =
+ if colormodel p = 3 :
+ withcolor greypart p
+ elseif colormodel p = 5 :
+ withcolor (redpart p,greenpart p,bluepart p)
+ elseif colormodel p = 7 :
+ withcolor (cyanpart p,magentapart p,yellowpart p,blackpart p)
+ fi
+ enddef ;
+
+else :
+
+ def withproperties expr p =
+ if colormodel p = 3 :
+ withcolor greypart p
+ elseif colormodel p = 5 :
+ withcolor (redpart p,greenpart p,bluepart p)
+ elseif colormodel p = 7 :
+ withcolor (cyanpart p,magentapart p,yellowpart p,blackpart p)
+ fi
+ withprescript prescript p
+ withpostscript postscript p
+ enddef ;
+
+fi ;
% Experimental:
@@ -614,3 +639,26 @@ primarydef t asgroup s = % s = isolated|knockout
wrappedpicture
endgroup
enddef ;
+
+% Also experimental
+
+string mfun_auto_align[] ;
+
+mfun_auto_align[0] := "rt" ;
+mfun_auto_align[1] := "urt" ;
+mfun_auto_align[2] := "top" ;
+mfun_auto_align[3] := "ulft" ;
+mfun_auto_align[4] := "lft" ;
+mfun_auto_align[5] := "llft" ;
+mfun_auto_align[6] := "bot" ;
+mfun_auto_align[7] := "lrt" ;
+mfun_auto_align[8] := "rt" ;
+
+def autoalign(expr n) =
+ scantokens mfun_auto_align[round((n mod 360)/45)]
+enddef ;
+
+% draw textext.autoalign(60) ("\strut oeps 1") ;
+% draw textext.autoalign(160)("\strut oeps 2") ;
+% draw textext.autoalign(260)("\strut oeps 3") ;
+% draw textext.autoalign(360)("\strut oeps 4") ;
diff --git a/Master/texmf-dist/metapost/context/base/mp-page.mpiv b/Master/texmf-dist/metapost/context/base/mp-page.mpiv
index 96f617257f5..9c538d42a65 100644
--- a/Master/texmf-dist/metapost/context/base/mp-page.mpiv
+++ b/Master/texmf-dist/metapost/context/base/mp-page.mpiv
@@ -5,7 +5,7 @@
%D subtitle=page enhancements,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
%C
%C This module is part of the \CONTEXT\ macro||package and is
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
@@ -106,20 +106,30 @@ OuterEdgeWidth := 0pt ;
InnerEdgeDistance := 0pt ;
OuterEdgeDistance := 0pt ;
-path Area [][] ; pair Location [][] ; path Field [][] ; path Page ;
-numeric HorPos ; numeric Hstep [] ; numeric Hsize [] ;
-numeric VerPos ; numeric Vstep [] ; numeric Vsize [] ;
-
-for VerPos=Top step 10 until Bottom:
- for HorPos=LeftEdge step 1 until RightEdge:
- Area[HorPos][VerPos] := origin--cycle ;
- Area[VerPos][HorPos] := Area[HorPos][VerPos] ;
- Location[HorPos][VerPos] := origin ;
- Location[VerPos][HorPos] := Location[HorPos][VerPos] ;
- Field[HorPos][VerPos] := origin--cycle ;
- Field[VerPos][HorPos] := Field[HorPos][VerPos] ;
- endfor ;
-endfor ;
+% path Area[][] ;
+% pair Location[][] ;
+% path Field[][] ;
+
+% numeric Hstep[] ;
+% numeric Hsize[] ;
+% numeric Vstep[] ;
+% numeric Vsize[] ;
+
+path Page ;
+
+numeric HorPos ;
+numeric VerPos ;
+
+% for VerPos=Top step 10 until Bottom:
+% for HorPos=LeftEdge step 1 until RightEdge:
+% Area[HorPos][VerPos] := origin--cycle ;
+% Area[VerPos][HorPos] := Area[HorPos][VerPos] ;
+% Location[HorPos][VerPos] := origin ;
+% Location[VerPos][HorPos] := Location[HorPos][VerPos] ;
+% Field[HorPos][VerPos] := origin--cycle ;
+% Field[VerPos][HorPos] := Field[HorPos][VerPos] ;
+% endfor ;
+% endfor ;
% def LoadPageState =
% scantokens "input mp-state.tmp" ;
@@ -160,10 +170,94 @@ def SwapPageState =
fi ;
enddef ;
-def SetPageAreas =
+% def SetPageAreas =
+%
+% numeric Vsize[], Hsize[], Vstep[], Hstep[] ;
+%
+% Vsize[Top] = TopHeight ;
+% Vsize[TopSeparator] = TopDistance ;
+% Vsize[Header] = HeaderHeight ;
+% Vsize[HeaderSeparator] = HeaderDistance ;
+% Vsize[Text] = TextHeight ;
+% Vsize[FooterSeparator] = FooterDistance ;
+% Vsize[Footer] = FooterHeight ;
+% Vsize[BottomSeparator] = BottomDistance ;
+% Vsize[Bottom] = BottomHeight ;
+%
+% Vstep[Top] = Vstep[TopSeparator] +Vsize[TopSeparator] ;
+% Vstep[TopSeparator] = PaperHeight-TopSpace ;
+% Vstep[Header] = Vstep[TopSeparator] -Vsize[Header] ;
+% Vstep[HeaderSeparator] = Vstep[Header] -Vsize[HeaderSeparator] ;
+% Vstep[Text] = Vstep[HeaderSeparator]-Vsize[Text] ;
+% Vstep[FooterSeparator] = Vstep[Text] -Vsize[FooterSeparator] ;
+% Vstep[Footer] = Vstep[FooterSeparator]-Vsize[Footer] ;
+% Vstep[BottomSeparator] = Vstep[Footer] -Vsize[BottomSeparator] ;
+% Vstep[Bottom] = Vstep[BottomSeparator]-Vsize[Bottom] ;
+%
+% Hsize[LeftEdge] = LeftEdgeWidth ;
+% Hsize[LeftEdgeSeparator] = LeftEdgeDistance ;
+% Hsize[LeftMargin] = LeftMarginWidth ;
+% Hsize[LeftMarginSeparator] = LeftMarginDistance ;
+% Hsize[Text] = MakeupWidth ;
+% Hsize[RightMarginSeparator] = RightMarginDistance ;
+% Hsize[RightMargin] = RightMarginWidth ;
+% Hsize[RightEdgeSeparator] = RightEdgeDistance ;
+% Hsize[RightEdge] = RightEdgeWidth ;
+%
+% Hstep[LeftEdge] = Hstep[LeftEdgeSeparator] -Hsize[LeftEdge] ;
+% Hstep[LeftEdgeSeparator] = Hstep[LeftMargin] -Hsize[LeftEdgeSeparator] ;
+% Hstep[LeftMargin] = Hstep[LeftMarginSeparator] -Hsize[LeftMargin] ;
+% Hstep[LeftMarginSeparator] = Hstep[Text] -Hsize[LeftMarginSeparator] ;
+% Hstep[Text] = BackSpace ;
+% Hstep[RightMarginSeparator] = Hstep[Text] +Hsize[Text] ;
+% Hstep[RightMargin] = Hstep[RightMarginSeparator]+Hsize[RightMarginSeparator] ;
+% Hstep[RightEdgeSeparator] = Hstep[RightMargin] +Hsize[RightMargin] ;
+% Hstep[RightEdge] = Hstep[RightEdgeSeparator] +Hsize[RightEdgeSeparator] ;
+%
+% for VerPos=Top step 10 until Bottom:
+% for HorPos=LeftEdge step 1 until RightEdge:
+% Area[HorPos][VerPos] := unitsquare xscaled Hsize[HorPos] yscaled Vsize[VerPos] ;
+% Area[VerPos][HorPos] := Area[HorPos][VerPos] ;
+% Location[HorPos][VerPos] := (Hstep[HorPos],Vstep[VerPos]) ;
+% Location[VerPos][HorPos] := Location[HorPos][VerPos] ;
+% Field[HorPos][VerPos] := Area[HorPos][VerPos] shifted Location[HorPos][VerPos] ;
+% Field[VerPos][HorPos] := Field[HorPos][VerPos] ;
+% endfor ;
+% endfor ;
+%
+% Page := unitsquare xscaled PaperWidth yscaled PaperHeight ;
+%
+% enddef ;
+%
+% def BoundPageAreas =
+% % pickup pencircle scaled 0pt ;
+% bboxmargin := 0 ; setbounds currentpicture to Page ;
+% enddef ;
+%
+% def StartPage =
+% begingroup ;
+% if PageStateAvailable :
+% LoadPageState ;
+% SwapPageState ;
+% fi ;
+% SetPageAreas ;
+% BoundPageAreas ;
+% enddef ;
+%
+% def StopPage =
+% BoundPageAreas ;
+% endgroup ;
+% enddef ;
- numeric Vsize[], Hsize[], Vstep[], Hstep[] ;
+% Because metapost > 1.50 has dynamic memory management and is less
+% efficient than before we now delay calculations ... (on a document
+% with 150 pages the time spent in mp was close to 5 seconds which was
+% only due to initialising the page related areas, something that was
+% hardly noticeable before. At least now we're back to half a second
+% for such a case.
+def SetPageVsize =
+ numeric Vsize[] ;
Vsize[Top] = TopHeight ;
Vsize[TopSeparator] = TopDistance ;
Vsize[Header] = HeaderHeight ;
@@ -173,17 +267,10 @@ def SetPageAreas =
Vsize[Footer] = FooterHeight ;
Vsize[BottomSeparator] = BottomDistance ;
Vsize[Bottom] = BottomHeight ;
+enddef ;
- Vstep[Top] = Vstep[TopSeparator] +Vsize[TopSeparator] ;
- Vstep[TopSeparator] = PaperHeight-TopSpace ;
- Vstep[Header] = Vstep[TopSeparator] -Vsize[Header] ;
- Vstep[HeaderSeparator] = Vstep[Header] -Vsize[HeaderSeparator] ;
- Vstep[Text] = Vstep[HeaderSeparator]-Vsize[Text] ;
- Vstep[FooterSeparator] = Vstep[Text] -Vsize[FooterSeparator] ;
- Vstep[Footer] = Vstep[FooterSeparator]-Vsize[Footer] ;
- Vstep[BottomSeparator] = Vstep[Footer] -Vsize[BottomSeparator] ;
- Vstep[Bottom] = Vstep[BottomSeparator]-Vsize[Bottom] ;
-
+def SetPageHsize =
+ numeric Hsize[] ;
Hsize[LeftEdge] = LeftEdgeWidth ;
Hsize[LeftEdgeSeparator] = LeftEdgeDistance ;
Hsize[LeftMargin] = LeftMarginWidth ;
@@ -193,7 +280,23 @@ def SetPageAreas =
Hsize[RightMargin] = RightMarginWidth ;
Hsize[RightEdgeSeparator] = RightEdgeDistance ;
Hsize[RightEdge] = RightEdgeWidth ;
+enddef ;
+
+def SetPageVstep =
+ numeric Vstep[] ;
+ Vstep[Top] = Vstep[TopSeparator] +Vsize[TopSeparator] ;
+ Vstep[TopSeparator] = PaperHeight-TopSpace ;
+ Vstep[Header] = Vstep[TopSeparator] -Vsize[Header] ;
+ Vstep[HeaderSeparator] = Vstep[Header] -Vsize[HeaderSeparator] ;
+ Vstep[Text] = Vstep[HeaderSeparator]-Vsize[Text] ;
+ Vstep[FooterSeparator] = Vstep[Text] -Vsize[FooterSeparator] ;
+ Vstep[Footer] = Vstep[FooterSeparator]-Vsize[Footer] ;
+ Vstep[BottomSeparator] = Vstep[Footer] -Vsize[BottomSeparator] ;
+ Vstep[Bottom] = Vstep[BottomSeparator]-Vsize[Bottom] ;
+enddef ;
+def SetPageHstep =
+ numeric Hstep[] ;
Hstep[LeftEdge] = Hstep[LeftEdgeSeparator] -Hsize[LeftEdge] ;
Hstep[LeftEdgeSeparator] = Hstep[LeftMargin] -Hsize[LeftEdgeSeparator] ;
Hstep[LeftMargin] = Hstep[LeftMarginSeparator] -Hsize[LeftMargin] ;
@@ -203,22 +306,67 @@ def SetPageAreas =
Hstep[RightMargin] = Hstep[RightMarginSeparator]+Hsize[RightMarginSeparator] ;
Hstep[RightEdgeSeparator] = Hstep[RightMargin] +Hsize[RightMargin] ;
Hstep[RightEdge] = Hstep[RightEdgeSeparator] +Hsize[RightEdgeSeparator] ;
+enddef ;
+def SetPageArea =
+ path Area[][] ;
for VerPos=Top step 10 until Bottom:
for HorPos=LeftEdge step 1 until RightEdge:
- Area[HorPos][VerPos] := unitsquare xscaled Hsize[HorPos] yscaled Vsize[VerPos] ;
- Area[VerPos][HorPos] := Area[HorPos][VerPos] ;
- Location[HorPos][VerPos] := (Hstep[HorPos],Vstep[VerPos]) ;
- Location[VerPos][HorPos] := Location[HorPos][VerPos] ;
- Field[HorPos][VerPos] := Area[HorPos][VerPos] shifted Location[HorPos][VerPos] ;
- Field[VerPos][HorPos] := Field[HorPos][VerPos] ;
+ Area[HorPos][VerPos] := unitsquare xscaled Hsize[HorPos] yscaled Vsize[VerPos] ;
+ Area[VerPos][HorPos] := Area[HorPos][VerPos] ;
endfor ;
endfor ;
+enddef ;
+def SetPageLocation =
+ pair Location[][] ;
+ for VerPos=Top step 10 until Bottom:
+ for HorPos=LeftEdge step 1 until RightEdge:
+ Location[HorPos][VerPos] := (Hstep[HorPos],Vstep[VerPos]) ;
+ Location[VerPos][HorPos] := Location[HorPos][VerPos] ;
+ endfor ;
+ endfor ;
+enddef ;
+
+def SetPageField =
+ path Field[][] ;
+ for VerPos=Top step 10 until Bottom:
+ for HorPos=LeftEdge step 1 until RightEdge:
+ Field[HorPos][VerPos] := unitsquare xscaled Hsize[HorPos] yscaled Vsize[VerPos] shifted (Hstep[HorPos],Vstep[VerPos]) ;
+ Field[VerPos][HorPos] := Field[HorPos][VerPos] ;
+ endfor ;
+ endfor ;
+enddef ;
+
+def SetPagePage =
+ path Page ;
Page := unitsquare xscaled PaperWidth yscaled PaperHeight ;
+enddef ;
+def mfun_page_Area = hide(SetPageArea ;) Area enddef ;
+def mfun_page_Location = hide(SetPageLocation ;) Location enddef ;
+def mfun_page_Field = hide(SetPageField ;) Field enddef ;
+def mfun_page_Vsize = hide(SetPageVsize ;) Vsize enddef ;
+def mfun_page_Hsize = hide(SetPageHsize ;) Hsize enddef ;
+def mfun_page_Vstep = hide(SetPageVstep ;) Vstep enddef ;
+def mfun_page_Hstep = hide(SetPageHstep ;) Hstep enddef ;
+def mfun_page_Page = hide(SetPagePage ;) Page enddef ;
+
+def SetPageVariables =
+ let Area = mfun_page_Area ;
+ let Location = mfun_page_Location ;
+ let Field = mfun_page_Field ;
+ let Vsize = mfun_page_Vsize ;
+ let Hsize = mfun_page_Hsize ;
+ let Vstep = mfun_page_Vstep ;
+ let Hstep = mfun_page_Hstep ;
+ let Page = mfun_page_Page ;
enddef ;
+SetPageVariables ;
+
+let SetPageAreas = SetPageVariables ; % compatiblity
+
def BoundPageAreas =
% pickup pencircle scaled 0pt ;
bboxmargin := 0 ; setbounds currentpicture to Page ;
@@ -226,11 +374,13 @@ enddef ;
def StartPage =
begingroup ;
- if PageStateAvailable :
- LoadPageState ;
- SwapPageState ;
+ if mfun_first_run :
+ if PageStateAvailable :
+ LoadPageState ;
+ SwapPageState ;
+ fi ;
+ SetPageVariables ;
fi ;
- SetPageAreas ;
BoundPageAreas ;
enddef ;
@@ -272,15 +422,27 @@ def SetCoverAreas =
enddef ;
+% def StartCover =
+% begingroup ;
+% if PageStateAvailable :
+% LoadPageState ;
+% % SwapPageState ;
+% fi ;
+% SetPageAreas ;
+% SetCoverAreas ;
+% BoundCoverAreas ;
+% enddef ;
def StartCover =
begingroup ;
- if PageStateAvailable :
- LoadPageState ;
- % SwapPageState ;
+ if mfun_first_run :
+ if PageStateAvailable :
+ LoadPageState ;
+ % SwapPageState ;
+ fi ;
+ SetPageVariables ; % was SetPageAreas ;
+ SetCoverAreas ;
fi ;
- SetPageAreas ;
- SetCoverAreas ;
BoundCoverAreas ;
enddef ;
diff --git a/Master/texmf-dist/metapost/context/base/mp-shap.mpiv b/Master/texmf-dist/metapost/context/base/mp-shap.mpiv
index b62e636d56e..7136565108d 100644
--- a/Master/texmf-dist/metapost/context/base/mp-shap.mpiv
+++ b/Master/texmf-dist/metapost/context/base/mp-shap.mpiv
@@ -5,7 +5,7 @@
%D subtitle=shapes,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
%C
%C This module is part of the \CONTEXT\ macro||package and is
%C therefore copyrighted by \PRAGMA. See licen-en.pdf for
diff --git a/Master/texmf-dist/metapost/context/base/mp-step.mpiv b/Master/texmf-dist/metapost/context/base/mp-step.mpiv
index 654ef443d5a..f7a7ba5debb 100644
--- a/Master/texmf-dist/metapost/context/base/mp-step.mpiv
+++ b/Master/texmf-dist/metapost/context/base/mp-step.mpiv
@@ -5,7 +5,7 @@
%D subtitle=steps,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
%C
%C This module is part of the \CONTEXT\ macro||package and is
%C therefore copyrighted by \PRAGMA. See licen-en.pdf for
diff --git a/Master/texmf-dist/metapost/context/base/mp-text.mpiv b/Master/texmf-dist/metapost/context/base/mp-text.mpiv
index d5630f68ef2..b68e8412aef 100644
--- a/Master/texmf-dist/metapost/context/base/mp-text.mpiv
+++ b/Master/texmf-dist/metapost/context/base/mp-text.mpiv
@@ -5,7 +5,7 @@
%D subtitle=text support,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
%C
%C This module is part of the \CONTEXT\ macro||package and is
%C therefore copyrighted by \PRAGMA. See licen-en.pdf for
diff --git a/Master/texmf-dist/metapost/context/base/mp-tool.mpiv b/Master/texmf-dist/metapost/context/base/mp-tool.mpiv
index 764863b65ce..5b53dcdef91 100644
--- a/Master/texmf-dist/metapost/context/base/mp-tool.mpiv
+++ b/Master/texmf-dist/metapost/context/base/mp-tool.mpiv
@@ -5,12 +5,14 @@
%D subtitle=auxiliary macros,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
%C
%C This module is part of the \CONTEXT\ macro||package and is
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
+% def loadfile(expr name) = scantokens("input " & name & ";") enddef ;
+
if known context_tool : endinput ; fi ;
boolean context_tool ; context_tool := true ;
@@ -26,33 +28,7 @@ let @## = @# ;
if not known mpversion : string mpversion ; mpversion := "0.641" ; fi ;
-% vardef mpversiongt(expr s) =
-% scantokens (mpversion & " > " & if numeric s : decimal s else : s fi)
-% enddef ;
-% vardef mpversionlt(expr s) =
-% scantokens (mpversion & " < " & if numeric s : decimal s else : s fi)
-% enddef ;
-% vardef mpversioneq(expr s) =
-% scantokens (mpversion & " = " & if numeric s : decimal s else : s fi)
-% enddef ;
-
-%D More interesting:
-%D
-%D \starttyping
-%D fill fullcircle scaled 4cm withcolor if mpversiongt("0.6") : red else : green fi ;
-%D fill fullcircle scaled 2cm withcolor if mpversionlt(0.6) : blue else : white fi ;
-%D fill fullcircle scaled 1cm withcolor if mpversioncmp(0.6,">=") : yellow else : black fi ;
-%D \stoptyping
-
-% no longer needed as we load runtime
-
-vardef mpversioncmp(expr s, c) =
- scantokens (mpversion & c & if numeric s : decimal s else : s fi)
-enddef ;
-
-vardef mpversionlt (expr s) = mpversioncmp(s, "<") enddef ;
-vardef mpversioneq (expr s) = mpversioncmp(s, "=") enddef ;
-vardef mpversiongt (expr s) = mpversioncmp(s, ">") enddef ;
+newinternal metapostversion ; metapostversion := scantokens(mpversion) ;
%D We always want \EPS\ conforming output, so we say:
@@ -2181,3 +2157,168 @@ vardef mcomponent expr p = if cmykcolor p : magentapart p elseif rgbcolor p : 1
vardef ycomponent expr p = if cmykcolor p : yellowpart p elseif rgbcolor p : 1 - bluepart p else : p fi enddef ;
vardef bcomponent expr p = if cmykcolor p : blackpart p elseif rgbcolor p : 0 else : p fi enddef ;
+% draw image (...) ... ; % prescripts prepended to first, postscripts appended to last
+% draw decorated (...) ... ; % prescripts prepended to each, postscripts appended to each
+% draw redecorated (...) ... ; % prescripts assigned to each, postscripts assigned to each
+% draw undecorated (...) ... ; % following properties are ignored, existing properties are kept
+%
+% draw decorated (
+% draw fullcircle scaled 20cm withpen pencircle scaled 20mm withcolor red withtransparency (1,.40) ;
+% draw fullcircle scaled 15cm withpen pencircle scaled 15mm withcolor green withtransparency (1,.30) ;
+% draw fullcircle scaled 10cm withpen pencircle scaled 10mm withcolor blue withtransparency (1,.20) ;
+% )
+% withcolor blue
+% withtransparency (1,.125) % selectively applied
+% withpen pencircle scaled 10mm
+% ;
+
+% vardef image (text imagedata) = % already defined
+% save currentpicture ;
+% picture currentpicture ;
+% currentpicture := nullpicture ;
+% imagedata ;
+% currentpicture
+% enddef ;
+
+vardef undecorated (text imagedata) text decoration =
+ save currentpicture ;
+ picture currentpicture ;
+ currentpicture := nullpicture ;
+ imagedata ;
+ currentpicture
+enddef ;
+
+
+if metapostversion < 1.770 :
+
+ vardef decorated (text imagedata) text decoration =
+ save mfun_decorated_path, currentpicture ;
+ picture mfun_decorated_path, currentpicture ;
+ currentpicture := nullpicture ;
+ imagedata ;
+ mfun_decorated_path := currentpicture ;
+ currentpicture := nullpicture ;
+ for i within mfun_decorated_path :
+ addto currentpicture
+ if stroked i :
+ doublepath pathpart i
+ dashed dashpart i
+ withpen penpart i
+ withcolor colorpart i
+ decoration
+ elseif filled i :
+ contour pathpart i
+ withpen penpart i
+ withcolor colorpart i
+ decoration
+ elseif textual i :
+ also i
+ withcolor colorpart i
+ decoration
+ else :
+ also i
+ fi
+ ;
+ endfor ;
+ currentpicture
+ enddef ;
+
+else:
+
+ vardef decorated (text imagedata) text decoration =
+ save mfun_decorated_path, currentpicture ;
+ picture mfun_decorated_path, currentpicture ;
+ currentpicture := nullpicture ;
+ imagedata ;
+ mfun_decorated_path := currentpicture ;
+ currentpicture := nullpicture ;
+ for i within mfun_decorated_path :
+ addto currentpicture
+ if stroked i :
+ doublepath pathpart i
+ dashed dashpart i
+ withpen penpart i
+ withcolor colorpart i
+ withprescript prescriptpart i
+ withpostscript postscriptpart i
+ decoration
+ elseif filled i :
+ contour pathpart i
+ withpen penpart i
+ withcolor colorpart i
+ withprescript prescriptpart i
+ withpostscript postscriptpart i
+ decoration
+ elseif textual i :
+ also i
+ withcolor colorpart i
+ withprescript prescriptpart i
+ withpostscript postscriptpart i
+ decoration
+ else :
+ also i
+ fi
+ ;
+ endfor ;
+ currentpicture
+ enddef ;
+
+fi ;
+
+vardef redecorated (text imagedata) text decoration =
+ save mfun_decorated_path, currentpicture ;
+ picture mfun_decorated_path, currentpicture ;
+ currentpicture := nullpicture ;
+ imagedata ;
+ mfun_decorated_path := currentpicture ;
+ currentpicture := nullpicture ;
+ for i within mfun_decorated_path :
+ addto currentpicture
+ if stroked i :
+ doublepath pathpart i
+ dashed dashpart i
+ withpen penpart i
+ decoration
+ elseif filled i :
+ contour pathpart i
+ withpen penpart i
+ decoration
+ elseif textual i :
+ also i
+ decoration
+ else :
+ also i
+ fi
+ ;
+ endfor ;
+ currentpicture
+enddef ;
+
+% path mfun_bleed_box ;
+
+% primarydef p bleeded d =
+% image (
+% mfun_bleed_box := boundingbox p ;
+% if pair d :
+% draw p xysized (bbwidth(p)+2*xpart d,bbheight(p)+2*ypart d) shifted -d ;
+% else :
+% draw p xysized (bbwidth(p)+2d,bbheight(p)+2d) shifted (-d,-d) ;
+% fi ;
+% setbounds currentpicture to mfun_bleed_box ;
+% )
+% enddef ;
+
+%D Dimensions have bever been an issue as traditional MP can't make that large
+%D pictures, but with double mode we need a catch:
+
+newinternal maxdimensions ; maxdimensions := 14000 ;
+
+def mfun_apply_max_dimensions = % not a generic helper, we want to protect this one
+ if bbwidth currentpicture > maxdimensions :
+ currentpicture := currentpicture if bbheight currentpicture > bbwidth currentpicture : ysized else : xsized fi maxdimensions ;
+ elseif bbheight currentpicture > maxdimensions :
+ currentpicture := currentpicture ysized maxdimensions ;
+ fi ;
+enddef;
+
+extra_endfig := extra_endfig & "mfun_apply_max_dimensions ;" ;
diff --git a/Master/texmf-dist/scripts/context/lua/mtx-babel.lua b/Master/texmf-dist/scripts/context/lua/mtx-babel.lua
index 120e490929e..8c11465dea4 100644
--- a/Master/texmf-dist/scripts/context/lua/mtx-babel.lua
+++ b/Master/texmf-dist/scripts/context/lua/mtx-babel.lua
@@ -9,9 +9,23 @@ if not modules then modules = { } end modules ['mtx-babel'] = {
-- data tables by Thomas A. Schmitz
local helpinfo = [[
---language=string conversion language (e.g. greek)
---structure=string obey given structure (e.g. 'document', default: 'context')
---convert convert babel codes into utf
+
+
+
+ mtx-babel
+ Babel Input To UTF Conversion
+ 1.20
+
+
+
+
+ conversion language (e.g. greek)
+ obey given structure (e.g. 'document', default: 'context')
+ convert babel codes into utf
+
+
+
+
]]
local application = logs.application {
@@ -431,6 +445,8 @@ end
if environment.argument("convert") then
scripts.babel.convert(environment.files[1] or "")
+elseif environment.argument("exporthelp") then
+ application.export(environment.argument("exporthelp"),environment.files[1])
else
application.help()
end
diff --git a/Master/texmf-dist/scripts/context/lua/mtx-base.lua b/Master/texmf-dist/scripts/context/lua/mtx-base.lua
index ab5bfe18a9b..bd674971793 100644
--- a/Master/texmf-dist/scripts/context/lua/mtx-base.lua
+++ b/Master/texmf-dist/scripts/context/lua/mtx-base.lua
@@ -7,29 +7,43 @@ if not modules then modules = { } end modules ['mtx-base'] = {
}
local helpinfo = [[
---generate generate file database
---variables show configuration variables
---configurations show configuration order
---expand-braces expand complex variable
---expand-path expand variable (resolve paths)
---expand-var expand variable (resolve references)
---show-path show path expansion of ...
---var-value report value of variable
---find-file report file location
---find-path report path of file
---make or --ini make luatex format
---run or --fmt= run luatex format
---compile assemble and compile lua inifile
---verbose give a bit more info
---all show all found files
---format=str filter cf format specification (default 'tex', use 'any' for any match)
---pattern=str filter variables
---trackers=list enable given trackers
+
+
+
+ mtx-base
+ ConTeXt TDS Management Tool (aka luatools)
+ 1.35
+
+
+
+
+ generate file database
+ show configuration variables
+ show configuration order
+ expand complex variable
+ expand variable (resolve paths)
+ expand variable (resolve references)
+ show path expansion of ...
+ report value of variable
+ report file location
+ report path of file
+ [or ] make luatex format
+ [or ] run luatex format
+ assemble and compile lua inifile
+ give a bit more info
+ show all found files
+ filter cf format specification (default 'tex', use 'any' for any match)
+ filter variables
+ enable given trackers
+
+
+
+
]]
local application = logs.application {
name = "mtx-base",
- banner = "ConTeXt TDS Management Tool 1.35 (aka luatools)",
+ banner = "ConTeXt TDS Management Tool (aka luatools) 1.35",
helpinfo = helpinfo,
}
@@ -107,6 +121,8 @@ elseif environment.arguments["variables"] or environment.arguments["show-variabl
elseif environment.arguments["configurations"] or environment.arguments["show-configurations"] then
resolvers.load("nofiles")
resolvers.listers.configurations()
+elseif environment.arguments["exporthelp"] then
+ application.export(environment.arguments["exporthelp"],environment.files[1])
elseif environment.arguments["help"] or (environment.files[1]=='help') or (#environment.files==0) then
application.help()
elseif environment.files[1] == 'texmfcnf.lua' then
diff --git a/Master/texmf-dist/scripts/context/lua/mtx-cache.lua b/Master/texmf-dist/scripts/context/lua/mtx-cache.lua
index 08202bbf816..cd5512618d5 100644
--- a/Master/texmf-dist/scripts/context/lua/mtx-cache.lua
+++ b/Master/texmf-dist/scripts/context/lua/mtx-cache.lua
@@ -7,11 +7,26 @@ if not modules then modules = { } end modules ['mtx-cache'] = {
}
local helpinfo = [[
---purge remove not used files
---erase completely remove cache
---list show cache
-
---all all (not yet implemented)
+
+
+
+ mtx-cache
+ ConTeXt & MetaTeX Cache Management
+ 0.10
+
+
+
+
+ remove not used files
+ completely remove cache
+ show cache
+
+
+ all (not yet implemented)
+
+
+
+
]]
local application = logs.application {
@@ -114,6 +129,8 @@ elseif environment.argument("erase") then
scripts.cache.erase()
elseif environment.argument("list") then
scripts.cache.list()
+elseif environment.argument("exporthelp") then
+ application.export(environment.argument("exporthelp"),environment.files[1])
else
application.help()
end
diff --git a/Master/texmf-dist/scripts/context/lua/mtx-chars.lua b/Master/texmf-dist/scripts/context/lua/mtx-chars.lua
index ad2c499bef4..9f6852da245 100644
--- a/Master/texmf-dist/scripts/context/lua/mtx-chars.lua
+++ b/Master/texmf-dist/scripts/context/lua/mtx-chars.lua
@@ -9,9 +9,23 @@ if not modules then modules = { } end modules ['mtx-chars'] = {
-- obsolete: --stix convert stix table to math table
local helpinfo = [[
---xtx generate xetx-*.tex (used by xetex)
---pdf generate pdfr-def.tex (used by pdftex)
---entities generate entities table
+
+
+
+ mtx-chars
+ MkII Character Table Generators
+ 0.10
+
+
+
+
+ generate xetx-*.tex (used by xetex)
+ generate pdfr-def.tex (used by pdftex)
+ generate entities table
+
+
+
+
]]
local application = logs.application {
@@ -387,6 +401,8 @@ elseif environment.argument("xtx") then
scripts.chars.makeencoutf()
elseif environment.argument("pdf") then
scripts.chars.makepdfr()
+elseif environment.argument("exporthelp") then
+ application.export(environment.argument("exporthelp"),environment.files[1])
else
application.help()
end
diff --git a/Master/texmf-dist/scripts/context/lua/mtx-check.lua b/Master/texmf-dist/scripts/context/lua/mtx-check.lua
index 8307a02c6b2..9f52509ec7e 100644
--- a/Master/texmf-dist/scripts/context/lua/mtx-check.lua
+++ b/Master/texmf-dist/scripts/context/lua/mtx-check.lua
@@ -11,7 +11,21 @@ local gsub, sub, format = string.gsub, string.sub, string.format
local insert, remove = table.insert, table.remove
local helpinfo = [[
---convert check tex file for errors
+
+
+
+ mtx-check
+ Basic ConTeXt Syntax Checking
+ 0.10
+
+
+
+
+ check tex file for errors
+
+
+
+
]]
local application = logs.application {
@@ -229,6 +243,8 @@ if environment.argument("check") then
scripts.checker.check(environment.files[1])
elseif environment.argument("help") then
application.help()
+elseif environment.argument("exporthelp") then
+ application.export(environment.argument("exporthelp"),environment.files[1])
elseif environment.files[1] then
scripts.checker.check(environment.files[1])
else
diff --git a/Master/texmf-dist/scripts/context/lua/mtx-colors.lua b/Master/texmf-dist/scripts/context/lua/mtx-colors.lua
index 2a51d50990e..7dd1b4ac4b0 100644
--- a/Master/texmf-dist/scripts/context/lua/mtx-colors.lua
+++ b/Master/texmf-dist/scripts/context/lua/mtx-colors.lua
@@ -9,11 +9,29 @@ if not modules then modules = { } end modules ['mtx-colors'] = {
-- todo: fc-cache -v en check dirs, or better is: fc-cat -v | grep Directory
local helpinfo = [[
---table show icc table
-
-example:
-
-mtxrun --script color --table somename
+
+
+
+ mtx-colors
+ ConTeXt Color Management
+ 0.10
+
+
+
+
+ show icc table
+
+
+
+
+
+ Example
+
+ mtxrun --script color --table somename
+
+
+
+
]]
local application = logs.application {
@@ -52,6 +70,8 @@ end
if environment.argument("table") then
scripts.colors.table()
+elseif environment.argument("exporthelp") then
+ application.export(environment.argument("exporthelp"),environment.files[1])
else
application.help()
end
diff --git a/Master/texmf-dist/scripts/context/lua/mtx-context.lua b/Master/texmf-dist/scripts/context/lua/mtx-context.lua
index e07ecdfc7fe..add21fc90ff 100644
--- a/Master/texmf-dist/scripts/context/lua/mtx-context.lua
+++ b/Master/texmf-dist/scripts/context/lua/mtx-context.lua
@@ -6,247 +6,157 @@ if not modules then modules = { } end modules ['mtx-context'] = {
license = "see context related readme files"
}
+-- todo: more local functions
+-- todo: pass jobticket/ctxdata table around
+
+local type, next, tostring, tonumber = type, next, tostring, tonumber
local format, gmatch, match, gsub, find = string.format, string.gmatch, string.match, string.gsub, string.find
-local quote = string.quote
+local quote, validstring = string.quote, string.valid
local concat = table.concat
+local settings_to_array = utilities.parsers.settings_to_array
+local appendtable = table.append
+local lpegpatterns, lpegmatch, Cs, P = lpeg.patterns, lpeg.match, lpeg.Cs, lpeg.P
-local getargument = environment.argument
-
-local basicinfo = [[
---run process (one or more) files (default action)
---make create context formats
-
---ctx=name use ctx file (process management specification)
---interface use specified user interface (default: en)
-
---autopdf close pdf file in viewer and start pdf viewer afterwards
---purge(all) purge files either or not after a run (--pattern=...)
-
---usemodule=list load the given module or style, normally part o fthe distribution
---environment=list load the given environment file first (document styles)
---mode=list enable given the modes (conditional processing in styles)
---path=list also consult the given paths when files are looked for
---arguments=list set variables that can be consulted during a run (key/value pairs)
---randomseed=number set the randomseed
---result=name rename the resulting output to the given name
---trackers=list set tracker variables (show list with --showtrackers)
---directives=list set directive variables (show list with --showdirectives)
---silent=list disable logcatgories (show list with --showlogcategories)
---noconsole disable logging to the console (logfile only)
---purgeresult purge result file before run
-
---forcexml force xml stub (optional flag: --mkii)
---forcecld force cld (context lua document) stub
-
---arrange run extra imposition pass, given that the style sets up imposition
---noarrange ignore imposition specifications in the style
-
---once only run once (no multipass data file is produced)
---batchmode run without stopping and don't show messages on the console
---nonstopmode run without stopping
-
---generate generate file database etc. (as luatools does)
---paranoid don't descend to .. and ../..
---version report installed context version
-
---global assume given file present elsewhere
-
---expert expert options
-]]
-
--- filter=list is kind of obsolete
--- color is obsolete for mkiv, always on
--- separation is obsolete for mkiv, no longer available
--- output is currently obsolete for mkiv
--- setuppath=list must check
--- modefile=name must check
--- input=name load the given inputfile (must check)
-
-local expertinfo = [[
-expert options:
-
---touch update context version number (remake needed afterwards, also provide --expert)
---nostats omit runtime statistics at the end of the run
---update update context from website (not to be confused with contextgarden)
---profile profile job (use: mtxrun --script profile --analyze)
---timing generate timing and statistics overview
-
---extra=name process extra (mtx-context- in distribution)
---extras show extras
-]]
-
-local specialinfo = [[
-special options:
-
---pdftex process file with texexec using pdftex
---xetex process file with texexec using xetex
-
---pipe don't check for file and enter scroll mode (--dummyfile=whatever.tmp)
-]]
+local getargument = environment.getargument or environment.argument
+local setargument = environment.setargument
local application = logs.application {
name = "mtx-context",
- banner = "ConTeXt Process Management 0.52",
- helpinfo = {
- basic = basicinfo,
- extra = extrainfo,
- expert = expertinfo,
- }
+ banner = "ConTeXt Process Management 0.60",
+ -- helpinfo = helpinfo, -- table with { category_a = text_1, category_b = text_2 } or helpstring or xml_blob
+ helpinfo = "mtx-context.xml",
}
+-- local luatexflags = {
+-- ["8bit"] = true, -- ignored, input is assumed to be in UTF-8 encoding
+-- ["default-translate-file"] = true, -- ignored, input is assumed to be in UTF-8 encoding
+-- ["translate-file"] = true, -- ignored, input is assumed to be in UTF-8 encoding
+-- ["etex"] = true, -- ignored, the etex extensions are always active
+--
+-- ["credits"] = true, -- display credits and exit
+-- ["debug-format"] = true, -- enable format debugging
+-- ["disable-write18"] = true, -- disable \write18{SHELL COMMAND}
+-- ["draftmode"] = true, -- switch on draft mode (generates no output PDF)
+-- ["enable-write18"] = true, -- enable \write18{SHELL COMMAND}
+-- ["file-line-error"] = true, -- enable file:line:error style messages
+-- ["file-line-error-style"] = true, -- aliases of --file-line-error
+-- ["no-file-line-error"] = true, -- disable file:line:error style messages
+-- ["no-file-line-error-style"] = true, -- aliases of --no-file-line-error
+-- ["fmt"] = true, -- load the format file FORMAT
+-- ["halt-on-error"] = true, -- stop processing at the first error
+-- ["help"] = true, -- display help and exit
+-- ["ini"] = true, -- be iniluatex, for dumping formats
+-- ["interaction"] = true, -- set interaction mode (STRING=batchmode/nonstopmode/scrollmode/errorstopmode)
+-- ["jobname"] = true, -- set the job name to STRING
+-- ["kpathsea-debug"] = true, -- set path searching debugging flags according to the bits of NUMBER
+-- ["lua"] = true, -- load and execute a lua initialization script
+-- ["mktex"] = true, -- enable mktexFMT generation (FMT=tex/tfm)
+-- ["no-mktex"] = true, -- disable mktexFMT generation (FMT=tex/tfm)
+-- ["nosocket"] = true, -- disable the lua socket library
+-- ["output-comment"] = true, -- use STRING for DVI file comment instead of date (no effect for PDF)
+-- ["output-directory"] = true, -- use existing DIR as the directory to write files in
+-- ["output-format"] = true, -- use FORMAT for job output; FORMAT is 'dvi' or 'pdf'
+-- ["parse-first-line"] = true, -- enable parsing of the first line of the input file
+-- ["no-parse-first-line"] = true, -- disable parsing of the first line of the input file
+-- ["progname"] = true, -- set the program name to STRING
+-- ["recorder"] = true, -- enable filename recorder
+-- ["safer"] = true, -- disable easily exploitable lua commands
+-- ["shell-escape"] = true, -- enable \write18{SHELL COMMAND}
+-- ["no-shell-escape"] = true, -- disable \write18{SHELL COMMAND}
+-- ["shell-restricted"] = true, -- restrict \write18 to a list of commands given in texmf.cnf
+-- ["synctex"] = true, -- enable synctex
+-- ["version"] = true, -- display version and exit
+-- ["luaonly"] = true, -- run a lua file, then exit
+-- ["luaconly"] = true, -- byte-compile a lua file, then exit
+-- ["jiton"] = false,
+-- }
+
local report = application.report
scripts = scripts or { }
scripts.context = scripts.context or { }
--- a demo cld file:
---
--- context.starttext()
--- context.chapter("Hello There")
--- context.readfile("tufte","","not found")
--- context.stoptext()
+-- for the moment here
--- l-file / todo
-
-function file.needsupdate(oldfile,newfile)
- return true
-end
-function file.syncmtimes(oldfile,newfile)
+if getargument("jit") or getargument("jiton") then
+ -- bonus shortcut, we assume than --jit also indicates the engine
+ -- although --jit and --engine=luajittex are independent
+ setargument("engine","luajittex")
end
--- l-io
+local engine_new = getargument("engine") or directives.value("system.engine")
+local engine_old = environment.ownbin
-function io.copydata(fromfile,tofile)
- io.savedata(tofile,io.loaddata(fromfile) or "")
+local function restart(engine_old,engine_new)
+ local command = format("%s --luaonly %q %s --redirected",engine_new,environment.ownname,environment.reconstructcommandline())
+ report(format("redirect %s -> %s: %s",engine_old,engine_new,command))
+ local result = os.execute(command)
+ os.exit(result)
end
--- ctx (will become util-ctx)
-
-local ctxrunner = { }
-
-function ctxrunner.filtered(str,method)
- str = tostring(str)
- if method == 'name' then str = file.removesuffix(file.basename(str))
- elseif method == 'path' then str = file.dirname(str)
- elseif method == 'suffix' then str = file.extname(str)
- elseif method == 'nosuffix' then str = file.removesuffix(str)
- elseif method == 'nopath' then str = file.basename(str)
- elseif method == 'base' then str = file.basename(str)
--- elseif method == 'full' then
--- elseif method == 'complete' then
--- elseif method == 'expand' then -- str = file.expandpath(str)
- end
- return str:gsub("\\","/")
+if getargument("redirected") then
+ setargument("engine",engine_old) -- later on we need this
+elseif engine_new == engine_old then
+ setargument("engine",engine_new) -- later on we need this
+elseif environment.validengines[engine_new] and engine_new ~= environment.basicengines[engine_old] then
+ restart(engine_old,engine_new)
+else
+ setargument("engine",engine_new) -- later on we need this
end
-function ctxrunner.substitute(e,str)
- local attributes = e.at
- if str and attributes then
- if attributes['method'] then
- str = ctxrunner.filtered(str,attributes['method'])
- end
- if str == "" and attributes['default'] then
- str = attributes['default']
- end
- end
- return str
-end
+-- so far
-function ctxrunner.reflag(flags)
- local t = { }
- for _, flag in next, flags do
- local key, value = match(flag,"^(.-)=(.+)$")
- if key and value then
- t[key] = value
- else
- t[flag] = true
- end
- end
- return t
-end
+-- constants
-function ctxrunner.substitute(str)
- return str
-end
+local usedfiles = {
+ nop = "cont-nop.mkiv",
+ yes = "cont-yes.mkiv",
+}
-function ctxrunner.justtext(str)
- str = xml.unescaped(tostring(str))
- str = xml.cleansed(str)
- str = str:gsub("\\+",'/')
- str = str:gsub("%s+",' ')
- return str
-end
+local usedsuffixes = {
+ before = {
+ "tuc"
+ },
+ after = {
+ "pdf", "tuc", "log"
+ },
+ keep = {
+ "log"
+ },
+}
-function ctxrunner.new()
- return {
- ctxname = "",
- jobname = "",
- xmldata = nil,
- suffix = "prep",
- locations = { '..', '../..' },
- variables = { },
- messages = { },
- environments = { },
- modules = { },
- filters = { },
- flags = { },
- modes = { },
- prepfiles = { },
- paths = { },
- }
-end
+local formatofinterface = {
+ en = "cont-en",
+ uk = "cont-uk",
+ de = "cont-de",
+ fr = "cont-fr",
+ nl = "cont-nl",
+ cs = "cont-cs",
+ it = "cont-it",
+ ro = "cont-ro",
+ pe = "cont-pe",
+}
-function ctxrunner.savelog(ctxdata,ctlname)
- local function yn(b)
- if b then return 'yes' else return 'no' end
- end
- if not ctlname or ctlname == "" or ctlname == ctxdata.jobname then
- if ctxdata.jobname then
- ctlname = file.replacesuffix(ctxdata.jobname,'ctl')
- elseif ctxdata.ctxname then
- ctlname = file.replacesuffix(ctxdata.ctxname,'ctl')
- else
- report("invalid ctl name: %s",ctlname or "?")
- return
- end
- end
- local prepfiles = ctxdata.prepfiles
- if prepfiles and next(prepfiles) then
- report("saving logdata in: %s",ctlname)
- f = io.open(ctlname,'w')
- if f then
- f:write("\n\n")
- f:write(format("\n",yn(ctxdata.runlocal)))
- local sorted = table.sortedkeys(prepfiles)
- for i=1,#sorted do
- local name = sorted[i]
- f:write(format("\t%s \n",yn(prepfiles[name]),name))
- end
- f:write(" \n")
- f:close()
- end
- else
- report("nothing prepared, no ctl file saved")
- os.remove(ctlname)
- end
-end
+local defaultformats = {
+ "cont-en",
+ "cont-nl",
+}
-function ctxrunner.register_path(ctxdata,path)
- -- test if exists
- ctxdata.paths[ctxdata.paths+1] = path
-end
+-- process information
-function ctxrunner.trace(ctxdata)
- print(table.serialize(ctxdata.messages))
- print(table.serialize(ctxdata.flags))
- print(table.serialize(ctxdata.environments))
- print(table.serialize(ctxdata.modules))
- print(table.serialize(ctxdata.filters))
- print(table.serialize(ctxdata.modes))
- print(xml.tostring(ctxdata.xmldata))
+local ctxrunner = { } -- namespace will go
+
+local ctx_locations = { '..', '../..' }
+
+function ctxrunner.new()
+ return {
+ ctxname = "",
+ jobname = "",
+ flags = { },
+ }
end
-function ctxrunner.manipulate(ctxdata,ctxname,defaultname)
+function ctxrunner.checkfile(ctxdata,ctxname,defaultname)
if not ctxdata.jobname or ctxdata.jobname == "" then
return
@@ -269,13 +179,14 @@ function ctxrunner.manipulate(ctxdata,ctxname,defaultname)
local usedname = ctxdata.ctxname
local found = lfs.isfile(usedname)
- -- no futher test if qualified path
+ -- no further test if qualified path
if not found then
- for _, path in next, ctxdata.locations do
+ for _, path in next, ctx_locations do
local fullname = file.join(path,ctxdata.ctxname)
if lfs.isfile(fullname) then
- usedname, found = fullname, true
+ usedname = fullname
+ found = true
break
end
end
@@ -283,194 +194,70 @@ function ctxrunner.manipulate(ctxdata,ctxname,defaultname)
if not found then
usedname = resolvers.findfile(ctxdata.ctxname,"tex")
- found = usedname ~= ""
+ found = usedname ~= ""
end
if not found and defaultname and defaultname ~= "" and lfs.isfile(defaultname) then
- usedname, found = defaultname, true
+ usedname = defaultname
+ found = true
end
if not found then
return
end
- ctxdata.xmldata = xml.load(usedname)
+ local xmldata = xml.load(usedname)
- if not ctxdata.xmldata then
+ if not xmldata then
return
else
-- test for valid, can be text file
end
- xml.include(ctxdata.xmldata,'ctx:include','name', table.append({'.', file.dirname(ctxdata.ctxname)},ctxdata.locations))
-
- ctxdata.variables['job'] = ctxdata.jobname
-
- ctxdata.flags = xml.collect_texts(ctxdata.xmldata,"/ctx:job/ctx:flags/ctx:flag",true)
- ctxdata.environments = xml.collect_texts(ctxdata.xmldata,"/ctx:job/ctx:process/ctx:resources/ctx:environment",true)
- ctxdata.modules = xml.collect_texts(ctxdata.xmldata,"/ctx:job/ctx:process/ctx:resources/ctx:module",true)
- ctxdata.filters = xml.collect_texts(ctxdata.xmldata,"/ctx:job/ctx:process/ctx:resources/ctx:filter",true)
- ctxdata.modes = xml.collect_texts(ctxdata.xmldata,"/ctx:job/ctx:process/ctx:resources/ctx:mode",true)
- ctxdata.messages = xml.collect_texts(ctxdata.xmldata,"ctx:message",true)
-
- ctxdata.flags = ctxrunner.reflag(ctxdata.flags)
-
- local messages = ctxdata.messages
- for i=1,#messages do
- report("ctx comment: %s", xml.tostring(messages[i]))
- end
-
- for r, d, k in xml.elements(ctxdata.xmldata,"ctx:value[@name='job']") do
- d[k] = ctxdata.variables['job'] or ""
- end
-
- local commands = { }
- for e in xml.collected(ctxdata.xmldata,"/ctx:job/ctx:preprocess/ctx:processors/ctx:processor") do
- commands[e.at and e.at['name'] or "unknown"] = e
- end
-
- local suffix = xml.filter(ctxdata.xmldata,"/ctx:job/ctx:preprocess/attribute('suffix')") or ctxdata.suffix
- local runlocal = xml.filter(ctxdata.xmldata,"/ctx:job/ctx:preprocess/ctx:processors/attribute('local')")
+ local ctxpaths = table.append({'.', file.dirname(ctxdata.ctxname)}, ctx_locations)
- runlocal = toboolean(runlocal)
+ xml.include(xmldata,'ctx:include','name', ctxpaths)
- for files in xml.collected(ctxdata.xmldata,"/ctx:job/ctx:preprocess/ctx:files") do
- for pattern in xml.collected(files,"ctx:file") do
+ local flags = ctxdata.flags
- preprocessor = pattern.at['processor'] or ""
-
- if preprocessor ~= "" then
-
- ctxdata.variables['old'] = ctxdata.jobname
- for r, d, k in xml.elements(ctxdata.xmldata,"ctx:value") do
- local ek = d[k]
- local ekat = ek.at['name']
- if ekat == 'old' then
- d[k] = ctxrunner.substitute(ctxdata.variables[ekat] or "")
- end
- end
-
- pattern = ctxrunner.justtext(xml.tostring(pattern))
-
- local oldfiles = dir.glob(pattern)
-
- local pluspath = false
- if #oldfiles == 0 then
- -- message: no files match pattern
- local paths = ctxdata.paths
- for i=1,#paths do
- local p = paths[i]
- local oldfiles = dir.glob(path.join(p,pattern))
- if #oldfiles > 0 then
- pluspath = true
- break
- end
- end
- end
- if #oldfiles == 0 then
- -- message: no old files
- else
- for i=1,#oldfiles do
- local oldfile = oldfiles[i]
- local newfile = oldfile .. "." .. suffix -- addsuffix will add one only
- if ctxdata.runlocal then
- newfile = file.basename(newfile)
- end
- if oldfile ~= newfile and file.needsupdate(oldfile,newfile) then
- -- message: oldfile needs preprocessing
- -- os.remove(newfile)
- local splitted = preprocessor:split(',')
- for i=1,#splitted do
- local pp = splitted[i]
- local command = commands[pp]
- if command then
- command = xml.copy(command)
- local suf = (command.at and command.at['suffix']) or ctxdata.suffix
- if suf then
- newfile = oldfile .. "." .. suf
- end
- if ctxdata.runlocal then
- newfile = file.basename(newfile)
- end
- for r, d, k in xml.elements(command,"ctx:old") do
- d[k] = ctxrunner.substitute(oldfile)
- end
- for r, d, k in xml.elements(command,"ctx:new") do
- d[k] = ctxrunner.substitute(newfile)
- end
- ctxdata.variables['old'] = oldfile
- ctxdata.variables['new'] = newfile
- for r, d, k in xml.elements(command,"ctx:value") do
- local ek = d[k]
- local ekat = ek.at and ek.at['name']
- if ekat then
- d[k] = ctxrunner.substitute(ctxdata.variables[ekat] or "")
- end
- end
- -- potential optimization: when mtxrun run internal
- command = xml.content(command)
- command = ctxrunner.justtext(command)
- report("command: %s",command)
- local result = os.spawn(command) or 0
- -- somehow we get the wrong return value
- if result > 0 then
- report("error, return code: %s",result)
- end
- if ctxdata.runlocal then
- oldfile = file.basename(oldfile)
- end
- end
- end
- if lfs.isfile(newfile) then
- file.syncmtimes(oldfile,newfile)
- ctxdata.prepfiles[oldfile] = true
- else
- report("error, check target location of new file: %s", newfile)
- ctxdata.prepfiles[oldfile] = false
- end
- else
- report("old file needs no preprocessing")
- ctxdata.prepfiles[oldfile] = lfs.isfile(newfile)
- end
- end
- end
- end
+ for e in xml.collected(xmldata,"/ctx:job/ctx:flags/ctx:flag") do
+ local flag = xml.text(e) or ""
+ local key, value = match(flag,"^(.-)=(.+)$")
+ if key and value then
+ flags[key] = value
+ else
+ flags[flag] = true
end
end
- ctxrunner.savelog(ctxdata)
-
end
-function ctxrunner.preppedfile(ctxdata,filename)
- if ctxdata.prepfiles[file.basename(filename)] then
- return filename .. ".prep"
- else
- return filename
+function ctxrunner.checkflags(ctxdata)
+ if ctxdata then
+ for k,v in next, ctxdata.flags do
+ if getargument(k) == nil then
+ setargument(k,v)
+ end
+ end
end
end
--- rest
+-- multipass control
-scripts.context.multipass = {
--- suffixes = { ".tuo", ".tuc" },
- suffixes = { ".tuc" },
- nofruns = 8,
--- nofruns = 7, -- test oscillation
-}
+local multipass_suffixes = { ".tuc" }
+local multipass_nofruns = 8 -- or 7 to test oscillation
-function scripts.context.multipass.hashfiles(jobname)
+local function multipass_hashfiles(jobname)
local hash = { }
- local suffixes = scripts.context.multipass.suffixes
- for i=1,#suffixes do
- local suffix = suffixes[i]
+ for i=1,#multipass_suffixes do
+ local suffix = multipass_suffixes[i]
local full = jobname .. suffix
hash[full] = md5.hex(io.loaddata(full) or "unknown")
end
return hash
end
-function scripts.context.multipass.changed(oldhash, newhash)
+local function multipass_changed(oldhash, newhash)
for k,v in next, oldhash do
if v ~= newhash[k] then
return true
@@ -479,126 +266,7 @@ function scripts.context.multipass.changed(oldhash, newhash)
return false
end
-function scripts.context.multipass.makeoptionfile(jobname,ctxdata,kindofrun,currentrun,finalrun,once)
- -- take jobname from ctx
- jobname = file.removesuffix(jobname)
- local f = io.open(jobname..".top","w")
- if f then
- local function someflag(flag)
- return (ctxdata and ctxdata.flags[flag]) or getargument(flag)
- end
- local function setvalue(flag,template,hash,default)
- local a = someflag(flag) or default
- if a and a ~= "" then
- if hash then
- if hash[a] then
- f:write(format(template,a),"\n")
- end
- else
- f:write(format(template,a),"\n")
- end
- end
- end
- local function setvalues(flag,template,plural)
- if type(flag) == "table" then
- for k, v in next, flag do
- f:write(format(template,v),"\n")
- end
- else
- local a = someflag(flag) or (plural and someflag(flag.."s"))
- if a and a ~= "" then
- for v in gmatch(a,"%s*([^,]+)") do
- f:write(format(template,v),"\n")
- end
- end
- end
- end
- local function setfixed(flag,template,...)
- if someflag(flag) then
- f:write(format(template,...),"\n")
- end
- end
- local function setalways(template,...)
- f:write(format(template,...),"\n")
- end
- --
- -- This might change ... we can just pass the relevant flags directly.
- --
- setalways("%% runtime options files (command line driven)")
- --
- setalways("\\unprotect")
- --
- setalways("%% feedback and basic job control")
- --
- -- Option file, we can pass more on the commandline some day soon. Actually we
- -- should use directives and trackers.
- --
- setfixed ("timing" , "\\usemodule[timing]")
- setfixed ("batchmode" , "\\batchmode")
- setfixed ("batch" , "\\batchmode")
- setfixed ("nonstopmode" , "\\nonstopmode")
- setfixed ("nonstop" , "\\nonstopmode")
- -- setfixed ("tracefiles" , "\\tracefilestrue")
- setfixed ("nostats" , "\\nomkivstatistics")
- setfixed ("paranoid" , "\\def\\maxreadlevel{1}")
- --
- setalways("%% handy for special styles")
- --
- setalways("\\startluacode")
- setalways("document = document or { }")
- setalways(table.serialize(environment.arguments, "document.arguments"))
- setalways(table.serialize(environment.files, "document.files"))
- setalways("\\stopluacode")
- --
- setalways("%% process info")
- --
- setalways( "\\setupsystem[inputfile=%s]",getargument("input") or environment.files[1] or "\\jobname")
- setvalue ("result" , "\\setupsystem[file=%s]")
- setalways( "\\setupsystem[\\c!n=%s,\\c!m=%s]", kindofrun or 0, currentrun or 0)
- setvalues("path" , "\\usepath[%s]")
- setvalue ("setuppath" , "\\setupsystem[\\c!directory={%s}]")
- setvalue ("randomseed" , "\\setupsystem[\\c!random=%s]")
- setvalue ("arguments" , "\\setupenv[%s]")
- if once then
- setalways("\\enabledirectives[system.runonce]")
- end
- setalways("%% modes")
- setvalues("modefile" , "\\readlocfile{%s}{}{}")
- setvalues("mode" , "\\enablemode[%s]", true)
- if ctxdata then
- setvalues(ctxdata.modes, "\\enablemode[%s]")
- end
- --
- setalways("%% options (not that important)")
- --
- setalways("\\startsetups *runtime:options")
- setfixed ("color" , "\\setupcolors[\\c!state=\\v!start]")
- setvalue ("separation" , "\\setupcolors[\\c!split=%s]")
- setfixed ("noarrange" , "\\setuparranging[\\v!disable]")
- if getargument('arrange') and not finalrun then
- setalways( "\\setuparranging[\\v!disable]")
- end
- setalways("\\stopsetups")
- --
- setalways("%% styles and modules")
- --
- setalways("\\startsetups *runtime:modules")
- setvalues("usemodule" , "\\usemodule[%s]", true)
- setvalues("environment" , "\\environment %s ", true)
- if ctxdata then
- setvalues(ctxdata.modules, "\\usemodule[%s]")
- setvalues(ctxdata.environments, "\\environment %s ")
- end
- setalways("\\stopsetups")
- --
- setalways("%% done")
- --
- setalways("\\protect \\endinput")
- f:close()
- end
-end
-
-function scripts.context.multipass.copyluafile(jobname) -- obsolete
+local function multipass_copyluafile(jobname)
local tuaname, tucname = jobname..".tua", jobname..".tuc"
if lfs.isfile(tuaname) then
os.remove(tucname)
@@ -606,120 +274,59 @@ function scripts.context.multipass.copyluafile(jobname) -- obsolete
end
end
-scripts.context.cldsuffixes = table.tohash {
- "cld",
-}
-
-scripts.context.xmlsuffixes = table.tohash {
- "xml",
-}
-
-scripts.context.luasuffixes = table.tohash {
- "lua",
-}
-
-scripts.context.beforesuffixes = {
- "tuo", "tuc"
-}
-scripts.context.aftersuffixes = {
- "pdf", "tuo", "tuc", "log"
-}
-
-scripts.context.errorsuffixes = {
- "log"
-}
-
-scripts.context.interfaces = {
- en = "cont-en",
- uk = "cont-uk",
- de = "cont-de",
- fr = "cont-fr",
- nl = "cont-nl",
- cs = "cont-cs",
- it = "cont-it",
- ro = "cont-ro",
- pe = "cont-pe",
-}
-
-scripts.context.defaultformats = {
- "cont-en",
- "cont-nl",
--- "mptopdf", -- todo: mak emkiv variant
--- "metatex", -- will show up soon
--- "metafun", -- todo: mp formats
--- "plain"
-}
-
-local lpegpatterns, Cs, P = lpeg.patterns, lpeg.Cs, lpeg.P
+--
local pattern = lpegpatterns.utfbom^-1 * (P("%% ") + P("% ")) * Cs((1-lpegpatterns.newline)^1)
-local function analyze(filename) -- only files on current path
- local f = io.open(file.addsuffix(filename,"tex"))
- if f then
- local t = { }
- local line = f:read("*line") or ""
- local preamble = lpeg.match(pattern,line)
+local function preamble_analyze(filename) -- only files on current path
+ local t = { }
+ local line = io.loadlines(file.addsuffix(filename,"tex"))
+ if line then
+ local preamble = lpegmatch(pattern,line)
if preamble then
for key, value in gmatch(preamble,"(%S+)%s*=%s*(%S+)") do
t[key] = value
end
t.type = "tex"
- elseif line:find("^&1', file.replacesuffix(name,"pdf")))
---~ end
---~ function scripts.context.closepdf(name)
---~ os.spawn(format('pdfclose --file "%s" 2>&1', file.replacesuffix(name,"pdf")))
---~ end
+-- automatically opening and closing pdf files
-local pdfview -- delayed loading
+local pdfview -- delayed
-function scripts.context.openpdf(name,method)
+local function pdf_open(name,method)
pdfview = pdfview or dofile(resolvers.findfile("l-pdfview.lua","tex"))
pdfview.setmethod(method)
report(pdfview.status())
pdfview.open(file.replacesuffix(name,"pdf"))
end
-function scripts.context.closepdf(name,method)
+local function pdf_close(name,method)
pdfview = pdfview or dofile(resolvers.findfile("l-pdfview.lua","tex"))
pdfview.setmethod(method)
pdfview.close(file.replacesuffix(name,"pdf"))
end
-local function push_result_purge(oldbase,newbase)
- for _, suffix in next, scripts.context.aftersuffixes do
+-- result file handling
+
+local function result_push_purge(oldbase,newbase)
+ for _, suffix in next, usedsuffixes.after do
local oldname = file.addsuffix(oldbase,suffix)
local newname = file.addsuffix(newbase,suffix)
os.remove(newname)
@@ -727,8 +334,8 @@ local function push_result_purge(oldbase,newbase)
end
end
-local function push_result_keep(oldbase,newbase)
- for _, suffix in next, scripts.context.beforesuffixes do
+local function result_push_keep(oldbase,newbase)
+ for _, suffix in next, usedsuffixes.before do
local oldname = file.addsuffix(oldbase,suffix)
local newname = file.addsuffix(newbase,suffix)
local tmpname = "keep-"..oldname
@@ -739,8 +346,8 @@ local function push_result_keep(oldbase,newbase)
end
end
-local function save_result_error(oldbase,newbase)
- for _, suffix in next, scripts.context.errorsuffixes do
+local function result_save_error(oldbase,newbase)
+ for _, suffix in next, usedsuffixes.keep do
local oldname = file.addsuffix(oldbase,suffix)
local newname = file.addsuffix(newbase,suffix)
os.remove(newname) -- to be sure
@@ -748,8 +355,8 @@ local function save_result_error(oldbase,newbase)
end
end
-local function save_result_purge(oldbase,newbase)
- for _, suffix in next, scripts.context.aftersuffixes do
+local function result_save_purge(oldbase,newbase)
+ for _, suffix in next, usedsuffixes.after do
local oldname = file.addsuffix(oldbase,suffix)
local newname = file.addsuffix(newbase,suffix)
os.remove(newname) -- to be sure
@@ -757,8 +364,8 @@ local function save_result_purge(oldbase,newbase)
end
end
-local function save_result_keep(oldbase,newbase)
- for _, suffix in next, scripts.context.aftersuffixes do
+local function result_save_keep(oldbase,newbase)
+ for _, suffix in next, usedsuffixes.after do
local oldname = file.addsuffix(oldbase,suffix)
local newname = file.addsuffix(newbase,suffix)
local tmpname = "keep-"..oldname
@@ -768,313 +375,375 @@ local function save_result_keep(oldbase,newbase)
end
end
-function scripts.context.run(ctxdata,filename)
- -- filename overloads environment.files
- local files = (filename and { filename }) or environment.files
- if ctxdata then
- -- todo: interface
- for k,v in next, ctxdata.flags do
- environment.setargument(k,v)
+-- executing luatex
+
+local function flags_to_string(flags,prefix) -- context flags get prepended by c:
+ local t = { }
+ for k, v in table.sortedhash(flags) do
+ if prefix then
+ k = format("c:%s",k)
+ end
+ if not v or v == "" or v == '""' then
+ -- no need to flag false
+ elseif v == true then
+ t[#t+1] = format('--%s',k)
+ elseif type(v) == "string" then
+ t[#t+1] = format('--%s=%s',k,quote(v))
+ else
+ t[#t+1] = format('--%s=%s',k,tostring(v))
+ end
+ end
+ return concat(t," ")
+end
+
+local function luatex_command(l_flags,c_flags,filename,engine)
+ return format('%s %s %s "%s"',
+ engine or "luatex",
+ flags_to_string(l_flags),
+ flags_to_string(c_flags,true),
+ filename
+ )
+end
+
+local function run_texexec(filename,a_purge,a_purgeall)
+ if false then
+ -- we need to write a top etc too and run mp etc so it's not worth the
+ -- trouble, so it will take a while before the next is finished
+ --
+ -- context --extra=texutil --convert myfile
+ else
+ local texexec = resolvers.findfile("texexec.rb") or ""
+ if texexec ~= "" then
+ os.setenv("RUBYOPT","")
+ local options = environment.reconstructcommandline(environment.arguments_after)
+ options = gsub(options,"--purge","")
+ options = gsub(options,"--purgeall","")
+ local command = format("ruby %s %s",texexec,options)
+ report("running command: %s\n\n",command)
+ if a_purge then
+ os.execute(command)
+ scripts.context.purge_job(filename,false,true)
+ elseif a_purgeall then
+ os.execute(command)
+ scripts.context.purge_job(filename,true,true)
+ else
+ os.execute(command) -- we can use os.exec but that doesn't give back timing
+ end
end
end
- if #files > 0 then
+end
+
+--
+
+function scripts.context.run(ctxdata,filename)
+ --
+ local a_nofile = getargument("nofile")
+ local a_engine = getargument("engine")
+ --
+ local files = environment.files or { }
+ --
+ local filelist, mainfile
+ --
+ if filename then
+ -- the given forced name is processed, the filelist is passed to context
+ mainfile = filename
+ filelist = { filename }
+ -- files = files
+ elseif a_nofile then
+ -- the list of given files is processed using the dummy file
+ mainfile = usedfiles.nop
+ filelist = { usedfiles.nop }
+ -- files = { }
+ elseif #files > 0 then
+ -- the list of given files is processed using the stub file
+ mainfile = usedfiles.yes
+ filelist = files
+ files = { }
+ else
+ return
+ end
+ --
+ local interface = validstring(getargument("interface")) or "en"
+ local formatname = formatofinterface[interface] or "cont-en"
+ local formatfile, scriptfile = resolvers.locateformat(formatname) -- regular engine !
+ if not formatfile or not scriptfile then
+ report("warning: no format found, forcing remake (commandline driven)")
+ scripts.context.make(formatname)
+ formatfile, scriptfile = resolvers.locateformat(formatname) -- variant
+ end
+ if formatfile and scriptfile then
+ -- okay
+ elseif formatname then
+ report("error, no format found with name: %s, aborting",formatname)
+ return
+ else
+ report("error, no format found (provide formatname or interface)")
+ return
+ end
+ --
+ local a_mkii = getargument("mkii") or getargument("pdftex") or getargument("xetex")
+ local a_purge = getargument("purge")
+ local a_purgeall = getargument("purgeall")
+ local a_purgeresult = getargument("purgeresult")
+ local a_global = getargument("global")
+ local a_timing = getargument("timing")
+ local a_profile = getargument("profile")
+ local a_batchmode = getargument("batchmode")
+ local a_nonstopmode = getargument("nonstopmode")
+ local a_once = getargument("once")
+ local a_synctex = getargument("synctex")
+ local a_backend = getargument("backend")
+ local a_arrange = getargument("arrange")
+ local a_noarrange = getargument("noarrange")
+ local a_jiton = getargument("jiton")
+ --
+ a_batchmode = (a_batchmode and "batchmode") or (a_nonstopmode and "nonstopmode") or nil
+ a_synctex = tonumber(a_synctex) or (toboolean(a_synctex,true) and 1) or (a_synctex == "zipped" and 1) or (a_synctex == "unzipped" and -1) or nil
+ --
+ for i=1,#filelist do
--
- local interface = getargument("interface")
- -- todo: getargument("interface","en")
- interface = (type(interface) == "string" and interface) or "en"
+ local filename = filelist[i]
+ local basename = file.basename(filename)
+ local pathname = file.dirname(filename)
+ local jobname = file.removesuffix(basename)
+ local ctxname = ctxdata and ctxdata.ctxname
--
- local formatname = scripts.context.interfaces[interface] or "cont-en"
- local formatfile, scriptfile = resolvers.locateformat(formatname)
- -- this catches the command line
- if not formatfile or not scriptfile then
- report("warning: no format found, forcing remake (commandline driven)")
- scripts.context.make(formatname)
- formatfile, scriptfile = resolvers.locateformat(formatname)
+ if pathname == "" and not a_global and filename ~= usedfiles.nop then
+ filename = "./" .. filename
end
--
- if formatfile and scriptfile then
- for i=1,#files do
- local filename = files[i]
- local basename, pathname = file.basename(filename), file.dirname(filename)
- local jobname = file.removesuffix(basename)
- if pathname == "" and not getargument("global") then
- filename = "./" .. filename
+ local analysis = preamble_analyze(filename)
+ --
+ if a_mkii or analysis.engine == 'pdftex' or analysis.engine == 'xetex' then
+ run_texexec(filename,a_purge,a_purgeall)
+ else
+ if analysis.interface and analysis.interface ~= interface then
+ formatname = formatofinterface[analysis.interface] or formatname
+ formatfile, scriptfile = resolvers.locateformat(formatname)
+ end
+ --
+ a_jiton = (a_jiton or toboolean(analysis.jiton,true)) and true or nil
+ --
+ if not formatfile or not scriptfile then
+ report("warning: no format found, forcing remake (source driven)")
+ scripts.context.make(formatname,a_engine)
+ formatfile, scriptfile = resolvers.locateformat(formatname)
+ end
+ if formatfile and scriptfile then
+ local suffix = validstring(getargument("suffix"))
+ local resultname = validstring(getargument("result"))
+ if suffix then
+ resultname = file.removesuffix(jobname) .. suffix
end
- -- look at the first line
- local a = analyze(filename)
- if a and (a.engine == 'pdftex' or a.engine == 'xetex' or getargument("pdftex") or getargument("xetex")) then
- if false then
- -- we need to write a top etc too and run mp etc so it's not worth the
- -- trouble, so it will take a while before the next is finished
- --
- -- context --extra=texutil --convert myfile
- else
- local texexec = resolvers.findfile("texexec.rb") or ""
- if texexec ~= "" then
- os.setenv("RUBYOPT","")
- local options = environment.reconstructcommandline(environment.arguments_after)
- options = gsub(options,"--purge","")
- options = gsub(options,"--purgeall","")
- local command = format("ruby %s %s",texexec,options)
- if getargument("purge") then
- os.execute(command)
- scripts.context.purge_job(filename,false,true)
- elseif getargument("purgeall") then
- os.execute(command)
- scripts.context.purge_job(filename,true,true)
- else
- os.exec(command)
- end
+ local oldbase = ""
+ local newbase = ""
+ if resultname then
+ oldbase = file.removesuffix(jobname)
+ newbase = file.removesuffix(resultname)
+ if oldbase ~= newbase then
+ if a_purgeresult then
+ result_push_purge(oldbase,newbase)
+ else
+ result_push_keep(oldbase,newbase)
end
+ else
+ resultname = nil
end
- else
- if a and a.interface and a.interface ~= interface then
- formatname = scripts.context.interfaces[a.interface] or formatname
- formatfile, scriptfile = resolvers.locateformat(formatname)
+ end
+ --
+ local pdfview = getargument("autopdf") or getargument("closepdf")
+ if pdfview then
+ pdf_close(filename,pdfview)
+ if resultname then
+ pdf_close(resultname,pdfview)
end
- -- this catches the command line
- if not formatfile or not scriptfile then
- report("warning: no format found, forcing remake (source driven)")
- scripts.context.make(formatname)
- formatfile, scriptfile = resolvers.locateformat(formatname)
+ end
+ --
+ -- we could do this when locating the format and exit from luatex when
+ -- there is a version mismatch .. that way we can use stock luatex
+ -- plus mtxrun to run luajittex instead .. this saves a restart but is
+ -- also cleaner as then mtxrun only has to check for a special return
+ -- code (signaling a make + rerun) .. maybe some day
+ --
+ local okay = statistics.checkfmtstatus(formatfile,a_engine)
+ if okay ~= true then
+ report("warning: %s, forcing remake",tostring(okay))
+ scripts.context.make(formatname)
+ end
+ --
+ local oldhash = multipass_hashfiles(jobname)
+ local newhash = { }
+ local maxnofruns = once and 1 or multipass_nofruns
+ --
+ local c_flags = {
+ directives = validstring(environment.directives), -- gets passed via mtxrun
+ trackers = validstring(environment.trackers), -- gets passed via mtxrun
+ experiments = validstring(environment.experiments), -- gets passed via mtxrun
+ --
+ result = validstring(resultname),
+ input = validstring(getargument("input") or filename), -- alternative input
+ fulljobname = validstring(filename),
+ files = concat(files,","),
+ ctx = validstring(ctxname),
+ }
+ --
+ for k, v in next, environment.arguments do
+ -- the raw arguments
+ if c_flags[k] == nil then
+ c_flags[k] = v
end
- if formatfile and scriptfile then
- -- we default to mkiv xml !
- -- the --prep argument might become automatic (and noprep)
- local suffix = file.extname(filename) or "?"
- if scripts.context.xmlsuffixes[suffix] or getargument("forcexml") then
- if getargument("mkii") then
- filename = makestub(true,"\\processXMLfilegrouped{%s}",filename)
- else
- filename = makestub(true,"\\xmlprocess{\\xmldocument}{%s}{}",filename)
- end
- elseif scripts.context.cldsuffixes[suffix] or getargument("forcecld") then
- -- self contained cld files need to have a starttext/stoptext (less fontloading)
- filename = makestub(false,"\\ctxlua{context.runfile('%s')}",filename)
- elseif scripts.context.luasuffixes[suffix] or getargument("forcelua") then
- filename = makestub(true,"\\ctxlua{dofile('%s')}",filename)
- elseif getargument("prep") then
- -- we need to keep the original jobname
- filename = makestub(true,"\\readfile{%s}{}{}",filename,ctxrunner.preppedfile(ctxdata,filename))
- end
- --
- -- todo: also other stubs
- --
- local suffix, resultname = getargument("suffix"), getargument("result")
- if type(suffix) == "string" then
- resultname = file.removesuffix(jobname) .. suffix
- end
- local oldbase, newbase = "", ""
- if type(resultname) == "string" then
- oldbase = file.removesuffix(jobname)
- newbase = file.removesuffix(resultname)
- if oldbase ~= newbase then
- if getargument("purgeresult") then
- push_result_purge(oldbase,newbase)
- else
- push_result_keep(oldbase,newbase)
- end
- else
- resultname = nil
- end
- else
- resultname = nil
- end
- --
- local pdfview = getargument("autopdf") or getargument("closepdf")
- if pdfview then
- scripts.context.closepdf(filename,pdfview)
- if resultname then
- scripts.context.closepdf(resultname,pdfview)
- end
- end
- --
- local okay = statistics.checkfmtstatus(formatfile)
- if okay ~= true then
- report("warning: %s, forcing remake",tostring(okay))
- scripts.context.make(formatname)
- end
- --
- local flags = { }
- if getargument("batchmode") or getargument("batch") then
- flags[#flags+1] = "--interaction=batchmode"
- end
- if getargument("synctex") then
- -- this should become a directive
- report("warning: synctex is enabled") -- can add upto 5% runtime
- flags[#flags+1] = "--synctex=1"
- end
- flags[#flags+1] = "--fmt=" .. quote(formatfile)
- flags[#flags+1] = "--lua=" .. quote(scriptfile)
- --
- -- We pass these directly.
- --
-
---~ local silent = getargument("silent")
---~ local noconsole = getargument("noconsole")
---~ local directives = getargument("directives")
---~ local trackers = getargument("trackers")
---~ if silent == true then
---~ silent = "*"
---~ end
---~ if type(silent) == "string" then
---~ if type(directives) == "string" then
---~ directives = format("%s,logs.blocked={%s}",directives,silent)
---~ else
---~ directives = format("logs.blocked={%s}",silent)
---~ end
---~ end
---~ if noconsole then
---~ if type(directives) == "string" then
---~ directives = format("%s,logs.target=file",directives)
---~ else
---~ directives = format("logs.target=file")
---~ end
---~ end
-
- local directives = environment.directives
- local trackers = environment.trackers
- local experiments = environment.experiments
-
- --
- if type(directives) == "string" then
- flags[#flags+1] = format('--directives="%s"',directives)
- end
- if type(trackers) == "string" then
- flags[#flags+1] = format('--trackers="%s"',trackers)
- end
- --
- local backend = getargument("backend")
- if type(backend) ~= "string" then
- backend = "pdf"
- end
- flags[#flags+1] = format('--backend="%s"',backend)
- --
- local command = format("luatex %s %s \\stoptext", concat(flags," "), quote(filename))
- local oldhash, newhash = scripts.context.multipass.hashfiles(jobname), { }
- local once = getargument("once")
- local maxnofruns = (once and 1) or scripts.context.multipass.nofruns
- local arrange = getargument("arrange")
- for i=1,maxnofruns do
- -- 1:first run, 2:successive run, 3:once, 4:last of maxruns
- local kindofrun = (once and 3) or (i==1 and 1) or (i==maxnofruns and 4) or 2
- scripts.context.multipass.makeoptionfile(jobname,ctxdata,kindofrun,i,false,once) -- kindofrun, currentrun, final
- report("run %s: %s",i,command)
---~ print("\n") -- cleaner, else continuation on same line
- print("") -- cleaner, else continuation on same line
- local returncode, errorstring = os.spawn(command)
- --~ if returncode == 3 then
- --~ scripts.context.make(formatname)
- --~ returncode, errorstring = os.spawn(command)
- --~ if returncode == 3 then
- --~ report("ks: return code 3, message: %s",errorstring or "?")
- --~ os.exit(1)
- --~ end
- --~ end
- if not returncode then
- report("fatal error: no return code, message: %s",errorstring or "?")
- if resultname then
- save_result_error(oldbase,newbase)
- end
- os.exit(1)
- break
- elseif returncode > 0 then
- report("fatal error: return code: %s",returncode or "?")
- if resultname then
- save_result_error(oldbase,newbase)
- end
- os.exit(returncode)
- break
- else
- scripts.context.multipass.copyluafile(jobname)
- -- scripts.context.multipass.copytuifile(jobname)
- newhash = scripts.context.multipass.hashfiles(jobname)
- if scripts.context.multipass.changed(oldhash,newhash) then
- oldhash = newhash
- else
- break
- end
- end
- end
- --
- if arrange then
- local kindofrun = 3
- scripts.context.multipass.makeoptionfile(jobname,ctxdata,kindofrun,i,true) -- kindofrun, currentrun, final
- report("arrange run: %s",command)
- local returncode, errorstring = os.spawn(command)
- if not returncode then
- report("fatal error: no return code, message: %s",errorstring or "?")
- os.exit(1)
- elseif returncode > 0 then
- report("fatal error: return code: %s",returncode or "?")
- os.exit(returncode)
- end
- end
- --
- if getargument("purge") then
- scripts.context.purge_job(jobname)
- elseif getargument("purgeall") then
- scripts.context.purge_job(jobname,true)
- end
- --
- os.remove(jobname..".top")
- --
+ end
+ --
+ --
+ local l_flags = {
+ ["interaction"] = a_batchmode,
+ ["synctex"] = a_synctex,
+ ["no-parse-first-line"] = true,
+ -- ["no-mktex"] = true,
+ -- ["file-line-error-style"] = true,
+ ["fmt"] = formatfile,
+ ["lua"] = scriptfile,
+ ["jobname"] = jobname,
+ ["jiton"] = a_jiton,
+ }
+ --
+ if a_synctex then
+ report("warning: synctex is enabled") -- can add upto 5% runtime
+ end
+ --
+ if not a_timing then
+ -- okay
+ elseif c_flags.usemodule then
+ c_flags.usemodule = format("timing,%s",c_flags.usemodule)
+ else
+ c_flags.usemodule = "timing"
+ end
+ --
+ if not a_profile then
+ -- okay
+ elseif c_flags.directives then
+ c_flags.directives = format("system.profile,%s",c_flags.directives)
+ else
+ c_flags.directives = "system.profile"
+ end
+ --
+ -- kindofrun: 1:first run, 2:successive run, 3:once, 4:last of maxruns
+ --
+ for currentrun=1,maxnofruns do
+ --
+ c_flags.final = false
+ c_flags.kindofrun = (a_once and 3) or (currentrun==1 and 1) or (currentrun==maxnofruns and 4) or 2
+ c_flags.maxnofruns = maxnofruns
+ c_flags.currentrun = currentrun
+ c_flags.noarrange = a_noarrange or a_arrange or nil
+ --
+ local command = luatex_command(l_flags,c_flags,mainfile,a_engine)
+ --
+ report("run %s: %s",i,command)
+ print("") -- cleaner, else continuation on same line
+ local returncode, errorstring = os.spawn(command)
+ if not returncode then
+ report("fatal error: no return code, message: %s",errorstring or "?")
if resultname then
- if getargument("purgeresult") then
- -- so, if there is no result then we don't get the old one, but
- -- related files (log etc) are still there for tracing purposes
- save_result_purge(oldbase,newbase)
- else
- save_result_keep(oldbase,newbase)
- end
- report("result renamed to: %s",newbase)
- end
- --
- if getargument("purge") then
- scripts.context.purge_job(resultname)
- elseif getargument("purgeall") then
- scripts.context.purge_job(resultname,true)
+ result_save_error(oldbase,newbase)
end
- --
- local pdfview = getargument("autopdf")
- if pdfview then
- scripts.context.openpdf(resultname or filename,pdfview)
- end
- --
- if getargument("timing") then
- report()
- report("you can process (timing) statistics with:",jobname)
- report()
- report("context --extra=timing '%s'",jobname)
- report("mtxrun --script timing --xhtml [--launch --remove] '%s'",jobname)
- report()
+ os.exit(1)
+ break
+ elseif returncode == 0 then
+ multipass_copyluafile(jobname)
+ newhash = multipass_hashfiles(jobname)
+ if multipass_changed(oldhash,newhash) then
+ oldhash = newhash
+ else
+ break
end
else
- if formatname then
- report("error, no format found with name: %s, skipping",formatname)
- else
- report("error, no format found (provide formatname or interface)")
+ report("fatal error: return code: %s",returncode or "?")
+ if resultname then
+ result_save_error(oldbase,newbase)
end
+ os.exit(1) -- (returncode)
break
end
+ --
+ end
+ --
+ if a_arrange then
+ --
+ c_flags.final = true
+ c_flags.kindofrun = 3
+ c_flags.currentrun = c_flags.currentrun + 1
+ c_flags.noarrange = nil
+ --
+ local command = luatex_command(l_flags,c_flags,mainfile,a_engine)
+ --
+ report("arrange run: %s",command)
+ local returncode, errorstring = os.spawn(command)
+ if not returncode then
+ report("fatal error: no return code, message: %s",errorstring or "?")
+ os.exit(1)
+ elseif returncode > 0 then
+ report("fatal error: return code: %s",returncode or "?")
+ os.exit(returncode)
+ end
+ --
+ end
+ --
+ if a_purge then
+ scripts.context.purge_job(jobname)
+ elseif a_purgeall then
+ scripts.context.purge_job(jobname,true)
+ end
+ --
+ if resultname then
+ if a_purgeresult then
+ -- so, if there is no result then we don't get the old one, but
+ -- related files (log etc) are still there for tracing purposes
+ result_save_purge(oldbase,newbase)
+ else
+ result_save_keep(oldbase,newbase)
+ end
+ report("result renamed to: %s",newbase)
+ end
+ --
+ if purge then
+ scripts.context.purge_job(resultname)
+ elseif purgeall then
+ scripts.context.purge_job(resultname,true)
+ end
+ --
+ local pdfview = getargument("autopdf")
+ if pdfview then
+ pdf_open(resultname or jobname,pdfview)
+ end
+ --
+ if a_timing then
+ report()
+ report("you can process (timing) statistics with:",jobname)
+ report()
+ report("context --extra=timing '%s'",jobname)
+ report("mtxrun --script timing --xhtml [--launch --remove] '%s'",jobname)
+ report()
end
- end
- else
- if formatname then
- report("error, no format found with name: %s, aborting",formatname)
else
- report("error, no format found (provide formatname or interface)")
+ if formatname then
+ report("error, no format found with name: %s, skipping",formatname)
+ else
+ report("error, no format found (provide formatname or interface)")
+ end
+ break
end
end
end
+ --
end
-function scripts.context.pipe()
+function scripts.context.pipe() -- still used?
-- context --pipe
-- context --pipe --purge --dummyfile=whatever.tmp
local interface = getargument("interface")
interface = (type(interface) == "string" and interface) or "en"
- local formatname = scripts.context.interfaces[interface] or "cont-en"
+ local formatname = formatofinterface[interface] or "cont-en"
local formatfile, scriptfile = resolvers.locateformat(formatname)
if not formatfile or not scriptfile then
report("warning: no format found, forcing remake (commandline driven)")
@@ -1087,11 +756,16 @@ function scripts.context.pipe()
report("warning: %s, forcing remake",tostring(okay))
scripts.context.make(formatname)
end
- local flags = {
- "--interaction=scrollmode",
- "--fmt=" .. quote(formatfile),
- "--lua=" .. quote(scriptfile),
- "--backend=pdf",
+ local l_flags = {
+ interaction = "scrollmode",
+ fmt = formatfile,
+ lua = scriptfile,
+ }
+ local c_flags = {
+ backend = "pdf",
+ final = false,
+ kindofrun = 3,
+ currentrun = 1,
}
local filename = getargument("dummyfile") or ""
if filename == "" then
@@ -1100,10 +774,9 @@ function scripts.context.pipe()
else
filename = file.addsuffix(filename,"tmp")
io.savedata(filename,"\\relax")
- scripts.context.multipass.makeoptionfile(filename,{ flags = flags },3,1,false) -- kindofrun, currentrun, final
report("entering scrollmode using '%s' with optionfile, end job with \\end",filename)
end
- local command = format("luatex %s %s", concat(flags," "), quote(filename))
+ local command = luatex_command(l_flags,c_flags,filename)
os.spawn(command)
if getargument("purge") then
scripts.context.purge_job(filename)
@@ -1120,14 +793,14 @@ function scripts.context.pipe()
end
end
-local make_mkiv_format = environment.make_format
+local function make_mkiv_format(name,engine)
+ environment.make_format(name) -- jit is picked up later
+end
local function make_mkii_format(name,engine)
- if getargument(engine) then
- local command = format("mtxrun texexec.rb --make --%s %s",name,engine)
- report("running command: %s",command)
- os.spawn(command)
- end
+ local command = format("mtxrun texexec.rb --make --%s %s",name,engine)
+ report("running command: %s",command)
+ os.spawn(command)
end
function scripts.context.generate()
@@ -1140,14 +813,20 @@ function scripts.context.make(name)
if not getargument("fast") then -- as in texexec
scripts.context.generate()
end
- local list = (name and { name }) or (environment.files[1] and environment.files) or scripts.context.defaultformats
+ local list = (name and { name }) or (environment.files[1] and environment.files) or defaultformats
+ local engine = getargument("engine") or "luatex"
+ if getargument("jit") or getargument("jiton") then
+ engine = "luajittex"
+ end
for i=1,#list do
local name = list[i]
- name = scripts.context.interfaces[name] or name or ""
- if name ~= "" then
- make_mkiv_format(name)
- make_mkii_format(name,"pdftex")
- make_mkii_format(name,"xetex")
+ name = formatofinterface[name] or name or ""
+ if name == "" then
+ -- nothing
+ elseif engine == "luatex" or engine == "luajittex" then
+ make_mkiv_format(name,engine)
+ elseif engine == "pdftex" or engine == "xetex" then
+ make_mkii_format(name,engine)
end
end
end
@@ -1155,68 +834,77 @@ end
function scripts.context.ctx()
local ctxdata = ctxrunner.new()
ctxdata.jobname = environment.files[1]
- ctxrunner.manipulate(ctxdata,getargument("ctx"))
+ ctxrunner.checkfile(ctxdata,getargument("ctx"))
+ ctxrunner.checkflags(ctxdata)
scripts.context.run(ctxdata)
end
function scripts.context.autoctx()
local ctxdata = nil
- local files = (filename and { filename }) or environment.files
+ local files = environment.files
local firstfile = #files > 0 and files[1]
- if firstfile and file.extname(firstfile) == "xml" then
- local f = io.open(firstfile)
- if f then
- local chunk = f:read(512) or ""
- f:close()
- local ctxname = match(chunk,"<%?context%-directive%s+job%s+ctxfile%s+([^ ]-)%s*?>")
- if ctxname then
- ctxdata = ctxrunner.new()
- ctxdata.jobname = firstfile
- ctxrunner.manipulate(ctxdata,ctxname)
+ if firstfile then
+ local suffix = file.suffix(firstfile)
+ if suffix == "xml" then
+ local chunk = io.loadchunk(firstfile) -- 1024
+ if chunk then
+ local ctxname = match(chunk,"<%?context%-directive%s+job%s+ctxfile%s+([^ ]-)%s*?>")
+ if ctxname then
+ ctxdata = ctxrunner.new()
+ ctxdata.jobname = firstfile
+ ctxrunner.checkfile(ctxdata,ctxname)
+ ctxrunner.checkflags(ctxdata)
+ end
end
+ elseif suffix == "tex" then
+ -- maybe but we scan the preamble later too
end
end
scripts.context.run(ctxdata)
end
-local template = [[
-\starttext
- \directMPgraphic{%s}{input "%s"}
-\stoptext
-]]
-
-local loaded = false
-
-function scripts.context.metapost()
- local filename = environment.files[1] or ""
- if not loaded then
- dofile(resolvers.findfile("mlib-run.lua"))
- loaded = true
- commands = commands or { }
- commands.writestatus = report -- no longer needed
- end
- local formatname = getargument("format") or "metafun"
- if formatname == "" or type(formatname) == "boolean" then
- formatname = "metafun"
- end
- if getargument("pdf") then
- local basename = file.removesuffix(filename)
- local resultname = getargument("result") or basename
- local jobname = "mtx-context-metapost"
- local tempname = file.addsuffix(jobname,"tex")
- io.savedata(tempname,format(template,"metafun",filename))
- environment.files[1] = tempname
- environment.setargument("result",resultname)
- environment.setargument("once",true)
- scripts.context.run()
- scripts.context.purge_job(jobname,true)
- scripts.context.purge_job(resultname,true)
- elseif getargument("svg") then
- metapost.directrun(formatname,filename,"svg")
- else
- metapost.directrun(formatname,filename,"mps")
- end
-end
+-- no longer ok as mlib-run misses something:
+
+-- local template = [[
+-- \starttext
+-- \directMPgraphic{%s}{input "%s"}
+-- \stoptext
+-- ]]
+--
+-- local loaded = false
+--
+-- function scripts.context.metapost()
+-- local filename = environment.files[1] or ""
+-- if not loaded then
+-- dofile(resolvers.findfile("mlib-run.lua"))
+-- loaded = true
+-- commands = commands or { }
+-- commands.writestatus = report -- no longer needed
+-- end
+-- local formatname = getargument("format") or "metafun"
+-- if formatname == "" or type(formatname) == "boolean" then
+-- formatname = "metafun"
+-- end
+-- if getargument("pdf") then
+-- local basename = file.removesuffix(filename)
+-- local resultname = getargument("result") or basename
+-- local jobname = "mtx-context-metapost"
+-- local tempname = file.addsuffix(jobname,"tex")
+-- io.savedata(tempname,format(template,"metafun",filename))
+-- environment.files[1] = tempname
+-- setargument("result",resultname)
+-- setargument("once",true)
+-- scripts.context.run()
+-- scripts.context.purge_job(jobname,true)
+-- scripts.context.purge_job(resultname,true)
+-- elseif getargument("svg") then
+-- metapost.directrun(formatname,filename,"svg")
+-- else
+-- metapost.directrun(formatname,filename,"mps")
+-- end
+-- end
+
+-- --
function scripts.context.version()
local name = resolvers.findfile("context.mkiv")
@@ -1238,6 +926,8 @@ function scripts.context.version()
end
end
+-- purging files
+
local generic_files = {
"texexec.tex", "texexec.tui", "texexec.tuo",
"texexec.tuc", "texexec.tua",
@@ -1253,7 +943,7 @@ local temporary_runfiles = {
"tui", "tua", "tup", "ted", "tes", "top",
"log", "tmp", "run", "bck", "rlg",
"mpt", "mpx", "mpd", "mpo", "mpb", "ctl",
- "synctex.gz", "pgf",
+ "synctex", "synctex.gz", "pgf",
"prep",
}
@@ -1262,7 +952,6 @@ local persistent_runfiles = {
}
local special_runfiles = {
---~ "-mpgraph*", "-mprun*", "-temp-*" -- hm, wasn't this escaped?
"-mpgraph", "-mprun", "-temp-"
}
@@ -1278,9 +967,6 @@ local function purge_file(dfile,cfile)
end
end
-local function remove_special_files(pattern)
-end
-
function scripts.context.purge_job(jobname,all,mkiitoo)
if jobname and jobname ~= "" then
jobname = file.basename(jobname)
@@ -1318,7 +1004,7 @@ function scripts.context.purge(all,pattern,mkiitoo)
local deleted = { }
for i=1,#files do
local name = files[i]
- local suffix = file.extname(name)
+ local suffix = file.suffix(name)
local basename = file.basename(name)
if obsolete[suffix] or temporary[suffix] or persistent[suffix] or generic[basename] then
deleted[#deleted+1] = purge_file(name)
@@ -1335,64 +1021,86 @@ function scripts.context.purge(all,pattern,mkiitoo)
end
end
-local function touch(name,pattern)
+-- touching files (signals regeneration of formats)
+
+local function touch(name,versionpattern,kind,kindpattern)
local name = resolvers.findfile(name)
local olddata = io.loaddata(name)
if olddata then
+ local oldkind, newkind = "", kind or ""
local oldversion, newversion = "", os.date("%Y.%m.%d %H:%M")
- local newdata, ok = olddata:gsub(pattern,function(pre,mid,post)
- oldversion = mid
- return pre .. newversion .. post
- end)
- if ok > 0 then
+ local newdata
+ if versionpattern then
+ newdata = gsub(olddata,versionpattern,function(pre,mid,post)
+ oldversion = mid
+ return pre .. newversion .. post
+ end) or olddata
+ end
+ if kind and kindpattern then
+ newdata = gsub(newdata,kindpattern,function(pre,mid,post)
+ oldkind = mid
+ return pre .. newkind .. post
+ end) or newdata
+ end
+ if newdata ~= "" and (oldversion ~= newversion or oldkind ~= newkind or newdata ~= olddata) then
local backup = file.replacesuffix(name,"tmp")
os.remove(backup)
os.rename(name,backup)
io.savedata(name,newdata)
- return true, oldversion, newversion, name
- else
- return false
+ return name, oldversion, newversion, oldkind, newkind
end
end
end
-local function touchfiles(suffix)
- local done, oldversion, newversion, foundname = touch(file.addsuffix("context",suffix),"(\\edef\\contextversion{)(.-)(})")
- if done then
- report("old version : %s", oldversion)
- report("new version : %s", newversion)
- report("touched file: %s", foundname)
- local ok, _, _, foundname = touch(file.addsuffix("cont-new",suffix), "(\\newcontextversion{)(.-)(})")
- if ok then
- report("touched file: %s", foundname)
+local p_contextkind = "(\\edef\\contextkind%s*{)(.-)(})"
+local p_contextversion = "(\\edef\\contextversion%s*{)(.-)(})"
+local p_newcontextversion = "(\\newcontextversion%s*{)(.-)(})"
+
+local function touchfiles(suffix,kind)
+ local foundname, oldversion, newversion, oldkind, newkind = touch(file.addsuffix("context",suffix),p_contextversion,kind,p_contextkind)
+ if foundname then
+ report("old version : %s (%s)",oldversion,oldkind)
+ report("new version : %s (%s)",newversion,newkind)
+ report("touched file : %s",foundname)
+ local foundname = touch(file.addsuffix("cont-new",suffix),p_newcontextversion)
+ if foundname then
+ report("touched file : %s", foundname)
end
end
end
function scripts.context.touch()
if getargument("expert") then
- touchfiles("mkii")
- touchfiles("mkiv")
- touchfiles("mkvi")
+ local touch = getargument("touch")
+ local kind = getargument("kind")
+ if touch == "mkii" or touch == "mkiv" or touch == "mkvi" then -- mkix mkxi
+ touchfiles(touch,kind)
+ else
+ touchfiles("mkii",kind)
+ touchfiles("mkiv",kind)
+ touchfiles("mkvi",kind)
+ end
+ else
+ report("touching needs --expert")
end
end
-- modules
local labels = { "title", "comment", "status" }
-local cards = { "*.mkvi", "*.mkiv", "*.tex" }
+local cards = { "*.mkvi", "*.mkiv", "*.mkxi", "*.mkix", "*.tex" }
function scripts.context.modules(pattern)
local list = { }
local found = resolvers.findfile("context.mkiv")
if not pattern or pattern == "" then
-- official files in the tree
- for _, card in ipairs(cards) do
- resolvers.findwildcardfiles(card,list)
+ for i=1,#cards do
+ resolvers.findwildcardfiles(cards[i],list)
end
-- my dev path
- for _, card in ipairs(cards) do
- dir.glob(file.join(file.dirname(found),card),list)
+ for i=1,#cards do
+ dir.glob(file.join(file.dirname(found),cards[i]),list)
end
else
resolvers.findwildcardfiles(pattern,list)
@@ -1405,7 +1113,7 @@ function scripts.context.modules(pattern)
if not done[base] then
done[base] = true
local suffix = file.suffix(base)
- if suffix == "tex" or suffix == "mkiv" or suffix == "mkvi" then
+ if suffix == "tex" or suffix == "mkiv" or suffix == "mkvi" or suffix == "mkix" or suffix == "mkxi" then
local prefix = match(base,"^([xmst])%-")
if prefix then
v = resolvers.findfile(base) -- so that files on my dev path are seen
@@ -1462,30 +1170,28 @@ end
function scripts.context.extra()
local extra = getargument("extra")
- if type(extra) == "string" then
- if getargument("help") then
- scripts.context.extras(extra)
+ if type(extra) ~= "string" then
+ scripts.context.extras()
+ elseif getargument("help") then
+ scripts.context.extras(extra)
+ else
+ local fullextra = extra
+ if not find(fullextra,"mtx%-context%-") then
+ fullextra = "mtx-context-" .. extra
+ end
+ local foundextra = resolvers.findfile(fullextra)
+ if foundextra == "" then
+ scripts.context.extras()
+ return
else
- local fullextra = extra
- if not find(fullextra,"mtx%-context%-") then
- fullextra = "mtx-context-" .. extra
- end
- local foundextra = resolvers.findfile(fullextra)
- if foundextra == "" then
- scripts.context.extras()
- return
- else
- report("processing extra: %s", foundextra)
- end
- environment.setargument("purgeall",true)
- local result = environment.setargument("result") or ""
- if result == "" then
- environment.setargument("result","context-extra")
- end
- scripts.context.run(nil,foundextra)
+ report("processing extra: %s", foundextra)
end
- else
- scripts.context.extras()
+ setargument("purgeall",true)
+ local result = getargument("result") or ""
+ if result == "" then
+ setargument("result","context-extra")
+ end
+ scripts.context.run(nil,foundextra)
end
end
@@ -1493,25 +1199,27 @@ end
function scripts.context.trackers()
environment.files = { resolvers.findfile("m-trackers.mkiv") }
- scripts.context.multipass.nofruns = 1
- environment.setargument("purgeall",true)
+ multipass_nofruns = 1
+ setargument("purgeall",true)
scripts.context.run()
end
function scripts.context.directives()
environment.files = { resolvers.findfile("m-directives.mkiv") }
- scripts.context.multipass.nofruns = 1
- environment.setargument("purgeall",true)
+ multipass_nofruns = 1
+ setargument("purgeall",true)
scripts.context.run()
end
function scripts.context.logcategories()
environment.files = { resolvers.findfile("m-logcategories.mkiv") }
- scripts.context.multipass.nofruns = 1
- environment.setargument("purgeall",true)
+ multipass_nofruns = 1
+ setargument("purgeall",true)
scripts.context.run()
end
+-- updating (often one will use mtx-update instead)
+
function scripts.context.timed(action)
statistics.timed(action)
end
@@ -1548,7 +1256,7 @@ function scripts.context.update()
local function is_okay(basetree)
for _, tree in next, validtrees do
local pattern = gsub(tree,"%-","%%-")
- if basetree:find(pattern) then
+ if find(basetree,pattern) then
return tree
end
end
@@ -1614,7 +1322,7 @@ function scripts.context.update()
end
for k in zipfile:files() do
local filename = k.filename
- if filename:find("/$") then
+ if find(filename,"/$") then
lfs.mkdir(filename)
else
local data = zip.loaddata(zipfile,filename)
@@ -1652,6 +1360,23 @@ function scripts.context.update()
end
end
+-- getting it done
+
+if getargument("nostats") then
+ setargument("nostatistics",true)
+ setargument("nostat",nil)
+end
+
+if getargument("batch") then
+ setargument("batchmode",true)
+ setargument("batch",nil)
+end
+
+if getargument("nonstop") then
+ setargument("nonstopmode",true)
+ setargument("nonstop",nil)
+end
+
do
local silent = getargument("silent")
@@ -1664,17 +1389,12 @@ do
end
if getargument("once") then
- scripts.context.multipass.nofruns = 1
+ multipass_nofruns = 1
elseif getargument("runs") then
- scripts.context.multipass.nofruns = tonumber(getargument("runs")) or nil
-end
-
-if getargument("profile") then
- os.setenv("MTX_PROFILE_RUN","YES")
+ multipass_nofruns = tonumber(getargument("runs")) or nil
end
if getargument("run") then
--- scripts.context.timed(scripts.context.run)
scripts.context.timed(scripts.context.autoctx)
elseif getargument("make") then
scripts.context.timed(function() scripts.context.make() end)
@@ -1682,8 +1402,8 @@ elseif getargument("generate") then
scripts.context.timed(function() scripts.context.generate() end)
elseif getargument("ctx") then
scripts.context.timed(scripts.context.ctx)
-elseif getargument("mp") or getargument("metapost") then
- scripts.context.timed(scripts.context.metapost)
+-- elseif getargument("mp") or getargument("metapost") then
+-- scripts.context.timed(scripts.context.metapost)
elseif getargument("version") then
application.identify()
scripts.context.version()
@@ -1699,6 +1419,9 @@ elseif getargument("extras") then
scripts.context.extras(environment.files[1] or getargument("extras"))
elseif getargument("extra") then
scripts.context.extra()
+elseif getargument("exporthelp") then
+ -- application.export(getargument("exporthelp"),environment.files[1])
+ application.export()
elseif getargument("help") then
if environment.files[1] == "extras" then
scripts.context.extras()
@@ -1711,10 +1434,7 @@ elseif getargument("showdirectives") or getargument("directives") == true then
scripts.context.directives()
elseif getargument("showlogcategories") then
scripts.context.logcategories()
-elseif getargument("track") and type(getargument("track")) == "boolean" then -- for old times sake, will go
- scripts.context.trackers()
-elseif environment.files[1] then
--- scripts.context.timed(scripts.context.run)
+elseif environment.files[1] or getargument("nofile") then
scripts.context.timed(scripts.context.autoctx)
elseif getargument("pipe") then
scripts.context.timed(scripts.context.pipe)
@@ -1727,7 +1447,3 @@ elseif getargument("purgeall") then
else
application.help("basic")
end
-
-if getargument("profile") then
- os.setenv("MTX_PROFILE_RUN","NO")
-end
diff --git a/Master/texmf-dist/scripts/context/lua/mtx-context.xml b/Master/texmf-dist/scripts/context/lua/mtx-context.xml
new file mode 100644
index 00000000000..6eb8afeb105
--- /dev/null
+++ b/Master/texmf-dist/scripts/context/lua/mtx-context.xml
@@ -0,0 +1,187 @@
+
+
+
+
+ mtx-context
+ ConTeXt Process Management
+ 0.60
+ external helpinfo file
+
+
+
+
+
+ process (one or more) files (default action)
+
+
+ create context formats
+
+
+
+
+ use ctx file (process management specification)
+
+
+ use specified user interface (default: en)
+
+
+
+
+ close pdf file in viewer and start pdf viewer afterwards
+
+
+ purge files either or not after a run (=...)
+
+
+ purge all files either or not after a run (=...)
+
+
+
+
+ load the given module or style, normally part of the distribution
+
+
+ load the given environment file first (document styles)
+
+
+ enable given the modes (conditional processing in styles)
+
+
+ also consult the given paths when files are looked for
+
+
+ set variables that can be consulted during a run (key/value pairs)
+
+
+ set the randomseed
+
+
+ rename the resulting output to the given name
+
+
+ set tracker variables (show list with )
+
+
+ set directive variables (show list with )
+
+
+ disable logcatgories (show list with )
+
+
+ disable logging to the console (logfile only)
+
+
+ purge result file before run
+
+
+
+
+ force xml stub
+
+
+ force cld (context lua document) stub
+
+
+ force lua stub (like texlua)
+
+
+ force mp stub
+
+
+
+
+ run extra imposition pass, given that the style sets up imposition
+
+
+ ignore imposition specifications in the style
+
+
+
+
+ use luajittex with jit turned off (only use the faster virtual machine)
+
+
+ use luajittex with jit turned on (in most cases not faster, even slower)
+
+
+
+
+ only run once (no multipass data file is produced)
+
+
+ run without stopping and do not show messages on the console
+
+
+ run without stopping
+
+
+ run with synctex enabled (optional value: zipped, unzipped, 1, -1)
+
+
+
+
+ generate file database etc. (as luatools does)
+
+
+ do not descend to .. and ../..
+
+
+ report installed context version
+
+
+
+
+ assume given file present elsewhere
+
+
+ use dummy file as jobname
+
+
+
+
+
+
+ update context version number (remake needed afterwards, also provide )
+
+
+ omit runtime statistics at the end of the run
+
+
+ update context from website (not to be confused with contextgarden)
+
+
+ profile job (use: mtxrun profile )
+
+
+ generate timing and statistics overview
+
+
+
+
+ process extra (mtx-context-... in distribution)
+
+
+ show extras
+
+
+
+
+
+
+ process file with texexec using pdftex
+
+
+ process file with texexec using xetex
+
+
+ process file with texexec
+
+
+
+
+ do not check for file and enter scroll mode (=whatever.tmp)
+
+
+
+
+
diff --git a/Master/texmf-dist/scripts/context/lua/mtx-convert.lua b/Master/texmf-dist/scripts/context/lua/mtx-convert.lua
index b4e6e010bf8..b76b3baaf62 100644
--- a/Master/texmf-dist/scripts/context/lua/mtx-convert.lua
+++ b/Master/texmf-dist/scripts/context/lua/mtx-convert.lua
@@ -9,12 +9,26 @@ if not modules then modules = { } end modules ['mtx-convert'] = {
-- todo: eps and svg
local helpinfo = [[
---convertall convert all graphics on path
---inputpath=string original graphics path
---outputpath=string converted graphics path
---watch watch folders
---force force conversion (even if older)
---delay time between sweeps
+
+
+
+ mtx-convert
+ ConTeXT Graphic Conversion Helpers
+ 0.10
+
+
+
+
+ convert all graphics on path
+ original graphics path
+ converted graphics path
+ watch folders
+ force conversion (even if older)
+ time between sweeps
+
+
+
+
]]
local application = logs.application {
@@ -34,7 +48,7 @@ local convert = scripts.convert
convert.converters = convert.converters or { }
local converters = convert.converters
-local gsprogram = (os.type == "windows" and "gswin32c") or "gs"
+local gsprogram = os.type == "windows" and "gswin32c" or "gs"
local gstemplate_eps = "%s -q -sDEVICE=pdfwrite -dPDFSETTINGS=/prepress -dEPSCrop -dNOPAUSE -dSAFER -dNOCACHE -dBATCH -dAutoRotatePages=/None -dProcessColorModel=/DeviceCMYK -sOutputFile=%s %s -c quit"
local gstemplate_ps = "%s -q -sDEVICE=pdfwrite -dPDFSETTINGS=/prepress -dNOPAUSE -dSAFER -dNOCACHE -dBATCH -dAutoRotatePages=/None -dProcessColorModel=/DeviceCMYK -sOutputFile=%s %s -c quit"
@@ -83,7 +97,7 @@ function converters.convertpath(inputpath,outputpath)
inputpath = inputpath or "."
outputpath = outputpath or "."
for name in lfs.dir(inputpath) do
- local suffix = file.extname(name)
+ local suffix = file.suffix(name)
if find(name,"%.$") then
-- skip . and ..
elseif converters[suffix] then
@@ -102,7 +116,7 @@ function converters.convertpath(inputpath,outputpath)
end
function converters.convertfile(oldname)
- local suffix = file.extname(oldname)
+ local suffix = file.suffix(oldname)
if converters[suffix] then
local newname = file.replacesuffix(oldname,"pdf")
if oldname == newname then
@@ -154,6 +168,8 @@ if environment.arguments.convertall then
convert.convertall()
elseif environment.files[1] then
convert.convertgiven()
+elseif environment.argument("exporthelp") then
+ application.export(environment.argument("exporthelp"),environment.files[1])
else
application.help()
end
diff --git a/Master/texmf-dist/scripts/context/lua/mtx-epub.lua b/Master/texmf-dist/scripts/context/lua/mtx-epub.lua
index 7d1c157749f..11f0a202453 100644
--- a/Master/texmf-dist/scripts/context/lua/mtx-epub.lua
+++ b/Master/texmf-dist/scripts/context/lua/mtx-epub.lua
@@ -11,8 +11,8 @@ if not modules then modules = { } end modules ['mtx-epub'] = {
-- really an id but has some special property). Then there is this ncx suffix
-- thing. Somehow it give the impression of a reversed engineered application
-- format so it will probably take a few cycles to let it become a real
--- clean standard. Thanks to Adam Reviczky for helping to figure out all these
--- puzzling details.
+-- clean standard. Thanks to Adam Reviczky, Luigi Scarso and Andy Thomas for
+-- helping to figure out all the puzzling details.
-- This is preliminary code. At some point we will deal with images as well but
-- first we need a decent strategy to export them. More information will be
@@ -22,16 +22,34 @@ local format, gsub = string.format, string.gsub
local concat = table.concat
local helpinfo = [[
---make create epub zip file
-
-example:
-
-mtxrun --script epub --make mydocument
+
+
+
+ mtx-epub
+ ConTeXt EPUB Helpers
+ 0.12
+
+
+
+
+ create epub zip file
+
+
+
+
+
+ Example
+
+ mtxrun --script epub --make mydocument
+
+
+
+
]]
local application = logs.application {
name = "mtx-epub",
- banner = "ConTeXt EPUB Helpers 0.11",
+ banner = "ConTeXt EPUB Helpers 0.12",
helpinfo = helpinfo,
}
@@ -43,26 +61,27 @@ scripts.epub = scripts.epub or { }
local mimetype = "application/epub+zip"
local container = [[
-
+
-
+
]]
local package = [[
-
+
- My Title
- en
- urn:uuid:%s
- MySelf
+ %s
+ %s
+ urn:uuid:%s
+ %s
%s
+
@@ -70,13 +89,14 @@ local package = [[
+
]]
-local item = [[ ]]
+local item = [[ ]]
local toc = [[
@@ -108,6 +128,23 @@ local toc = [[
]]
+local coverxhtml = [[
+
+
+
+
+
+
+ cover.xhtml
+
+
+
+
+
+
+
+]]
+
-- We need to figure out what is permitted. Numbers only seem to give
-- problems is some applications as do names with dashes. Also the
-- optional toc is supposed to be there and although id's are by
@@ -117,7 +154,7 @@ local toc = [[
local function dumbid(filename)
-- return (string.gsub(os.uuid(),"%-%","")) -- to be tested
- return file.nameonly(filename) .. "-" .. file.extname(filename)
+ return file.nameonly(filename) .. "-" .. file.suffix(filename)
end
local mimetypes = {
@@ -128,6 +165,7 @@ local mimetypes = {
png = "image/png",
jpg = "image/jpeg",
ncx = "application/x-dtbncx+xml",
+ gif = "image/gif",
-- default = "text/plain",
}
@@ -194,9 +232,21 @@ function scripts.epub.make()
local files = specification.files or { file.addsuffix(filename,"xhtml") }
local images = specification.images or { }
local root = specification.root or files[1]
+ local language = specification.language or "en"
+ local creator = specification.author or "My Self"
+ local title = specification.title or "My Title"
+ local firstpage = specification.firstpage or ""
+ local lastpage = specification.lastpage or ""
-- identifier = gsub(identifier,"[^a-zA-z0-9]","")
+ if firstpage ~= "" then
+ images[firstpage] = firstpage
+ end
+ if lastpage ~= "" then
+ images[lastpage] = lastpage
+ end
+
identifier = "BookId" -- weird requirement
local epubname = name
@@ -204,11 +254,12 @@ function scripts.epub.make()
local epubfile = file.replacesuffix(name,"epub")
local epubroot = file.replacesuffix(name,"opf")
local epubtoc = "toc.ncx"
+ local epubcover = "cover.xhtml"
application.report("creating paths in tree %s",epubpath)
lfs.mkdir(epubpath)
lfs.mkdir(file.join(epubpath,"META-INF"))
- lfs.mkdir(file.join(epubpath,"OPS"))
+ lfs.mkdir(file.join(epubpath,"OEBPS"))
local used = { }
@@ -217,13 +268,14 @@ function scripts.epub.make()
local mime = mimetypes[suffix]
if mime then
local idmaker = idmakers[suffix] or idmakers.default
- local target = file.join(epubpath,"OPS",filename)
+ local target = file.join(epubpath,"OEBPS",filename)
file.copy(filename,target)
application.report("copying %s to %s",filename,target)
used[#used+1] = format(item,idmaker(filename),filename,mime)
end
end
+ copyone("cover.xhtml")
copyone("toc.ncx")
local function copythem(files)
@@ -241,7 +293,7 @@ function scripts.epub.make()
for k, v in table.sortedpairs(images) do
theimages[#theimages+1] = k
- if not lfs.isfile(k) and file.extname(k) == "svg" and file.extname(v) == "pdf" then
+ if not lfs.isfile(k) and file.suffix(k) == "svg" and file.suffix(v) == "pdf" then
local command = format("inkscape --export-plain-svg=%s %s",k,v)
application.report("running command '%s'\n\n",command)
os.execute(command)
@@ -250,33 +302,52 @@ function scripts.epub.make()
copythem(theimages)
- local idmaker = idmakers[file.extname(root)] or idmakers.default
-
- container = format(container,epubroot)
- package = format(package,identifier,identifier,os.uuid(),os.date("!%Y-%m-%dT%H:%M:%SZ"),concat(used,"\n"),idmaker(root))
- toc = format(toc,identifier,"title",root)
+ local idmaker = idmakers[file.suffix(root)] or idmakers.default
+
+ container = format(container,
+ epubroot
+ )
+ package = format(package,
+ identifier,
+ title,
+ language,
+ identifier,
+ os.uuid(),
+ creator,
+ os.date("!%Y-%m-%dT%H:%M:%SZ"),
+ idmaker(firstpage),
+ concat(used,"\n"),
+ idmaker(root)
+ )
+ toc = format(toc,
+ identifier,
+ title,
+ root
+ )
+ coverxhtml = format(coverxhtml,
+ firstpage
+ )
io.savedata(file.join(epubpath,"mimetype"),mimetype)
io.savedata(file.join(epubpath,"META-INF","container.xml"),container)
- io.savedata(file.join(epubpath,"OPS",epubroot),package)
- io.savedata(file.join(epubpath,"OPS",epubtoc),toc)
+ io.savedata(file.join(epubpath,"OEBPS",epubroot),package)
+ io.savedata(file.join(epubpath,"OEBPS",epubtoc),toc)
+ io.savedata(file.join(epubpath,"OEBPS",epubcover),coverxhtml)
application.report("creating archive\n\n")
- local done = false
- local list = { }
-
lfs.chdir(epubpath)
os.remove(epubfile)
+ local done = false
+
for i=1,#zippers do
local zipper = zippers[i]
if os.execute(format(zipper.uncompressed,epubfile,"mimetype")) then
os.execute(format(zipper.compressed,epubfile,"META-INF"))
- os.execute(format(zipper.compressed,epubfile,"OPS"))
+ os.execute(format(zipper.compressed,epubfile,"OEBPS"))
done = zipper.name
- else
- list[#list+1] = zipper.name
+ break
end
end
@@ -285,6 +356,10 @@ function scripts.epub.make()
if done then
application.report("epub archive made using %s: %s",done,file.join(epubpath,epubfile))
else
+ local list = { }
+ for i=1,#zippers do
+ list[#list+1] = zipper.name
+ end
application.report("no epub archive made, install one of: %s",concat(list," "))
end
@@ -296,6 +371,8 @@ end
if environment.argument("make") then
scripts.epub.make()
+elseif environment.argument("exporthelp") then
+ application.export(environment.argument("exporthelp"),environment.files[1])
else
application.help()
end
diff --git a/Master/texmf-dist/scripts/context/lua/mtx-fcd.lua b/Master/texmf-dist/scripts/context/lua/mtx-fcd.lua
new file mode 100644
index 00000000000..ba9299020ba
--- /dev/null
+++ b/Master/texmf-dist/scripts/context/lua/mtx-fcd.lua
@@ -0,0 +1,386 @@
+if not modules then modules = { } end modules ['mtx-fcd'] = {
+ version = 1.002,
+ comment = "companion to mtxrun.lua",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+ comment = "based on the ruby version from 2005",
+}
+
+-- This is a kind of variant of the good old ncd (norton change directory) program. This
+-- script uses the same indirect cmd trick as Erwin Waterlander's wcd program.
+--
+-- The program is called via the stubs fcd.cmd or fcd.sh. On unix one should probably source
+-- the file: ". fcd args" in order to make the chdir persistent.
+--
+-- You need to create a stub with:
+--
+-- mtxrun --script fcd --stub > fcd.cmd
+-- mtxrun --script fcd --stub > fcd.sh
+--
+-- The stub starts this script and afterwards runs the created directory change script as
+-- part if the same run, so that indeed we change.
+
+local helpinfo = [[
+
+
+
+ mtx-fcd
+ Fast Directory Change
+ 1.00
+
+
+
+
+ clear the cache
+ [entry] clear the history
+ clear the cache and add given path(s)
+ add given path(s)
+ find given path (can be substring)
+ find given path (can be substring) but don't use history
+ print platform stub file
+ show roots of cached dirs
+ show history of chosen dirs
+ show this help
+
+
+
+
+
+ Example
+
+ fcd --scan t:\
+ fcd --add f:\project
+ fcd [--find] whatever
+ fcd --list
+
+
+
+
+]]
+
+local application = logs.application {
+ name = "mtx-fcd",
+ banner = "Fast Directory Change 1.00",
+ helpinfo = helpinfo,
+}
+
+local report = application.report
+local writeln = print -- texio.write_nl
+
+local find, char, byte, lower, gsub, format = string.find, string.char, string.byte, string.lower, string.gsub, string.format
+
+local mswinstub = [[@echo off
+
+rem this is: fcd.cmd
+
+@echo off
+
+if not exist "%HOME%" goto homepath
+
+:home
+
+mtxrun --script mtx-fcd.lua %1 %2 %3 %4 %5 %6 %7 %8 %9
+
+if exist "%HOME%\mtx-fcd-goto.cmd" call "%HOME%\mtx-fcd-goto.cmd"
+
+goto end
+
+:homepath
+
+if not exist "%HOMEDRIVE%\%HOMEPATH%" goto end
+
+mtxrun --script mtx-fcd.lua %1 %2 %3 %4 %5 %6 %7 %8 %9
+
+if exist "%HOMEDRIVE%\%HOMEPATH%\mtx-fcd-goto.cmd" call "%HOMEDRIVE%\%HOMEPATH%\mtx-fcd-goto.cmd"
+
+goto end
+
+:end
+]]
+
+local unixstub = [[#!/usr/bin/env sh
+
+# this is: fcd.sh
+
+# mv fcd.sh fcd
+# chmod fcd 755
+# . fcd [args]
+
+ruby -S fcd_start.rb $1 $2 $3 $4 $5 $6 $7 $8 $9
+
+if test -f "$HOME/fcd_stage.sh" ; then
+ . $HOME/fcd_stage.sh ;
+fi;
+
+]]
+
+local gotofile
+local datafile
+local stubfile
+local stubdata
+local stubdummy
+local stubchdir
+
+if os.platform == 'mswin' then
+ gotofile = 'mtx-fcd-goto.cmd'
+ datafile = 'mtx-fcd-data.lua'
+ stubfile = 'fcd.cmd'
+ stubdata = mswinstub
+ stubdummy = 'rem no dir to change to'
+ stubchdir = 'cd /d "%s"'
+else
+ gotofile = 'mtx-fcd-goto.sh'
+ datafile = 'mtx-fcd-data.lua'
+ stubfile = 'fcd.sh'
+ stubdata = unixstub
+ stubdummy = '# no dir to change to'
+ stubchdir = '# cd "%s"'
+end
+
+local homedir = os.env["HOME"] or "" -- no longer TMP etc
+
+if homedir == "" then
+ homedir = format("%s/%s",os.env["HOMEDRIVE"] or "",os.env["HOMEPATH"] or "")
+end
+
+if homedir == "/" or not lfs.isdir(homedir) then
+ os.exit()
+end
+
+local datafile = file.join(homedir,datafile)
+local gotofile = file.join(homedir,gotofile)
+local hash = nil
+local found = { }
+local pattern = ""
+local version = modules['mtx-fcd'].version
+
+io.savedata(gotofile,stubdummy)
+
+if not lfs.isfile(gotofile) then
+ -- write error
+ os.exit()
+end
+
+local function fcd_clear(onlyhistory,what)
+ if onlyhistory and hash and hash.history then
+ if what and what ~= "" then
+ hash.history[what] = nil
+ else
+ hash.history = { }
+ end
+ else
+ hash = {
+ name = "fcd cache",
+ comment = "generated by mtx-fcd.lua",
+ created = os.date(),
+ version = version,
+ paths = { },
+ history = { },
+ }
+ end
+end
+
+local function fcd_changeto(dir)
+ if dir and dir ~= "" then
+ io.savedata(gotofile,format(stubchdir,dir))
+ end
+end
+
+local function fcd_load(forcecreate)
+ if lfs.isfile(datafile) then
+ hash = dofile(datafile)
+ end
+ if not hash or hash.version ~= version then
+ if forcecache then
+ fcd_clear()
+ else
+ writeln("empty dir cache")
+ fcd_clear()
+ os.exit()
+ end
+ end
+end
+
+local function fcd_save()
+ if hash then
+ io.savedata(datafile,table.serialize(hash,true))
+ end
+end
+
+local function fcd_list(onlyhistory)
+ if hash then
+ writeln("")
+ if onlyhistory then
+ if next(hash.history) then
+ for k, v in table.sortedhash(hash.history) do
+ writeln(format("%s => %s",k,v))
+ end
+ else
+ writeln("no history")
+ end
+ else
+ local paths = hash.paths
+ if #paths > 0 then
+ for i=1,#paths do
+ local path = paths[i]
+ writeln(format("%4i %s",#path[2],path[1]))
+ end
+ else
+ writeln("empty cache")
+ end
+ end
+ end
+end
+
+local function fcd_find()
+ found = { }
+ pattern = environment.files[1] or ""
+ if pattern ~= "" then
+ pattern = string.escapedpattern(pattern)
+ local paths = hash.paths
+ for i=1,#paths do
+ local paths = paths[i][2]
+ for i=1,#paths do
+ local path = paths[i]
+ if find(path,pattern) then
+ found[#found+1] = path
+ end
+ end
+ end
+ end
+end
+
+local function fcd_choose(new)
+ if pattern == "" then
+ writeln(format("staying in dir %q",(gsub(lfs.currentdir(),"\\","/"))))
+ return
+ end
+ if #found == 0 then
+ writeln(format("dir %q not found",pattern))
+ return
+ end
+ local okay = #found == 1 and found[1] or (not new and hash.history[pattern])
+ if okay then
+ writeln(format("changing to %q",okay))
+ fcd_changeto(okay)
+ return
+ end
+ local offset = 0
+ while true do
+ if not found[offset] then
+ offset = 0
+ end
+ io.write("\n")
+ for i=1,26 do
+ local v = found[i+offset]
+ if v then
+ writeln(format("%s %3i %s",char(i+96),offset+i,v))
+ else
+ break
+ end
+ end
+ offset = offset + 26
+ if found[offset+1] then
+ io.write("\n[press enter for more or select letter]\n\n>> ")
+ else
+ io.write("\n[select letter]\n\n>> ")
+ end
+ local answer = lower(io.read() or "")
+ if not answer or answer == 'quit' then
+ break
+ elseif #answer > 0 then
+ local choice = tonumber(answer)
+ if not choice then
+ if answer >= "a" and answer <= "z" then
+ choice = byte(answer) - 96 + offset - 26
+ end
+ end
+ local newdir = found[choice]
+ if newdir then
+ hash.history[pattern] = newdir
+ writeln(format("changing to %q",newdir))
+ fcd_changeto(newdir)
+ fcd_save()
+ return
+ end
+ else
+ -- try again
+ end
+ end
+end
+
+local function globdirs(path,dirs)
+ local dirs = dirs or { }
+ for name in lfs.dir(path) do
+ if not find(name,"%.$") then
+ local fullname = path .. "/" .. name
+ if lfs.isdir(fullname) and not find(fullname,"/%.") then
+ dirs[#dirs+1] = fullname
+ globdirs(fullname,dirs)
+ end
+ end
+ end
+ return dirs
+end
+
+local function fcd_scan()
+ if hash then
+ local paths = hash.paths
+ for i=1,#environment.files do
+ local name = environment.files[i]
+ local name = gsub(name,"\\","/")
+ local name = gsub(name,"/$","")
+ local list = globdirs(name)
+ local done = false
+ for i=1,#paths do
+ if paths[i][1] == name then
+ paths[i][2] = list
+ done = true
+ break
+ end
+ end
+ if not done then
+ paths[#paths+1] = { name, list }
+ end
+ end
+ end
+end
+
+local argument = environment.argument
+
+if argument("clear") then
+ if argument("history") then
+ fcd_load()
+ fcd_clear(true)
+ else
+ fcd_clear()
+ end
+ fcd_save()
+elseif argument("scan") then
+ fcd_clear()
+ fcd_scan()
+ fcd_save()
+elseif argument("add") then
+ fcd_load(true)
+ fcd_scan()
+ fcd_save()
+elseif argument("stub") then
+ writeln(stubdata)
+elseif argument("list") then
+ fcd_load()
+ if argument("history") then
+ fcd_list(true)
+ else
+ fcd_list()
+ end
+elseif argument("help") then
+ application.help()
+elseif argument("exporthelp") then
+ application.export(argument("exporthelp"),environment.files[1])
+else -- also argument("find")
+ fcd_load()
+ fcd_find()
+ fcd_choose(argument("nohistory"))
+end
+
diff --git a/Master/texmf-dist/scripts/context/lua/mtx-flac.lua b/Master/texmf-dist/scripts/context/lua/mtx-flac.lua
index 37f985654a3..2155b24becb 100644
--- a/Master/texmf-dist/scripts/context/lua/mtx-flac.lua
+++ b/Master/texmf-dist/scripts/context/lua/mtx-flac.lua
@@ -6,17 +6,15 @@ if not modules then modules = { } end modules ['mtx-flac'] = {
license = "see context related readme files"
}
--- Written with Within Temptation's "The Unforgiven" in loopmode on
--- the speakers. The following code is also used for my occasional music
--- repository cleanup session using the code below.
-
--- this can become l-flac.lua
-
local sub, match, byte, lower = string.sub, string.match, string.byte, string.lower
local readstring, readnumber = io.readstring, io.readnumber
-local concat = table.concat
+local concat, sortedpairs = table.concat, table.sortedpairs
local tonumber = tonumber
local tobitstring = number.tobitstring
+local lpegmatch = lpeg.match
+local p_escaped = lpeg.patterns.xml.escaped
+
+-- rather silly: pack info in bits while a flac file is large anyway
flac = flac or { }
@@ -25,7 +23,7 @@ flac.report = string.format
local splitter = lpeg.splitat("=")
local readers = { }
-readers[0] = function(f,size,target) -- not yet ok
+readers[0] = function(f,size,target) -- not yet ok .. todo: use bit32 lib
local info = { }
target.info = info
info.minimum_block_size = readnumber(f,-2)
@@ -78,6 +76,7 @@ function flac.getmetadata(filename)
local reader = readers[flag] or readers.default
reader(f,size,data,banner)
if last then
+ f:close()
return data
end
end
@@ -127,28 +126,29 @@ function flac.savecollection(pattern,filename)
local nofartists, nofalbums, noftracks, noferrors = 0, 0, 0, 0
local f = io.open(filename,"wb")
if f then
+ flac.report("saving data in file %q",filename)
f:write("\n\n")
f:write("\n")
- for artist, albums in table.sortedpairs(music) do
+ for artist, albums in sortedpairs(music) do
nofartists = nofartists + 1
f:write("\t\n")
- f:write("\t\t" .. artist .. " \n")
+ f:write("\t\t",lpegmatch(p_escaped,artist)," \n")
f:write("\t\t\n")
- for album, data in table.sortedpairs(albums) do
+ for album, data in sortedpairs(albums) do
nofalbums = nofalbums + 1
- f:write("\t\t\t\n")
- f:write("\t\t\t\t" .. album .. " \n")
+ f:write("\t\t\t\n")
+ f:write("\t\t\t\t",lpegmatch(p_escaped,album)," \n")
f:write("\t\t\t\t\n")
local tracks = data.tracks
for i=1,#tracks do
local track = tracks[i]
if track then
noftracks = noftracks + 1
- f:write("\t\t\t\t\t" .. track.title .. " \n")
+ f:write("\t\t\t\t\t",lpegmatch(p_escaped,track.title)," \n")
else
noferrors = noferrors + 1
- flac.report("error in album: %q of artist",album,artist)
- f:write("\t\t\t\t\t \n")
+ flac.report("error in album: %q of %q, no track %s",album,artist,i)
+ f:write("\t\t\t\t\t \n")
end
end
f:write("\t\t\t\t \n")
@@ -158,20 +158,40 @@ function flac.savecollection(pattern,filename)
f:write("\t \n")
end
f:write(" \n")
+ f:close()
+ flac.report("%s tracks of %s albums of %s artists saved in %q (%s errors)",noftracks,nofalbums,nofartists,filename,noferrors)
+ else
+ flac.report("unable to save data in file %q",filename)
end
- f:close()
- flac.report("%s tracks of %s albums of %s artists saved in %q (%s errors)",noftracks,nofalbums,nofartists,filename,noferrors)
end
--
local helpinfo = [[
---collect collect albums in xml file
-
-example:
-
-mtxrun --script flac --collect somename.flac
-mtxrun --script flac --collect --pattern="m:/music/**")
+
+
+
+ mtx-flac
+ ConTeXt Flac Helpers
+ 0.10
+
+
+
+
+ collect albums in xml file
+
+
+
+
+
+ Example
+
+ mtxrun --script flac --collect somename.flac
+ mtxrun --script flac --collect --pattern="m:/music/**")
+
+
+
+
]]
local application = logs.application {
@@ -211,6 +231,8 @@ end
if environment.argument("collect") then
scripts.flac.collect()
+elseif environment.argument("exporthelp") then
+ application.export(environment.argument("exporthelp"),environment.files[1])
else
application.help()
end
diff --git a/Master/texmf-dist/scripts/context/lua/mtx-fonts.lua b/Master/texmf-dist/scripts/context/lua/mtx-fonts.lua
index c5b458c1422..d427f8b2fc3 100644
--- a/Master/texmf-dist/scripts/context/lua/mtx-fonts.lua
+++ b/Master/texmf-dist/scripts/context/lua/mtx-fonts.lua
@@ -6,40 +6,70 @@ if not modules then modules = { } end modules ['mtx-fonts'] = {
license = "see context related readme files"
}
-local helpinfo = [[
---save save open type font in raw table
---unpack save a tma file in a more readale format
-
---reload generate new font database
---reload --simple generate 'luatex-fonts-names.lua' (not for context!)
-
---list --name list installed fonts, filter by name [--pattern]
---list --spec list installed fonts, filter by spec [--filter]
---list --file list installed fonts, filter by file [--pattern]
-
---pattern=str filter files using pattern
---filter=list key-value pairs
---all show all found instances
---info give more details
---track=list enable trackers
---statistics some info about the database
-
-examples of searches:
+local getargument = environment.getargument
+local setargument = environment.setargument
+local givenfiles = environment.files
-mtxrun --script font --list somename (== --pattern=*somename*)
-
-mtxrun --script font --list --name somename
-mtxrun --script font --list --name --pattern=*somename*
-
-mtxrun --script font --list --spec somename
-mtxrun --script font --list --spec somename-bold-italic
-mtxrun --script font --list --spec --pattern=*somename*
-mtxrun --script font --list --spec --filter="fontname=somename"
-mtxrun --script font --list --spec --filter="familyname=somename,weight=bold,style=italic,width=condensed"
-mtxrun --script font --list --spec --filter="familyname=crap*,weight=bold,style=italic"
-
-mtxrun --script font --list --file somename
-mtxrun --script font --list --file --pattern=*somename*
+local helpinfo = [[
+
+
+
+ mtx-fonts
+ ConTeXt Font Database Management
+ 0.21
+
+
+
+
+ save open type font in raw table
+ save a tma file in a more readale format
+
+
+ generate new font database (use when in doubt)
+ :generate luatex-fonts-names.lua (not for context!)
+
+
+ : list installed fonts, filter by name []
+ : list installed fonts, filter by spec []
+ : list installed fonts, filter by file []
+
+
+ filter files using pattern
+ key-value pairs
+ show all found instances (combined with other flags)
+ give more details
+ enable trackers
+ some info about the database
+
+
+
+
+
+ Examples
+
+ mtxrun --script font --list somename (== --pattern=*somename*)
+
+
+ mtxrun --script font --list --name somename
+ mtxrun --script font --list --name --pattern=*somename*
+
+
+ mtxrun --script font --list --spec somename
+ mtxrun --script font --list --spec somename-bold-italic
+ mtxrun --script font --list --spec --pattern=*somename*
+ mtxrun --script font --list --spec --filter="fontname=somename"
+ mtxrun --script font --list --spec --filter="familyname=somename,weight=bold,style=italic,width=condensed"
+ mtxrun --script font --list --spec --filter="familyname=crap*,weight=bold,style=italic"
+
+
+ mtxrun --script font --list --all
+ mtxrun --script font --list --file somename
+ mtxrun --script font --list --file --all somename
+ mtxrun --script font --list --file --pattern=*somename*
+
+
+
+
]]
local application = logs.application {
@@ -126,7 +156,7 @@ function fonts.names.simple()
end
report("saving names in '%s'",name)
io.savedata(name,table.serialize(simplified,true))
- local data = io.loaddata(resolvers.findfile("font-dum.lua","tex"))
+ local data = io.loaddata(resolvers.findfile("luatex-fonts-syn.lua","tex")) or ""
local dummy = string.match(data,"fonts%.names%.version%s*=%s*([%d%.]+)")
if tonumber(dummy) ~= simpleversion then
report("warning: version number %s in 'font-dum' does not match database version number %s",dummy or "?",simpleversion)
@@ -137,10 +167,10 @@ function fonts.names.simple()
end
function scripts.fonts.reload()
- if environment.argument("simple") then
+ if getargument("simple") then
fonts.names.simple()
else
- fonts.names.load(true)
+ fonts.names.load(true,getargument("force"))
end
end
@@ -208,7 +238,7 @@ end
local function reloadbase(reload)
if reload then
report("fontnames, reloading font database")
- names.load(true)
+ names.load(true,getargument("force"))
report("fontnames, done\n\n")
end
end
@@ -274,16 +304,16 @@ end
function scripts.fonts.list()
- local all = environment.argument("all")
- local info = environment.argument("info")
- local reload = environment.argument("reload")
- local pattern = environment.argument("pattern")
- local filter = environment.argument("filter")
- local given = environment.files[1]
+ local all = getargument("all")
+ local info = getargument("info")
+ local reload = getargument("reload")
+ local pattern = getargument("pattern")
+ local filter = getargument("filter")
+ local given = givenfiles[1]
reloadbase(reload)
- if environment.argument("name") then
+ if getargument("name") then
if pattern then
--~ mtxrun --script font --list --name --pattern=*somename*
list_matches(fonts.names.list(string.topattern(pattern,true),reload,all),info)
@@ -295,7 +325,7 @@ function scripts.fonts.list()
else
report("not supported: --list --name ",name)
end
- elseif environment.argument("spec") then
+ elseif getargument("spec") then
if pattern then
--~ mtxrun --script font --list --spec --pattern=*somename*
report("not supported: --list --spec --pattern",name)
@@ -308,7 +338,7 @@ function scripts.fonts.list()
else
report("not supported: --list --spec ",name)
end
- elseif environment.argument("file") then
+ elseif getargument("file") then
if pattern then
--~ mtxrun --script font --list --file --pattern=*somename*
list_specifications(fonts.names.collectfiles(string.topattern(pattern,true),reload,all),info)
@@ -336,7 +366,7 @@ function scripts.fonts.list()
end
function scripts.fonts.unpack()
- local name = file.removesuffix(file.basename(environment.files[1] or ""))
+ local name = file.removesuffix(file.basename(givenfiles[1] or ""))
if name and name ~= "" then
local cache = containers.define("fonts", "otf", 2.730, true)
local cleanname = containers.cleanname(name)
@@ -353,8 +383,8 @@ function scripts.fonts.unpack()
end
function scripts.fonts.save()
- local name = environment.files[1] or ""
- local sub = environment.files[2] or ""
+ local name = givenfiles[1] or ""
+ local sub = givenfiles[2] or ""
local function save(savename,fontblob)
if fontblob then
savename = savename:lower() .. ".lua"
@@ -367,7 +397,7 @@ function scripts.fonts.save()
if name and name ~= "" then
local filename = resolvers.findfile(name) -- maybe also search for opentype
if filename and filename ~= "" then
- local suffix = string.lower(file.extname(filename))
+ local suffix = string.lower(file.suffix(filename))
if suffix == 'ttf' or suffix == 'otf' or suffix == 'ttc' or suffix == "dfont" then
local fontinfo = fontloader.info(filename)
if fontinfo then
@@ -394,21 +424,23 @@ function scripts.fonts.save()
end
end
-if environment.argument("names") then
- environment.setargument("reload",true)
- environment.setargument("simple",true)
+if getargument("names") then
+ setargument("reload",true)
+ setargument("simple",true)
end
-if environment.argument("list") then
+if getargument("list") then
scripts.fonts.list()
-elseif environment.argument("reload") then
+elseif getargument("reload") then
scripts.fonts.reload()
-elseif environment.argument("save") then
+elseif getargument("save") then
scripts.fonts.save()
-elseif environment.argument("unpack") then
+elseif getargument("unpack") then
scripts.fonts.unpack()
-elseif environment.argument("statistics") then
+elseif getargument("statistics") then
fonts.names.statistics()
+elseif getargument("exporthelp") then
+ application.export(getargument("exporthelp"),givenfiles[1])
else
application.help()
end
diff --git a/Master/texmf-dist/scripts/context/lua/mtx-grep.lua b/Master/texmf-dist/scripts/context/lua/mtx-grep.lua
index 3cbc1421ad2..dbcce67f6a2 100644
--- a/Master/texmf-dist/scripts/context/lua/mtx-grep.lua
+++ b/Master/texmf-dist/scripts/context/lua/mtx-grep.lua
@@ -7,12 +7,27 @@ if not modules then modules = { } end modules ['mtx-babel'] = {
}
local helpinfo = [[
---pattern search for pattern (optional)
---count count matches only
---nocomment skip lines that start with %% or #
---xml pattern is lpath expression
-
-patterns are lua patterns and need to be escaped accordingly
+
+
+
+ mtx-grep
+ Simple Grepper
+ 0.10
+
+
+
+
+ search for pattern (optional)
+ count matches only
+ skip lines that start with %% or #
+ pattern is lpath expression
+
+
+
+
+ patterns are lua patterns and need to be escaped accordingly
+
+
]]
local application = logs.application {
@@ -60,7 +75,7 @@ function scripts.grep.find(pattern, files, offset)
if m > 0 then
nofmatches = nofmatches + m
nofmatchedfiles = nofmatchedfiles + 1
- write_nl(format("%s: %s",name,m))
+ write_nl(format("%5i %s",m,name))
io.flush()
end
else
@@ -127,7 +142,7 @@ function scripts.grep.find(pattern, files, offset)
if count and m > 0 then
nofmatches = nofmatches + m
nofmatchedfiles = nofmatchedfiles + 1
- write_nl(format("%s: %s",name,m))
+ write_nl(format("%5i %s",m,name))
io.flush()
end
end
@@ -144,7 +159,9 @@ end
local pattern = environment.argument("pattern")
local files = environment.files and #environment.files > 0 and environment.files
-if pattern and files then
+if environment.argument("exporthelp") then
+ application.export(environment.argument("exporthelp"),files[1])
+elseif pattern and files then
scripts.grep.find(pattern, files)
elseif files then
scripts.grep.find(files[1], files, 2)
diff --git a/Master/texmf-dist/scripts/context/lua/mtx-interface.lua b/Master/texmf-dist/scripts/context/lua/mtx-interface.lua
index f52fde345d5..82cefd63817 100644
--- a/Master/texmf-dist/scripts/context/lua/mtx-interface.lua
+++ b/Master/texmf-dist/scripts/context/lua/mtx-interface.lua
@@ -11,25 +11,43 @@ local gsub, format, gmatch, find = string.gsub, string.format, string.gmatch, st
local utfchar, utfgsub = utf.char, utf.gsub
local helpinfo = [[
---interfaces generate context interface files
---messages generate context message files
---labels generate context label files
-
---context equals --interfaces --messages --languages
-
---scite generate scite interface
---bbedit generate bbedit interface files
---jedit generate jedit interface files
---textpad generate textpad interface files
---text create text files for commands and environments
---raw report commands to the console
---check generate check file
-
---toutf replace named characters by utf
---preprocess preprocess mkvi files to tex files [force,suffix]
-
---suffix use given suffix for output files
---force force action even when in doubt
+
+
+
+ mtx-interface
+ ConTeXt Interface Related Goodies
+ 0.13
+
+
+
+
+ generate context interface files
+ generate context message files
+ generate context label files
+
+
+ equals
+
+
+ generate scite interface
+ generate bbedit interface files
+ generate jedit interface files
+ generate textpad interface files
+ create text files for commands and environments
+ report commands to the console
+ generate check file
+
+
+ replace named characters by utf
+ preprocess mkvi files to tex files [force,suffix]
+
+
+ use given suffix for output files
+ force action even when in doubt
+
+
+
+
]]
local application = logs.application {
@@ -50,7 +68,7 @@ local messageinterfaces = { 'en','cs','de','it','nl','ro','fr','pe','no' }
local function collect(filename,class,data)
if data then
local result = { }
- for name, list in next, data do
+ for name, list in table.sortedhash(data) do
result[#result+1] = format("keywordclass.%s.%s=\\\n",class,name)
for i=1,#list do
if i%5 == 0 then
@@ -596,6 +614,8 @@ elseif ea("scite") or ea("bbedit") or ea("jedit") or ea("textpad") or ea("text")
if ea("raw") then
scripts.interface.editor("raw")
end
+elseif ea("exporthelp") then
+ application.export(ea("exporthelp"),environment.files[1])
else
application.help()
end
diff --git a/Master/texmf-dist/scripts/context/lua/mtx-metapost.lua b/Master/texmf-dist/scripts/context/lua/mtx-metapost.lua
index 3b9ed6ff17e..08daec978dc 100644
--- a/Master/texmf-dist/scripts/context/lua/mtx-metapost.lua
+++ b/Master/texmf-dist/scripts/context/lua/mtx-metapost.lua
@@ -7,19 +7,38 @@ if not modules then modules = { } end modules ['mtx-metapost'] = { -- this was m
}
local helpinfo = [[
---rawmp raw metapost run
---metafun use metafun instead of plain
---latex force --tex=latex
---texexec force texexec usage (mkii)
---split split single result file into pages
-
-intended usage:
-
-mtxrun --script metapost yourfile.mp
-mtxrun --script metapost --split yourfile.mp
-mtxrun --script metapost yourfile.123 myfile.mps
-
-other usage resembles mptopdf.pl
+
+
+
+ mtx-metapost
+ MetaPost to PDF processor
+ 0.10
+
+
+
+
+ raw metapost run
+ use metafun instead of plain
+ force
+ force texexec usage (mkii)
+ split single result file into pages
+
+
+
+
+
+ Examples
+
+ mtxrun --script metapost yourfile.mp
+ mtxrun --script metapost --split yourfile.mp
+ mtxrun --script metapost yourfile.123 myfile.mps
+
+
+
+
+ other usage resembles mptopdf.pl
+
+
]]
local application = logs.application {
@@ -49,7 +68,7 @@ local tempname = "mptopdf-temp.tex"
local function do_convert(filename)
if find(filename,".%d+$") or find(filename,"%.mps$") then
io.savedata(tempname,format(template,filename))
- local resultname = format("%s-%s.pdf",file.nameonly(filename),file.extname(filename))
+ local resultname = format("%s-%s.pdf",file.nameonly(filename),file.suffix(filename))
local result = os.execute(format([[context --once --batch --purge --result=%s "%s"]],resultname,tempname))
return lfs.isfile(resultname) and resultname
end
@@ -166,10 +185,12 @@ function scripts.mptopdf.convertall()
end
end
-if environment.files[1] then
+if environment.argument("exporthelp") then
+ application.export(environment.argument("exporthelp"),environment.files[1])
+elseif environment.files[1] then
scripts.mptopdf.convertall()
else
- if not environment.arguments.help then
+ if not environment.argument("help") then
report("provide MP output file (or pattern)")
report()
end
diff --git a/Master/texmf-dist/scripts/context/lua/mtx-metatex.lua b/Master/texmf-dist/scripts/context/lua/mtx-metatex.lua
index 0b66d59ef3a..455ecbd5281 100644
--- a/Master/texmf-dist/scripts/context/lua/mtx-metatex.lua
+++ b/Master/texmf-dist/scripts/context/lua/mtx-metatex.lua
@@ -9,8 +9,22 @@ if not modules then modules = { } end modules ['mtx-metatex'] = {
-- future versions will deal with specific variants of metatex
local helpinfo = [[
---run process (one or more) files (default action)
---make create metatex format(s)
+
+
+
+ mtx-metatex
+ MetaTeX Process Management
+ 0.10
+
+
+
+
+ process (one or more) files (default action)
+ create metatex format(s)
+
+
+
+
]]
local application = logs.application {
@@ -57,6 +71,8 @@ elseif environment.argument("make") then
scripts.metatex.timed(scripts.metatex.make)
elseif environment.argument("help") then
logs.help(messages.help,false)
+elseif environment.argument("exporthelp") then
+ application.export(environment.argument("exporthelp"),environment.files[1])
elseif environment.files[1] then
scripts.metatex.timed(scripts.metatex.run)
else
diff --git a/Master/texmf-dist/scripts/context/lua/mtx-mk-help.lua b/Master/texmf-dist/scripts/context/lua/mtx-mk-help.lua
new file mode 100644
index 00000000000..794bbca3799
--- /dev/null
+++ b/Master/texmf-dist/scripts/context/lua/mtx-mk-help.lua
@@ -0,0 +1,473 @@
+if not modules then modules = { } end modules ['mtx-mk-help'] = {
+ version = 1.001,
+ comment = "a script for making help files",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+--[[
+
+mtxrun --exporthelp=all %targetpath%\mkiv\mtxrun.tmp
+context --exporthelp=all %targetpath%\mkiv\context.tmp
+mtxrun --script context --exporthelp=all %targetpath%\mkiv\mtx-context.tmp
+
+mtxrun --script babel --exporthelp=all %targetpath%\mkiv\mtx-babel.tmp
+mtxrun --script base --exporthelp=all %targetpath%\mkiv\mtx-base.tmp
+mtxrun --script cache --exporthelp=all %targetpath%\mkiv\mtx-cache.tmp
+mtxrun --script chars --exporthelp=all %targetpath%\mkiv\mtx-chars.tmp
+mtxrun --script check --exporthelp=all %targetpath%\mkiv\mtx-check.tmp
+mtxrun --script colors --exporthelp=all %targetpath%\mkiv\mtx-colors.tmp
+mtxrun --script convert --exporthelp=all %targetpath%\mkiv\mtx-convert.tmp
+mtxrun --script epub --exporthelp=all %targetpath%\mkiv\mtx-epub.tmp
+mtxrun --script fcd --exporthelp=all %targetpath%\mkiv\mtx-fcd.tmp
+mtxrun --script flac --exporthelp=all %targetpath%\mkiv\mtx-flac.tmp
+mtxrun --script fonts --exporthelp=all %targetpath%\mkiv\mtx-fonts.tmp
+mtxrun --script grep --exporthelp=all %targetpath%\mkiv\mtx-grep.tmp
+mtxrun --script interface --exporthelp=all %targetpath%\mkiv\mtx-interface.tmp
+mtxrun --script metapost --exporthelp=all %targetpath%\mkiv\mtx-metapost.tmp
+mtxrun --script metatex --exporthelp=all %targetpath%\mkiv\mtx-metatex.tmp
+mtxrun --script modules --exporthelp=all %targetpath%\mkiv\mtx-modules.tmp
+mtxrun --script mtxworks --exporthelp=all %targetpath%\mkiv\mtx-mtxworks.tmp
+mtxrun --script package --exporthelp=all %targetpath%\mkiv\mtx-package.tmp
+mtxrun --script patterns --exporthelp=all %targetpath%\mkiv\mtx-patterns.tmp
+mtxrun --script pdf --exporthelp=all %targetpath%\mkiv\mtx-pdf.tmp
+mtxrun --script profile --exporthelp=all %targetpath%\mkiv\mtx-profile.tmp
+mtxrun --script rsync --exporthelp=all %targetpath%\mkiv\mtx-rsync.tmp
+mtxrun --script scite --exporthelp=all %targetpath%\mkiv\mtx-scite.tmp
+mtxrun --script server --exporthelp=all %targetpath%\mkiv\mtx-server.tmp
+mtxrun --script texworks --exporthelp=all %targetpath%\mkiv\mtx-texworks.tmp
+mtxrun --script timing --exporthelp=all %targetpath%\mkiv\mtx-timing.tmp
+mtxrun --script tools --exporthelp=all %targetpath%\mkiv\mtx-tools.tmp
+mtxrun --script unzip --exporthelp=all %targetpath%\mkiv\mtx-unzip.tmp
+mtxrun --script update --exporthelp=all %targetpath%\mkiv\mtx-update.tmp
+mtxrun --script watch --exporthelp=all %targetpath%\mkiv\mtx-watch.tmp
+
+mtxrun --script mk-help luatools --exporthelp=all %targetpath%\mkiv\luatools.tmp
+
+mtxrun --script mk-help texmfstart --exporthelp=all %targetpath%\mkii\texmfstart.tmp
+mtxrun --script mk-help texexec --exporthelp=all %targetpath%\mkii\texexec.tmp
+mtxrun --script mk-help texutil --exporthelp=all %targetpath%\mkii\texutil.tmp
+mtxrun --script mk-help ctxtools --exporthelp=all %targetpath%\mkii\ctxtools.tmp
+mtxrun --script mk-help textools --exporthelp=all %targetpath%\mkii\textools.tmp
+mtxrun --script mk-help pdftools --exporthelp=all %targetpath%\mkii\pdftools.tmp
+mtxrun --script mk-help tmftools --exporthelp=all %targetpath%\mkii\tmftools.tmp
+mtxrun --script mk-help xmltools --exporthelp=all %targetpath%\mkii\xmltools.tmp
+mtxrun --script mk-help pstopdf --exporthelp=all %targetpath%\mkii\pstopdf.tmp
+mtxrun --script mk-help rlxtools --exporthelp=all %targetpath%\mkii\rlxtools.tmp
+mtxrun --script mk-help imgtopdf --exporthelp=all %targetpath%\mkii\imgtopdf.tmp
+
+]]--
+
+local helpinfo = os.resultof("mtxrun --exporthelp") or ""
+local helpinfo = string.match(helpinfo,[[^.-(.- )]]) or [[ ]]
+
+local texmfstart = logs.application {
+ name = "texmfstart",
+ banner = "texmfstart 7.0.0",
+ helpinfo = [[]] .. helpinfo,
+}
+
+-- let's also put luatools here:
+
+local helpinfo = os.resultof("luatools --exporthelp") or ""
+local helpinfo = string.match(helpinfo,[[^.-(.- )]]) or [[ ]]
+local helpinfo = string.gsub(helpinfo,"mtx%-base","luatools")
+
+local luatools = logs.application {
+ name = "luatools",
+ banner = "luatools 1.35",
+ helpinfo = [[]] .. helpinfo,
+}
+
+--
+
+local helpinfo = [[
+
+
+
+ texexec
+ TeXExec
+ 6.2.1
+
+
+
+
+ make formats
+ check versions
+ process file
+ process mp file
+ process mpx file
+ process mp file to stand-alone graphics
+ process mp/ctx file to stand-alone graphics
+ list of file content
+ generate overview of figures
+ generate module documentation
+ impose pages (booklets)
+ select pages from file(s)
+ copy pages from file(s)
+ trim pages from file(s)
+ combine multiple pages
+ split file in pages
+
+
+
+
+]]
+
+local texexec = logs.application {
+ name = "texexec",
+ banner = "TeXExec 6.2.1",
+ helpinfo = helpinfo,
+}
+
+local helpinfo = [[
+
+
+
+ texutil
+ TeXUtil
+ 9.1.0
+
+
+
+
+ convert tui file into tuo file
+ generate figure dimensions file
+ filter essential log messages
+ remove most temporary files
+ remove all temporary files
+ generate documentation file from source
+ analyze pdf file
+
+
+
+ ]]
+
+local texutil = logs.application {
+ name = "texutil",
+ banner = "TeXUtil 9.1.0",
+ helpinfo = helpinfo,
+}
+
+local helpinfo = [[
+
+
+
+ ctxtools
+ CtxTools
+ 1.3.5
+
+
+
+
+ update context version
+ report context version
+ generate jedit syntax files [
+ generate bbedit syntax files [
+ generate scite syntax files [
+ generate raw syntax files [
+ generate interface files (xml) [nl de ..]
+ remove temporary files [ [basename]
+ [filename]
+ ) # no help, hidden temporary feature
+ convert pdftex mapfiles to dvipdfmx [ [texmfroot]
+ create doctype entity definition from enco-uc.tex
+ add context copyright notice [
+ replace line-endings [ [pattern]
+ [filename]
+ download latest version and remake formats [
+ remove utf bom [
+
+
+
+
+]]
+
+local ctxtools = logs.application {
+ name = "ctxtools",
+ banner = "CtxTools 1.3.5",
+ helpinfo = helpinfo,
+}
+
+local helpinfo = [[
+
+
+
+ textools
+ TeXTools
+ 1.3.1
+
+
+
+
+ [pattern] [
+ [pattern] [
+ [pattern] [
+ [pattern] [
+ filename [
+ [pattern] [
+ [pattern] [
+ [pattern] [
+ [texmfroot] [
+ filename [
+ fromroot toroot [
+ [ [
+ [ [
+ filename
+ afmfile encodingname
+ tpm file (run in texmf root)
+
+
+
+
+]]
+
+local textools = logs.application {
+ name = "textools",
+ banner = "TeXTools 1.3.1",
+ helpinfo = helpinfo,
+}
+
+local helpinfo = [[
+
+
+
+ pdftools
+ PDFTools
+ 1.2.1
+
+
+
+
+ [
+ [ ]
+ filename [
+ filename [
+ filename
+ [
+ [
+ filename
+
+
+
+
+]]
+
+local pdftools = logs.application {
+ name = "pdftools",
+ banner = "PDFTools 1.2.1",
+ helpinfo = helpinfo,
+}
+
+local helpinfo = [[
+
+
+
+ tmftools
+ TMFTools
+ 1.1.0
+
+
+
+
+ [ ] [pattern]
+
+
+ act as kpse server
+
+
+
+
+]]
+
+local tmftools = logs.application {
+ name = "tmftools",
+ banner = "TMFTools 1.2.1",
+ helpinfo = helpinfo,
+}
+
+local helpinfo = [[
+
+
+
+ xmltools
+ XMLTools
+ 1.2.2
+
+
+
+
+ generate directory listing
+ generate graphic from mathml
+ report entities and elements [ ]
+ cleanup xml file []
+ enhance xml file (partial)
+ filter elements from xml file []
+ generate ddirectory listing
+
+
+
+
+]]
+
+local xmltools = logs.application {
+ name = "xmltools",
+ banner = "XMLTools 1.2.1",
+ helpinfo = helpinfo,
+}
+
+local helpinfo = [[
+
+
+
+ pstopdf
+ PStoPDF
+ 2.0.1
+
+
+
+
+ handles exa request file
+ watch folders for conversions (untested)
+
+
+
+
+]]
+
+local pstopdf = logs.application {
+ name = "pstopdf",
+ banner = "PStoPDF 2.0.1",
+ helpinfo = helpinfo,
+}
+
+local helpinfo = [[
+
+
+
+ rlxtools
+ RlxTools
+ 1.0.1
+
+
+
+
+ [ manipulatorfile resourselog
+ [ filename
+
+
+
+
+]]
+
+local rlxtools = logs.application {
+ name = "rlxtools",
+ banner = "RlxTools 1.0.1",
+ helpinfo = helpinfo,
+}
+
+local helpinfo = [[
+
+
+
+ imgtopdf
+ ImgToPdf
+ 1.1.2
+
+
+
+
+ convert image into pdf
+ level of compression in percent
+ image depth in bits
+ colorspace (rgb,cmyk,gray)
+ quality in percent
+ path where files are looked for
+ path where files end up
+ determine settings automatically
+
+
+
+
+]]
+
+local imgtopdf = logs.application {
+ name = "imgtopdf",
+ banner = "ImgToPdf 1.1.2",
+ helpinfo = helpinfo,
+}
+
+local helpinfo = [[
+
+
+
+ mptopdf
+ convert MetaPost to PDF
+ 1.4.1
+
+
+
+
+ use the metafun format to process the file (default is mpost)
+ use texexec (context) to process text snippets
+ use latex to process text snippets
+
+
+
+
+]]
+
+local mptopdf = logs.application {
+ name = "mptopdf",
+ banner = "MPtoPDF 1.4.1",
+ helpinfo = helpinfo,
+}
+
+-- texmfstart.rb is normally replaced by mtxrun
+-- runtools.rb is run from within context
+-- concheck.rb is run from within editors
+-- texsync.rb is no longer in the zip
+-- mpstools.rb is no longer in the zip
+-- rscortool.rb is only run indirectly
+-- rsfiltool.rb is only run indirectly
+-- rslibtool.rb is only run indirectly
+
+local application = logs.application {
+ name = "mk-help",
+ banner = "Mk Help generator 1.00",
+}
+
+local filename = environment.files[1]
+
+if not filename then
+ application.report("no mk script given")
+ return
+end
+
+local mkapplication
+
+if filename == "texmfstart" then mkapplication = texmfstart
+elseif filename == "luatools" then mkapplication = luatools
+elseif filename == "texexec" then mkapplication = texexec
+elseif filename == "texutil" then mkapplication = texutil
+elseif filename == "ctxtools" then mkapplication = ctxtools
+elseif filename == "textools" then mkapplication = textools
+elseif filename == "pdftools" then mkapplication = pdftools
+elseif filename == "tmftools" then mkapplication = tmftools
+elseif filename == "xmltools" then mkapplication = xmltools
+elseif filename == "pstopdf" then mkapplication = pstopdf
+elseif filename == "rlxtools" then mkapplication = rlxtools
+elseif filename == "imgtopdf" then mkapplication = imgtopdf
+elseif filename == "mptopdf" then mkapplication = mptopdf end
+
+if not mkapplication then
+ application.report("no valid mk script given")
+ return
+end
+
+if environment.argument("exporthelp") then
+ mkapplication.export(environment.argument("exporthelp"),environment.files[2])
+else
+ mkapplication.help()
+end
diff --git a/Master/texmf-dist/scripts/context/lua/mtx-modules.lua b/Master/texmf-dist/scripts/context/lua/mtx-modules.lua
index 902b12ac303..ef38a715673 100644
--- a/Master/texmf-dist/scripts/context/lua/mtx-modules.lua
+++ b/Master/texmf-dist/scripts/context/lua/mtx-modules.lua
@@ -10,9 +10,23 @@ scripts = scripts or { }
scripts.modules = scripts.modules or { }
local helpinfo = [[
---convert convert source files (tex, mkii, mkiv, mp) to 'ted' files
---process process source files (tex, mkii, mkiv, mp) to 'pdf' files
---prep use original name with suffix 'prep' appended
+
+
+
+ mtx-modules
+ ConTeXt Module Documentation Generators
+ 1.00
+
+
+
+
+ convert source files (tex, mkii, mkiv, mp) to 'ted' files
+ process source files (tex, mkii, mkiv, mp) to 'pdf' files
+ use original name with suffix 'prep' appended
+
+
+
+
]]
local application = logs.application {
@@ -181,6 +195,8 @@ if environment.argument("process") then
scripts.modules.process(true)
elseif environment.argument("convert") then
scripts.modules.process(false)
+elseif environment.argument("exporthelp") then
+ application.export(environment.argument("exporthelp"),environment.files[1])
else
application.help()
end
diff --git a/Master/texmf-dist/scripts/context/lua/mtx-package.lua b/Master/texmf-dist/scripts/context/lua/mtx-package.lua
index 294ef4f285a..8c9e6b9fc85 100644
--- a/Master/texmf-dist/scripts/context/lua/mtx-package.lua
+++ b/Master/texmf-dist/scripts/context/lua/mtx-package.lua
@@ -9,7 +9,21 @@ if not modules then modules = { } end modules ['mtx-package'] = {
local format, gsub, gmatch = string.format, string.gsub, string.gmatch
local helpinfo = [[
---merge merge 'loadmodule' into merge file
+
+
+
+ mtx-package
+ Distribution Related Goodies
+ 0.10
+
+
+
+
+ merge 'loadmodule' into merge file
+
+
+
+
]]
local application = logs.application {
@@ -24,18 +38,18 @@ scripts = scripts or { }
messages = messages or { }
scripts.package = scripts.package or { }
-function scripts.package.merge_luatex_files(name,strip)
+function scripts.package.merge_luatex_files(name)
local oldname = resolvers.findfile(name) or ""
oldname = file.replacesuffix(oldname,"lua")
if oldname == "" then
- report("missing '%s'",name)
+ report("missing %q",name)
else
local newname = file.removesuffix(oldname) .. "-merged.lua"
local data = io.loaddata(oldname) or ""
if data == "" then
- report("missing '%s'",newname)
+ report("missing %q",newname)
else
- report("loading '%s'",oldname)
+ report("loading %q",oldname)
local collected = { }
collected[#collected+1] = format("-- merged file : %s\n",newname)
collected[#collected+1] = format("-- parent file : %s\n",oldname)
@@ -45,23 +59,17 @@ function scripts.package.merge_luatex_files(name,strip)
if file.basename(lib) ~= file.basename(newname) then
local fullname = resolvers.findfile(lib) or ""
if fullname == "" then
- report("missing '%s'",lib)
+ report("missing %q",lib)
else
- report("fetching '%s'",fullname)
+ report("fetching %q",fullname)
local data = io.loaddata(fullname)
- if strip then
- data = gsub(data,"%-%-%[%[ldx%-%-.-%-%-%ldx%]%]%-%-[\n\r]*","")
- data = gsub(data,"%-%-%~[^\n\r]*[\n\r]*","\n")
- data = gsub(data,"%s+%-%-[^\n\r]*[\n\r]*","\n")
- data = gsub(data,"[\n\r]+","\n")
- end
collected[#collected+1] = "\ndo -- begin closure to overcome local limits and interference\n\n"
- collected[#collected+1] = data
+ collected[#collected+1] = utilities.merger.compact(data)
collected[#collected+1] = "\nend -- closure\n"
end
end
end
- report("saving '%s'",newname)
+ report("saving %q",newname)
io.savedata(newname,table.concat(collected))
end
end
@@ -69,6 +77,8 @@ end
if environment.argument("merge") then
scripts.package.merge_luatex_files(environment.files[1] or "")
+elseif environment.argument("exporthelp") then
+ application.export(environment.argument("exporthelp"),environment.files[1])
else
application.help()
end
diff --git a/Master/texmf-dist/scripts/context/lua/mtx-patterns.lua b/Master/texmf-dist/scripts/context/lua/mtx-patterns.lua
index fbcb251b1f2..7144da9b090 100644
--- a/Master/texmf-dist/scripts/context/lua/mtx-patterns.lua
+++ b/Master/texmf-dist/scripts/context/lua/mtx-patterns.lua
@@ -12,17 +12,36 @@ local addsuffix = file.addsuffix
local lpegmatch, validutf8 = lpeg.match, lpeg.patterns.validutf8
local helpinfo = [[
---convert generate context language files (mnemonic driven, if not given then all)
---check check pattern file (or those used by context when no file given)
---path source path where hyph-foo.tex files are stored
---destination destination path
-
-examples of usage:
-
-mtxrun --script pattern --check hyph-*.tex
-mtxrun --script pattern --check --path=c:/data/develop/svn-hyphen/trunk/hyph-utf8/tex/generic/hyph-utf8/patterns
-mtxrun --script pattern --convert --path=c:/data/develop/svn-hyphen/trunk/hyph-utf8/tex/generic/hyph-utf8/patterns/tex --destination=e:/tmp/patterns
-mtxrun --script pattern --convert --path=c:/data/develop/svn-hyphen/trunk/hyph-utf8/tex/generic/hyph-utf8/patterns/txt --destination=e:/tmp/patterns
+
+
+
+ mtx-patterns
+ ConTeXt Pattern File Management
+ 0.20
+
+
+
+
+ generate context language files (mnemonic driven, if not given then all)
+ check pattern file (or those used by context when no file given)
+ source path where hyph-foo.tex files are stored
+ destination path
+ additional patterns: e.g.: =cy,hyph-cy,welsh
+
+
+
+
+
+ Examples
+
+ mtxrun --script pattern --check hyph-*.tex
+ mtxrun --script pattern --check --path=c:/data/develop/svn-hyphen/trunk/hyph-utf8/tex/generic/hyph-utf8/patterns
+ mtxrun --script pattern --convert --path=c:/data/develop/svn-hyphen/trunk/hyph-utf8/tex/generic/hyph-utf8/patterns/tex --destination=e:/tmp/patterns
+ mtxrun --script pattern --convert --path=c:/data/develop/svn-hyphen/trunk/hyph-utf8/tex/generic/hyph-utf8/patterns/txt --destination=e:/tmp/patterns
+
+
+
+
]]
local application = logs.application {
@@ -454,7 +473,19 @@ function scripts.patterns.save(destination,mnemonic,name,patternsnew,hyphenation
end
function scripts.patterns.prepare()
+ --
dofile(resolvers.findfile("char-def.lua"))
+ --
+ local specification = environment.argument("specification")
+ if specification then
+ local components = utilities.parsers.settings_to_array(specification)
+ if #components == 3 then
+ table.insert(scripts.patterns.list,1,components)
+ report("specification added: %s %s %s",table.unpack(components))
+ else
+ report('invalid specification: %q, "xx,lang-yy,zzzz" expected',specification)
+ end
+ end
end
function scripts.patterns.check()
@@ -484,7 +515,7 @@ function scripts.patterns.convert()
else
local destination = environment.argument("destination") or "."
if path == destination then
- resport("source path and destination path should differ (use --path and/or --destination)")
+ report("source path and destination path should differ (use --path and/or --destination)")
else
local files = environment.files
local only = false
@@ -516,6 +547,8 @@ if environment.argument("check") then
elseif environment.argument("convert") then
scripts.patterns.prepare()
scripts.patterns.convert()
+elseif environment.argument("exporthelp") then
+ application.export(environment.argument("exporthelp"),environment.files[1])
else
application.help()
end
diff --git a/Master/texmf-dist/scripts/context/lua/mtx-pdf.lua b/Master/texmf-dist/scripts/context/lua/mtx-pdf.lua
index 5654b8bc487..3e4130344ee 100644
--- a/Master/texmf-dist/scripts/context/lua/mtx-pdf.lua
+++ b/Master/texmf-dist/scripts/context/lua/mtx-pdf.lua
@@ -6,14 +6,35 @@ if not modules then modules = { } end modules ['mtx-pdf'] = {
license = "see context related readme files"
}
+local tonumber = tonumber
+local format, gmatch = string.format, string.gmatch
+local utfchar = utf.char
+local concat = table.concat
+local setmetatableindex, sortedhash, sortedkeys = table.setmetatableindex, table.sortedhash, table.sortedkeys
+
local helpinfo = [[
---info show some info about the given file
---metadata show metadata xml blob
+
+
+
+ mtx-pdf
+ ConTeXt PDF Helpers
+ 0.10
+
+
+
+
+ show some info about the given file
+ show metadata xml blob
+ show used fonts (
+
+
+
+
]]
local application = logs.application {
name = "mtx-pdf",
- banner = "ConTeXt PDF Helpers 0.01",
+ banner = "ConTeXt PDF Helpers 0.10",
helpinfo = helpinfo,
}
@@ -39,9 +60,8 @@ local function loadpdffile(filename)
end
end
-function scripts.pdf.info()
- local filename = environment.files[1]
- local pdffile = loadpdffile(filename)
+function scripts.pdf.info(filename)
+ local pdffile = loadpdffile(filename)
if pdffile then
local catalog = pdffile.Catalog
local info = pdffile.Info
@@ -73,9 +93,8 @@ function scripts.pdf.info()
end
end
-function scripts.pdf.metadata()
- local filename = environment.files[1]
- local pdffile = loadpdffile(filename)
+function scripts.pdf.metadata(filename)
+ local pdffile = loadpdffile(filename)
if pdffile then
local catalog = pdffile.Catalog
local metadata = catalog.Metadata
@@ -87,10 +106,129 @@ function scripts.pdf.metadata()
end
end
-if environment.argument("info") then
- scripts.pdf.info()
+local function getfonts(pdffile)
+ local usedfonts = { }
+ for i=1,pdffile.pages.n do
+ local page = pdffile.pages[i]
+ local fontlist = page.Resources.Font
+ for k, v in next, lpdf.epdf.expand(fontlist) do
+ usedfonts[k] = lpdf.epdf.expand(v)
+ end
+ end
+ return usedfonts
+end
+
+local function getunicodes(font)
+ local cid = font.ToUnicode
+ if cid then
+ cid = cid()
+ local counts = { }
+ -- for s in gmatch(cid,"begincodespacerange%s*(.-)%s*endcodespacerange") do
+ -- for a, b in gmatch(s,"<([^>]+)>%s+<([^>]+)>") do
+ -- print(a,b)
+ -- end
+ -- end
+ setmetatableindex(counts, function(t,k) t[k] = 0 return 0 end)
+ for s in gmatch(cid,"beginbfrange%s*(.-)%s*endbfrange") do
+ for first, last, offset in gmatch(s,"<([^>]+)>%s+<([^>]+)>%s+<([^>]+)>") do
+ first = tonumber(first,16)
+ last = tonumber(last,16)
+ offset = tonumber(offset,16)
+ offset = offset - first
+ for i=first,last do
+ local c = i + offset
+ counts[c] = counts[c] + 1
+ end
+ end
+ end
+ for s in gmatch(cid,"beginbfchar%s*(.-)%s*endbfchar") do
+ for old, new in gmatch(s,"<([^>]+)>%s+<([^>]+)>") do
+ for n in gmatch(new,"....") do
+ local c = tonumber(n,16)
+ counts[c] = counts[c] + 1
+ end
+ end
+ end
+ return counts
+ end
+end
+
+function scripts.pdf.fonts(filename)
+ local pdffile = loadpdffile(filename)
+ if pdffile then
+ local usedfonts = getfonts(pdffile)
+ local found = { }
+ for k, v in table.sortedhash(usedfonts) do
+ local counts = getunicodes(v)
+ local codes = { }
+ local chars = { }
+ local freqs = { }
+ if counts then
+ codes = sortedkeys(counts)
+ for i=1,#codes do
+ local k = codes[i]
+ local c = utfchar(k)
+ chars[i] = c
+ freqs[i] = format("U+%05X %s %s",k,counts[k] > 1 and "+" or " ", c)
+ end
+ for i=1,#codes do
+ codes[i] = format("U+%05X",codes[i])
+ end
+ end
+ found[k] = {
+ basefont = v.BaseFont or "no basefont",
+ encoding = v.Encoding or "no encoding",
+ subtype = v.Subtype or "no subtype",
+ unicode = v.ToUnicode and "unicode" or "no unicode",
+ chars = chars,
+ codes = codes,
+ freqs = freqs,
+ }
+ end
+
+ if environment.argument("detail") then
+ for k, v in sortedhash(found) do
+ report("id : %s",k)
+ report("basefont : %s",v.basefont)
+ report("encoding : %s",v.encoding)
+ report("subtype : %s",v.subtype)
+ report("unicode : %s",v.unicode)
+ report("characters : %s", concat(v.chars," "))
+ report("codepoints : %s", concat(v.codes," "))
+ report("")
+ end
+ else
+ local results = { { "id", "basefont", "encoding", "subtype", "unicode", "characters" } }
+ for k, v in sortedhash(found) do
+ results[#results+1] = { k, v.basefont, v.encoding, v.subtype, v.unicode, concat(v.chars," ") }
+ end
+ utilities.formatters.formatcolumns(results)
+ report(results[1])
+ report("")
+ for i=2,#results do
+ report(results[i])
+ end
+ report("")
+ end
+ end
+end
+
+-- scripts.pdf.info("e:/tmp/oeps.pdf")
+-- scripts.pdf.metadata("e:/tmp/oeps.pdf")
+-- scripts.pdf.fonts("e:/tmp/oeps.pdf")
+
+local filename = environment.files[1] or ""
+
+if filename == "" then
+ application.help()
+elseif environment.argument("info") then
+ scripts.pdf.info(filename)
elseif environment.argument("metadata") then
- scripts.pdf.metadata()
+ scripts.pdf.metadata(filename)
+elseif environment.argument("fonts") then
+ scripts.pdf.fonts(filename)
+elseif environment.argument("exporthelp") then
+ application.export(environment.argument("exporthelp"),environment.files[1])
else
application.help()
end
diff --git a/Master/texmf-dist/scripts/context/lua/mtx-profile.lua b/Master/texmf-dist/scripts/context/lua/mtx-profile.lua
index 74e1d153845..3550474f38c 100644
--- a/Master/texmf-dist/scripts/context/lua/mtx-profile.lua
+++ b/Master/texmf-dist/scripts/context/lua/mtx-profile.lua
@@ -12,8 +12,22 @@ if not modules then modules = { } end modules ['mtx-profile'] = {
local match, format, find = string.match, string.format, string.find
local helpinfo = [[
---analyze analyze lua calls
---trace analyze tex calls
+
+
+
+ mtx-profile
+ ConTeXt MkIV LuaTeX Profiler
+ 1.00
+
+
+
+
+ analyze lua calls
+ analyze tex calls
+
+
+
+
]]
local application = logs.application {
@@ -41,33 +55,28 @@ function scripts.profiler.analyze(filename)
if f then
local times, counts, calls = { }, { }, { }
local totalruntime, totalcount, totalcalls = 0, 0, 0
- while true do
- local line = f:read()
- if line then
- local stacklevel, filename, functionname, linenumber, currentline, localtime, totaltime = line:match("^(%d+)\t(.-)\t(.-)\t(.-)\t(.-)\t(.-)\t(.-)")
- if not filename then
- -- next
- elseif filename == "=[C]" then
- if not functionname:find("^%(") then
- calls[functionname] = (calls[functionname] or 0) + 1
- end
- else
- local filename = filename:match("^@(.*)$")
- if filename then
- local fi = times[filename]
- if not fi then fi = { } times[filename] = fi end
- fi[functionname] = (fi[functionname] or 0) + tonumber(localtime)
- counts[functionname] = (counts[functionname] or 0) + 1
- end
+ for line in f:lines() do
+ local stacklevel, filename, functionname, linenumber, currentline, localtime, totaltime = line:match("^(%d+)\t(.-)\t(.-)\t(.-)\t(.-)\t(.-)\t(.-)")
+ if not filename then
+ -- next
+ elseif filename == "=[C]" then
+ if not functionname:find("^%(") then
+ calls[functionname] = (calls[functionname] or 0) + 1
end
else
- break
+ local filename = filename:match("^@(.*)$")
+ if filename then
+ local fi = times[filename]
+ if not fi then fi = { } times[filename] = fi end
+ fi[functionname] = (fi[functionname] or 0) + tonumber(localtime)
+ counts[functionname] = (counts[functionname] or 0) + 1
+ end
end
end
f:close()
print("")
local loaded = { }
- sortedtable.sortedkeys(times)
+ local sorted = table.sortedkeys(times)
for i=1,#sorted do
local filename = sorted[i]
local functions = times[filename]
@@ -171,6 +180,8 @@ if environment.argument("analyze") then
scripts.profiler.analyze(environment.files[1] or "luatex-profile.log")
elseif environment.argument("trace") then
scripts.profiler.analyze(environment.files[1] or "temp.log")
+elseif environment.argument("exporthelp") then
+ application.export(environment.argument("exporthelp"),environment.files[1])
else
application.help()
end
diff --git a/Master/texmf-dist/scripts/context/lua/mtx-rsync.lua b/Master/texmf-dist/scripts/context/lua/mtx-rsync.lua
index b549d5bcb62..65f795ee557 100644
--- a/Master/texmf-dist/scripts/context/lua/mtx-rsync.lua
+++ b/Master/texmf-dist/scripts/context/lua/mtx-rsync.lua
@@ -46,9 +46,23 @@ if not modules then modules = { } end modules ['mtx-rsync'] = {
-- }
local helpinfo = [[
---job use given file as specification
---dryrun show what would happen
---force force run
+
+
+
+ mtx-rsync
+ Rsync Helpers
+ 0.10
+
+
+
+
+ use given file as specification
+ show what would happen
+ force run
+
+
+
+
]]
local application = logs.application {
@@ -79,7 +93,7 @@ else
end
function rsynccommand(dryrun,recurse,origin,target)
- local command = "rsync -ptlv "
+ local command = "rsync -ptlva "
if dryrun then
command = command .. "-n "
end
@@ -104,6 +118,11 @@ function rsync.run(origin,target,message,recurse)
end
origin = cleanup(origin)
target = cleanup(target)
+ local path = gsub(target,"^/cygdrive/(.)","%1:")
+ if not lfs.isdir(path) then
+ report_message("creating target dir %s",path)
+ dir.makedirs(path) -- as rsync only creates them when --recursive
+ end
if message then
report_message(message)
end
@@ -159,7 +178,9 @@ elseif arguments.force then
rsync.mode = "force"
end
-if arguments.job then
+if arguments.exporthelp then
+ application.export(arguments.exporthelp,environment.files[1])
+elseif arguments.job then
rsync.job(files[1])
elseif files[1] and files[2] then
rsync.run(files[1],files[2])
diff --git a/Master/texmf-dist/scripts/context/lua/mtx-scite.lua b/Master/texmf-dist/scripts/context/lua/mtx-scite.lua
index 116555e79b0..972edbfe6a6 100644
--- a/Master/texmf-dist/scripts/context/lua/mtx-scite.lua
+++ b/Master/texmf-dist/scripts/context/lua/mtx-scite.lua
@@ -10,13 +10,22 @@ local P, R, S, C, Ct, Cf, Cc, Cg = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Ct, lpeg
local lpegmatch = lpeg.match
local format, lower, gmatch = string.format, string.lower, string.gmatch
--- local helpinfo = [[
--- --start [--verbose] start scite
--- --test report what will happen
--- ]]
-
local helpinfo = [[
---words convert spell-*.txt into spell-*.lua
+
+
+
+ mtx-scite
+ Scite Helper Script
+ 1.00
+
+
+
+
+ convert spell-*.txt into spell-*.lua
+
+
+
+
]]
local application = logs.application {
@@ -199,14 +208,31 @@ function scripts.scite.words()
if lfs.isfile(txtname) then
report("loading %s",txtname)
local olddata = io.loaddata(txtname) or ""
+ local words = splitwords(olddata)
+ local min, max, n = 100, 1, 0
+ for k, v in next, words do
+ local l = #k
+ if l < min then
+ min = l
+ end
+ if l > max then
+ max = l
+ end
+ n = n + 1
+ end
+ if min > max then
+ min = max
+ end
local newdata = {
- words = splitwords(olddata),
- -- words = olddata,
+ words = words,
source = oldname,
+ min = min,
+ max = max,
+ n = n,
}
- report("saving %s",luaname)
+ report("saving %q, %s words, %s shortest, %s longest",luaname,n,min,max)
io.savedata(luaname,table.serialize(newdata,true))
- report("compiling %s",lucname)
+ report("compiling %q",lucname)
os.execute(format("luac -s -o %s %s",lucname,luaname))
else
report("no data file %s",txtname)
@@ -225,6 +251,8 @@ end
if environment.argument("words") then
scripts.scite.words()
+elseif environment.argument("exporthelp") then
+ application.export(environment.argument("exporthelp"),environment.files[1])
else
application.help()
end
diff --git a/Master/texmf-dist/scripts/context/lua/mtx-server-ctx-fonttest.lua b/Master/texmf-dist/scripts/context/lua/mtx-server-ctx-fonttest.lua
index b30cf017525..a8d7edf4106 100644
--- a/Master/texmf-dist/scripts/context/lua/mtx-server-ctx-fonttest.lua
+++ b/Master/texmf-dist/scripts/context/lua/mtx-server-ctx-fonttest.lua
@@ -6,12 +6,17 @@ if not modules then modules = { } end modules ['mtx-server-ctx-fonttest'] = {
license = "see context related readme files"
}
---~ dofile(resolvers.findfile("l-aux.lua","tex"))
+-- probably too much but who cares
+
dofile(resolvers.findfile("trac-lmx.lua","tex"))
+dofile(resolvers.findfile("font-ini.lua","tex"))
+dofile(resolvers.findfile("font-con.lua","tex"))
+dofile(resolvers.findfile("font-oti.lua","tex"))
+dofile(resolvers.findfile("font-otf.lua","tex"))
+dofile(resolvers.findfile("font-otp.lua","tex"))
dofile(resolvers.findfile("font-ott.lua","tex"))
dofile(resolvers.findfile("font-syn.lua","tex"))
dofile(resolvers.findfile("font-mis.lua","tex"))
---~ dofile(resolvers.findfile("font-otp.lua","tex"))
local format, gsub, concat, match, find = string.format, string.gsub, table.concat, string.match, string.find
@@ -34,7 +39,7 @@ local process_templates = { }
process_templates.default = [[
\starttext
- \setcharactermirroring[1]
+ \setupdirections[bidi=global]
\definefontfeature[sample][analyze=yes,%s]
\definedfont[name:%s*sample]
\startTEXpage[offset=3pt]
@@ -59,7 +64,7 @@ process_templates.trace = [[
\setupcolors[state=start]
-\setcharactermirroring[1]
+\setupdirections[bidi=global]
\setvariables
[otftracker]
@@ -280,9 +285,11 @@ local edit_template = [[
options: %s
]]
+--
+
local result_template = [[
-
+
results:
tex file
pdf file
@@ -377,8 +384,14 @@ local function process_font(currentfont,detail) -- maybe just fontname
local sample = string.strip(detail.sampletext or "")
if sample == "" then sample = sample_line end
report("sample text: %s",sample)
- io.savedata(file.join(temppath,file.addsuffix(tempname,"tex")),format(variant,concat(features,","),currentfont,sample))
- os.execute(format("mtxrun --path=%s --script context --once --batchmode %s",temppath,tempname))
+ dir.mkdirs(temppath)
+ local fullname = file.join(temppath,file.addsuffix(tempname,"tex"))
+ local data = format(variant,concat(features,","),currentfont,sample)
+ local command = format("mtxrun --path=%q --script context --once --batchmode %q",temppath,tempname)
+ report("filename: %s",fullname)
+ report("command: %s",command)
+ io.savedata(fullname,data)
+ os.execute(command)
return edit_font(currentfont,detail,tempname)
end
@@ -390,7 +403,8 @@ local tex_template = [[
local function show_source(currentfont,detail)
if tempname and tempname ~= "" then
- return format(tex_template,io.loaddata(file.join(temppath,file.addsuffix(tempname,"tex"))) or "no source yet")
+ local data = io.loaddata(file.join(temppath,file.addsuffix(tempname,"tex"))) or "no source yet"
+ return format(tex_template,data)
else
return "no source file"
end
diff --git a/Master/texmf-dist/scripts/context/lua/mtx-server-ctx-help.lua b/Master/texmf-dist/scripts/context/lua/mtx-server-ctx-help.lua
index a212e1369d0..b8dc0dfb278 100644
--- a/Master/texmf-dist/scripts/context/lua/mtx-server-ctx-help.lua
+++ b/Master/texmf-dist/scripts/context/lua/mtx-server-ctx-help.lua
@@ -9,13 +9,11 @@ if not modules then modules = { } end modules ['mtx-server-ctx-help'] = {
-- todo in lua interface: noargument, oneargument, twoarguments, threearguments
-- todo: pickup translations from mult file
---~ dofile(resolvers.findfile("l-aux.lua","tex"))
---~ dofile(resolvers.findfile("l-url.lua","tex"))
dofile(resolvers.findfile("trac-lmx.lua","tex"))
-- problem ... serialize parent stack
-local format = string.format
+local format, match, gsub, find = string.format, string.match, string.gsub, string.find
local concat = table.concat
local report = logs.reporter("ctx-help")
@@ -282,18 +280,48 @@ document.setups.translations = document.setups.translations or {
}
document.setups.formats = {
- open_command = { [[\%s]], [[context.%s (]] },
- close_command = { [[]], [[ )]] },
- connector = { [[]], [[, ]] },
- href_in_list = { [[%s ]], [[%s ]] },
- href_as_command = { [[\%s ]], [[context.%s ]] },
+ open_command = {
+ tex = [[\%s]],
+ lua = [[context.%s (]],
+ },
+ close_command = {
+ tex = [[]],
+ lua = [[ )]],
+ },
+ connector = {
+ tex = [[]],
+ lua = [[, ]],
+ },
+ href_in_list = {
+ tex = [[%s ]],
+ lua = [[%s ]],
+ },
+ href_as_command = {
+ tex = [[\%s ]],
+ lua = [[context.%s ]],
+ },
+ modes = {
+ tex = [[lua mode ]],
+ lua = [[tex mode ]],
+ },
+ optional_single = {
+ tex = "[optional string %s]",
+ lua = "{optional string %s}",
+ },
+ optional_list = {
+ tex = "[optional list %s]",
+ lua = "{optional table %s}" ,
+ } ,
+ mandate_single = {
+ tex = "[mandate string %s]",
+ lua = "{mandate string %s}",
+ },
+ mandate_list = {
+ tex = "[mandate list %s]",
+ lua = "{mandate list %s}",
+ },
interface = [[%s ]],
source = [[%s ]],
- modes = { [[lua mode ]], [[tex mode ]] },
- optional_single = { "[optional string %s]", "{optional string %s}" },
- optional_list = { "[optional list %s]", "{optional table %s}" } ,
- mandate_single = { "[mandate string %s]", "{mandate string %s}" },
- mandate_list = { "[mandate list %s]", "{mandate list %s}" },
parameter = [[%s %s %s ]],
parameters = [[]],
listing = [[%s ]],
@@ -315,7 +343,7 @@ end
local function translated(e,int)
local attributes = e.at
local s = attributes.type or "?"
- local tag = s:match("^cd:(.*)$")
+ local tag = match(s,"^cd:(.*)$")
if attributes.default == "yes" then
return format(document.setups.formats.default,tag or "?")
elseif tag then
@@ -329,7 +357,7 @@ document.setups.loaded = document.setups.loaded or { }
document.setups.current = { }
document.setups.showsources = true
-document.setups.mode = 1
+document.setups.mode = "tex"
function document.setups.load(filename)
filename = resolvers.findfile(filename) or ""
@@ -402,7 +430,7 @@ end
function document.setups.show(name)
local current = document.setups.current
if current.root then
- local name = name:gsub("[<>]","")
+ local name = gsub(name,"[<>]","")
local setup = xml.first(current.root,"cd:command[@name='" .. name .. "']")
current.used[#current.used+1] = setup
xml.sprint(setup)
@@ -452,12 +480,12 @@ function document.setups.collect(name,int,lastmode)
category = attributes.category or "",
}
if document.setups.showsources then
- data.source = (attributes.file and formats.source:format(attributes.file,lastmode,attributes.file)) or ""
+ data.source = (attributes.file and format(formats.source,attributes.file,lastmode,attributes.file)) or ""
else
data.source = attributes.file or ""
end
local n, sequence, tags = 0, { }, { }
- sequence[#sequence+1] = formats.open_command[lastmode]:format(document.setups.csname(command,int))
+ sequence[#sequence+1] = format(formats.open_command[lastmode],document.setups.csname(command,int))
local arguments, tag = { }, ""
for r, d, k in xml.elements(command,"(cd:keywords|cd:assignments)") do
n = n + 1
@@ -470,15 +498,15 @@ function document.setups.collect(name,int,lastmode)
end
if attributes.optional == 'yes' then
if attributes.list == 'yes' then
- tag = formats.optional_list[lastmode]:format(n)
+ tag = format(formats.optional_list[lastmode],n)
else
- tag = formats.optional_single[lastmode]:format(n)
+ tag = format(formats.optional_single[lastmode],n)
end
else
if attributes.list == 'yes' then
- tag = formats.mandate_list[lastmode]:format(n)
+ tag = format(formats.mandate_list[lastmode],n)
else
- tag = formats.mandate_single[lastmode]:format(n)
+ tag = format(formats.mandate_single[lastmode],n)
end
end
sequence[#sequence+1] = tag
@@ -506,7 +534,7 @@ function document.setups.collect(name,int,lastmode)
right[#right+1] = translated(d[k],int)
end
end
- parameters[#parameters+1] = formats.parameter:format(left,"",concat(right, ", "))
+ parameters[#parameters+1] = format(formats.parameter,left,"",concat(right, ", "))
else
local what = tags[n]
for r, d, k in xml.elements(d[k],"(cd:parameter|cd:inherit)") do
@@ -514,11 +542,11 @@ function document.setups.collect(name,int,lastmode)
local left, right = d[k].at.name or "?", { }
if tag == "inherit" then
local name = d[k].at.name or "?"
- local goto = document.setups.formats.href_as_command[lastmode]:format(name,lastmode,name)
- if #parameters > 0 and not parameters[#parameters]:find(" ") then
- parameters[#parameters+1] = formats.parameter:format(" ","","")
+ local goto = format(document.setups.formats.href_as_command[lastmode],name,lastmode,name)
+ if #parameters > 0 and not find(parameters[#parameters]," ") then
+ parameters[#parameters+1] = format(formats.parameter," ","","")
end
- parameters[#parameters+1] = formats.parameter:format(what,formats.special:format(translate("inherits",int)),goto)
+ parameters[#parameters+1] = format(formats.parameter,what,format(formats.special,translate("inherits",int)),goto)
else
for r, d, k in xml.elements(d[k],"(cd:constant|cd:resolve)") do
local tag = d[k].tg
@@ -534,15 +562,15 @@ function document.setups.collect(name,int,lastmode)
right[#right+1] = translated(d[k],int)
end
end
- parameters[#parameters+1] = formats.parameter:format(what,left,concat(right, ", "))
+ parameters[#parameters+1] = format(formats.parameter,what,left,concat(right, ", "))
end
what = ""
end
end
- parameters[#parameters+1] = formats.parameter:format(" ","","")
+ parameters[#parameters+1] = format(formats.parameter," ","","")
end
data.parameters = parameters or { }
- data.mode = formats.modes[lastmode or 1]
+ data.mode = formats.modes[lastmode or "tex"]
return data
else
return nil
@@ -566,7 +594,7 @@ local interfaces = {
romanian = 'ro',
}
-local lastinterface, lastcommand, lastsource, lastmode = "en", "", "", 1
+local lastinterface, lastcommand, lastsource, lastmode = "en", "", "", "tex"
local variables = {
['color-background-main-left'] = '#3F3F3F',
@@ -584,78 +612,87 @@ local function doit(configuration,filename,hashed)
local formats = document.setups.formats
- local start = os.clock()
+ local start = os.clock()
+ local detail = hashed.queries or { }
- local detail = url.query(hashed.query or "")
+ if detail then
- lastinterface = detail.interface or lastinterface
- lastcommand = detail.command or lastcommand
- lastsource = detail.source or lastsource
- lastmode = tonumber(detail.mode or lastmode) or 1
+ lastinterface = detail.interface or lastinterface
+ lastcommand = detail.command or lastcommand
+ lastsource = detail.source or lastsource
+ lastmode = detail.mode or lastmode or "tex"
- if lastinterface then
- report("checking interface: %s",lastinterface)
- document.setups.load(format("cont-%s.xml",lastinterface))
- end
+ lastcommand = gsub(lastcommand,"%s*^\\*(.+)%s*","%1")
- local div = document.setups.div[lastinterface]
- local span = document.setups.span[lastinterface]
+ if lastinterface then
+ report("checking interface: %s",lastinterface)
+ document.setups.load(format("cont-%s.xml",lastinterface))
+ end
- local result = { content = "error" }
+ local div = document.setups.div [lastinterface]
+ local span = document.setups.span[lastinterface]
- local names, refs, ints = document.setups.names(lastinterface), { }, { }
- for k=1,#names do
- local v = names[k]
- refs[k] = formats.href_in_list[lastmode]:format(v[1],lastmode,v[2])
- end
- if lastmode ~= 2 then
- local sorted = table.sortedkeys(interfaces)
- for k=1,#sorted do
- local v = sorted[k]
- ints[k] = formats.interface:format(interfaces[v],lastmode,v)
+ local names, refs, ints = document.setups.names(lastinterface), { }, { }
+ for k=1,#names do
+ local v = names[k]
+ refs[k] = format(formats.href_in_list[lastmode],v[1],lastmode,v[2])
+ end
+ if lastmode ~= "lua" then
+ local sorted = table.sortedkeys(interfaces)
+ for k=1,#sorted do
+ local v = sorted[k]
+ ints[k] = format(formats.interface,interfaces[v],lastmode,v)
+ end
end
- end
- local n = concat(refs," ")
- local i = concat(ints," ")
+ local n = concat(refs," ")
+ local i = concat(ints," ")
- if div then
- variables.names = div:format(n)
- variables.interfaces = div:format(i)
- else
- variables.names = n
- variables.interfaces = i
- end
+ if div then
+ variables.names = format(div,n)
+ variables.interfaces = format(div,i)
+ else
+ variables.names = n
+ variables.interfaces = i
+ end
- -- first we need to add information about mkii/mkiv
-
- variables.maintitle = "no definition"
- variables.maintext = ""
- variables.extra = ""
-
- if document.setups.showsources and lastsource and lastsource ~= "" then
- -- todo: mkii, mkiv, tex (can be different)
- local data = io.loaddata(resolvers.findfile(lastsource))
- variables.maintitle = lastsource
- variables.maintext = formats.listing:format(data)
- lastsource = ""
- elseif lastcommand and lastcommand ~= "" then
- local data = document.setups.collect(lastcommand,lastinterface,lastmode)
- if data then
- local what, extra = { "environment", "category", "source", "mode" }, { }
- for k=1,#what do
- local v = what[k]
- if data[v] and data[v] ~= "" then
- lmx.set(v, data[v])
- extra[#extra+1] = v .. ": " .. data[v]
+ -- first we need to add information about mkii/mkiv
+
+ variables.maintitle = "no definition"
+ variables.maintext = ""
+ variables.extra = ""
+
+ if document.setups.showsources and lastsource and lastsource ~= "" then
+ -- todo: mkii, mkiv, tex (can be different)
+ local data = io.loaddata(resolvers.findfile(lastsource))
+ variables.maintitle = lastsource
+ variables.maintext = format(formats.listing,data)
+ lastsource = ""
+ elseif lastcommand and lastcommand ~= "" then
+ local data = document.setups.collect(lastcommand,lastinterface,lastmode)
+ if data then
+ local what, extra = { "environment", "category", "source", "mode" }, { }
+ for k=1,#what do
+ local v = what[k]
+ if data[v] and data[v] ~= "" then
+ lmx.set(v, data[v])
+ extra[#extra+1] = v .. ": " .. data[v]
+ end
end
+ variables.maintitle = data.sequence
+ variables.maintext = format(formats.parameters,concat(data.parameters))
+ variables.extra = concat(extra," ")
+ else
+ variables.maintext = "select command"
end
- variables.maintitle = data.sequence
- variables.maintext = formats.parameters:format(concat(data.parameters))
- variables.extra = concat(extra," ")
- else
- variables.maintext = "select command"
end
+
+ else
+
+ variables.maintitle = "no definition"
+ variables.maintext = "some error"
+ variables.extra = ""
+
end
local content = lmx.convert('context-help.lmx',false,variables)
diff --git a/Master/texmf-dist/scripts/context/lua/mtx-server.lua b/Master/texmf-dist/scripts/context/lua/mtx-server.lua
index 068d5111130..5ec15de708f 100644
--- a/Master/texmf-dist/scripts/context/lua/mtx-server.lua
+++ b/Master/texmf-dist/scripts/context/lua/mtx-server.lua
@@ -7,12 +7,26 @@ if not modules then modules = { } end modules ['mtx-server'] = {
}
local helpinfo = [[
---start start server
---port port to listen to
---root server root
---scripts scripts sub path
---index index file
---auto start on own path
+
+
+
+ mtx-server
+ Simple Webserver For Helpers
+ 0.10
+
+
+
+
+ start server
+ port to listen to
+ server root
+ scripts sub path
+ index file
+ start on own path
+
+
+
+
]]
local application = logs.application {
@@ -26,11 +40,10 @@ local report = application.report
scripts = scripts or { }
scripts.webserver = scripts.webserver or { }
-dofile(resolvers.findfile("l-url.lua","tex"))
dofile(resolvers.findfile("luat-soc.lua","tex"))
local socket = socket or require("socket")
-local http = socket or require("socket.http")
+local http = http or require("socket.http") -- not needed
local format = string.format
-- The following two lists are taken from webrick (ruby) and
@@ -192,13 +205,13 @@ function handlers.generic(client,configuration,data,suffix,iscontent)
end
end
---~ return os.date()
+-- return os.date()
---~ return { content = "crap" }
+-- return { content = "crap" }
---~ return function(configuration,filename)
---~ return { content = filename }
---~ end
+-- return function(configuration,filename)
+-- return { content = filename }
+-- end
local loaded = { }
@@ -226,11 +239,13 @@ function handlers.lua(client,configuration,filename,suffix,iscontent,hashed) --
end
end
else
+ report("problematic script: %s",filename)
errormessage(client,configuration,404)
end
end
if result then
if type(result) == "function" then
+ report("running script: %s",filename)
result = result(configuration,filename,hashed) -- second argument will become query
end
if result and type(result) == "string" then
@@ -242,7 +257,7 @@ function handlers.lua(client,configuration,filename,suffix,iscontent,hashed) --
local action = handlers[suffix] or handlers.generic
action(client,configuration,result.content,suffix,true) -- content
elseif result.filename then
- local suffix = file.extname(result.filename) or "text/html"
+ local suffix = file.suffix(result.filename) or "text/html"
local action = handlers[suffix] or handlers.generic
action(client,configuration,result.filename,suffix,false) -- filename
else
@@ -301,40 +316,50 @@ function scripts.webserver.run(configuration)
report("scripts subpath: %s",configuration.scripts)
report("context services: http://localhost:%s/mtx-server-ctx-startup.lua",configuration.port)
local server = assert(socket.bind("*", configuration.port))
--- local reading = { server }
- while true do -- no multiple clients
+ local script = configuration.script
+ while true do -- blocking
local start = os.clock()
--- local input = socket.select(reading)
--- local client = input:accept()
local client = server:accept()
client:settimeout(configuration.timeout or 60)
local request, e = client:receive()
--- local request, e = client:receive("*a") -- doesn't work well (so no post)
if e then
errormessage(client,configuration,404)
else
local from = client:getpeername()
report("request from: %s",tostring(from))
- local fullurl = request:match("GET (.+) HTTP/.*$") or "" -- todo: more clever / post
+ report("request data: %s",tostring(request))
+ local fullurl = string.match(request,"GET (.+) HTTP/.*$") or "" -- todo: more clever / post
if fullurl == "" then
+ report("no url")
errormessage(client,configuration,404)
else
- fullurl = socket.url.unescape(fullurl)
+ report("requested url: %s",fullurl)
+ fullurl = socket.url.unescape(fullurl) -- still needed?
local hashed = url.hashed(fullurl)
local query = url.query(hashed.query)
- local filename = hashed.path
--- table.print(hashed)
- if filename then
+ local filename = hashed.path -- hm, not query?
+ if script then
+ filename = script
+ report("forced script: %s",filename)
+ local suffix = file.suffix(filename)
+ local action = handlers[suffix] or handlers.generic
+ if action then
+ report("performing action: %s",filename)
+ action(client,configuration,filename,suffix,false,hashed) -- filename and no content
+ else
+ errormessage(client,configuration,404)
+ end
+ elseif filename then
filename = socket.url.unescape(filename)
report("requested action: %s",filename)
- if filename:find("%.%.") then
+ if string.find(filename,"%.%.") then
filename = nil -- invalid path
end
if filename == nil or filename == "" or filename == "/" then
filename = configuration.index
report("invalid filename, forcing: %s",filename)
end
- local suffix = file.extname(filename)
+ local suffix = file.suffix(filename)
local action = handlers[suffix] or handlers.generic
if action then
report("performing action: %s",filename)
@@ -358,6 +383,7 @@ if environment.argument("auto") then
port = environment.argument("port"),
root = environment.argument("root") or file.dirname(path) or ".",
scripts = environment.argument("scripts") or file.dirname(path) or ".",
+ script = environment.argument("script"),
}
elseif environment.argument("start") then
scripts.webserver.run {
@@ -365,10 +391,12 @@ elseif environment.argument("start") then
root = environment.argument("root") or ".", -- "e:/websites/www.pragma-ade.com",
index = environment.argument("index"),
scripts = environment.argument("scripts"),
+ script = environment.argument("script"),
}
+elseif environment.argument("exporthelp") then
+ application.export(environment.argument("exporthelp"),environment.files[1])
else
application.help()
end
-
-- mtxrun --script server --start => http://localhost:31415/mtx-server-ctx-startup.lua
diff --git a/Master/texmf-dist/scripts/context/lua/mtx-texworks.lua b/Master/texmf-dist/scripts/context/lua/mtx-texworks.lua
index 33e56df468a..ae5f2afa419 100644
--- a/Master/texmf-dist/scripts/context/lua/mtx-texworks.lua
+++ b/Master/texmf-dist/scripts/context/lua/mtx-texworks.lua
@@ -7,8 +7,22 @@ if not modules then modules = { } end modules ['mtx-texworks'] = {
}
local helpinfo = [[
---start [--verbose] start texworks
---test report what will happen
+
+
+
+ mtx-texworks
+ TeXworks Startup Script
+ 1.00
+
+
+
+
+ [ start texworks
+ report what will happen
+
+
+
+
]]
local application = logs.application {
@@ -100,6 +114,8 @@ if environment.argument("start") then
scripts.texworks.start(true)
elseif environment.argument("test") then
scripts.texworks.start()
+elseif environment.argument("exporthelp") then
+ application.export(environment.argument("exporthelp"),environment.files[1])
else
application.help()
end
diff --git a/Master/texmf-dist/scripts/context/lua/mtx-timing.lua b/Master/texmf-dist/scripts/context/lua/mtx-timing.lua
index 03100e991af..5ba361e5f1a 100644
--- a/Master/texmf-dist/scripts/context/lua/mtx-timing.lua
+++ b/Master/texmf-dist/scripts/context/lua/mtx-timing.lua
@@ -9,9 +9,23 @@ if not modules then modules = { } end modules ['mtx-timing'] = {
local format, gsub, concat = string.format, string.gsub, table.concat
local helpinfo = [[
---xhtml make xhtml file
---launch launch after conversion
---remove remove after launching
+
+
+
+ mtx-timing
+ ConTeXt Timing Tools
+ 0.10
+
+
+
+
+ make xhtml file
+ launch after conversion
+ remove after launching
+
+
+
+
]]
local application = logs.application {
@@ -22,6 +36,7 @@ local application = logs.application {
local report = application.report
+dofile(resolvers.findfile("node-snp.lua","tex"))
dofile(resolvers.findfile("trac-tim.lua","tex"))
dofile(resolvers.findfile("trac-lmx.lua","tex"))
@@ -71,7 +86,7 @@ local directrun = true
local what = { "parameters", "nodes" }
-plugins = plugins or { } -- brrr, will become moduledata as well
+plugins = plugins or { progress = { } } -- brrr, will become moduledata as well
function plugins.progress.make_svg(filename,other)
local metadata, menudata, c = { }, { }, 0
@@ -196,6 +211,8 @@ end
if environment.argument("xhtml") then
scripts.timings.xhtml(environment.files[1] or "")
+elseif environment.argument("exporthelp") then
+ application.export(environment.argument("exporthelp"),environment.files[1])
else
application.help()
end
diff --git a/Master/texmf-dist/scripts/context/lua/mtx-tools.lua b/Master/texmf-dist/scripts/context/lua/mtx-tools.lua
index 45961a639a0..19b7458a19a 100644
--- a/Master/texmf-dist/scripts/context/lua/mtx-tools.lua
+++ b/Master/texmf-dist/scripts/context/lua/mtx-tools.lua
@@ -9,22 +9,37 @@ if not modules then modules = { } end modules ['mtx-tools'] = {
local find, format, sub, rep, gsub, lower = string.find, string.format, string.sub, string.rep, string.gsub, string.lower
local helpinfo = [[
---disarmutfbomb remove utf bomb if present
- --force remove indeed
-
---dirtoxml glob directory into xml
- --pattern glob pattern (default: *)
- --url url attribute (no processing)
- --root the root of the globbed path (default: .)
- --output output filename (console by default)
- --recurse recurse into subdirecories
- --stripname take pathpart of given pattern
- --longname set name attributes to full path name
-
---downcase
- --pattern glob pattern (default: *)
- --recurse recurse into subdirecories
- --force downcase indeed
+
+
+
+ mtx-tools
+ Some File Related Goodies
+ 1.01
+
+
+
+
+ remove utf bomb if present
+ remove indeed
+
+
+ glob directory into xml
+ glob pattern (default: *)
+ url attribute (no processing)
+ the root of the globbed path (default: .)
+ output filename (console by default)
+ recurse into subdirecories
+ take pathpart of given pattern
+ set name attributes to full path name
+
+
+ glob pattern (default: *)
+ recurse into subdirecories
+ downcase indeed
+
+
+
+
]]
local application = logs.application {
@@ -102,7 +117,7 @@ end
function scripts.tools.dirtoxml()
- local join, removesuffix, extname, date = file.join, file.removesuffix, file.extname, os.date
+ local join, removesuffix, suffixonly, date = file.join, file.removesuffix, file.suffixonly, os.date
local xmlns = "http://www.pragma-ade.com/rlg/xmldir.rng"
local timestamp = "%Y-%m-%d %H:%M"
@@ -124,7 +139,7 @@ function scripts.tools.dirtoxml()
if mode == "file" then
result[#result+1] = format("%s",d,(longname and path and join(path,name)) or name)
result[#result+1] = format("%s %s",d,removesuffix(name))
- result[#result+1] = format("%s %s ",d,extname(name))
+ result[#result+1] = format("%s %s ",d,suffixonly(name))
result[#result+1] = format("%s %s ",d,attr.size)
result[#result+1] = format("%s %s ",d,sub(attr.permissions,7,9))
result[#result+1] = format("%s %s ",d,date(timestamp,attr.modification))
@@ -177,6 +192,8 @@ elseif environment.argument("dirtoxml") then
scripts.tools.dirtoxml()
elseif environment.argument("downcase") then
scripts.tools.downcase()
+elseif environment.argument("exporthelp") then
+ application.export(environment.argument("exporthelp"),environment.files[1])
else
application.help()
end
diff --git a/Master/texmf-dist/scripts/context/lua/mtx-unzip.lua b/Master/texmf-dist/scripts/context/lua/mtx-unzip.lua
index 645863426db..02d9676bcaa 100644
--- a/Master/texmf-dist/scripts/context/lua/mtx-unzip.lua
+++ b/Master/texmf-dist/scripts/context/lua/mtx-unzip.lua
@@ -11,9 +11,23 @@ if not modules then modules = { } end modules ['mtx-unzip'] = {
local format = string.format
local helpinfo = [[
---list list files in archive
---junk flatten unzipped directory structure
---extract extract files
+
+
+
+ mtx-unzip
+ Simple Unzipper
+ 0.10
+
+
+
+
+ list files in archive
+ flatten unzipped directory structure
+ extract files
+
+
+
+
]]
local application = logs.application {
@@ -109,6 +123,8 @@ if environment.arguments["h"] or environment.arguments["help"] then
application.help()
elseif environment.arguments["l"] or environment.arguments["list"] then
scripts.unzipper.list(zipfile)
+elseif environment.arguments["exporthelp"] then
+ application.export(environment.arguments["exporthelp"],environment.files[1])
elseif environment.files[1] then -- implicit --extract
scripts.unzipper.extract(zipfile)
else
diff --git a/Master/texmf-dist/scripts/context/lua/mtx-update.lua b/Master/texmf-dist/scripts/context/lua/mtx-update.lua
index 037de8650ff..64203d3e3e2 100644
--- a/Master/texmf-dist/scripts/context/lua/mtx-update.lua
+++ b/Master/texmf-dist/scripts/context/lua/mtx-update.lua
@@ -12,27 +12,43 @@ if not modules then modules = { } end modules ['mtx-update'] = {
-- platforms that matter.
local helpinfo = [[
---platform=string platform (windows, linux, linux-64, osx-intel, osx-ppc, linux-ppc)
---server=string repository url (rsync://contextgarden.net)
---module=string repository url (minimals)
---repository=string specify version (current, experimental)
---context=string specify version (current, latest, beta, yyyy.mm.dd)
---rsync=string rsync binary (rsync)
---texroot=string installation directory (not guessed for the moment)
---engine=string tex engine (luatex, pdftex, xetex)
---modules=string extra modules (can be list or 'all')
---fonts=string additional fonts (can be list or 'all')
---goodies=string extra binaries (like scite and texworks)
---force instead of a dryrun, do the real thing
---update update minimal tree
---make also make formats and generate file databases
---keep don't delete unused or obsolete files
---state update tree using saved state
+
+
+
+ mtx-update
+ ConTeXt Minimals Updater
+ 0.31
+
+
+
+
+ platform (windows, linux, linux-64, osx-intel, osx-ppc, linux-ppc)
+ repository url (rsync://contextgarden.net)
+ repository url (minimals)
+ specify version (current, experimental)
+ specify version (current, latest, beta, yyyy.mm.dd)
+ rsync binary (rsync)
+ installation directory (not guessed for the moment)
+ tex engine (luatex, pdftex, xetex)
+ extra modules (can be list or 'all')
+ additional fonts (can be list or 'all')
+ extra binaries (like scite and texworks)
+ instead of a dryrun, do the real thing
+ update minimal tree
+ also make formats and generate file databases
+ don't delete unused or obsolete files
+ update tree using saved state
+ adapt drive specs to cygwin
+ assume mingw binaries being used
+
+
+
+
]]
local application = logs.application {
name = "mtx-update",
- banner = "ConTeXt Minimals Updater 0.30",
+ banner = "ConTeXt Minimals Updater 0.31",
helpinfo = helpinfo,
}
@@ -108,6 +124,7 @@ scripts.update.engines = {
["luatex"] = {
{ "fonts/new/", "texmf" },
{ "bin/luatex//", "texmf-" },
+ { "bin/luajittex//","texmf-" },
},
["xetex"] = {
{ "base/xetex/", "texmf" },
@@ -125,6 +142,7 @@ scripts.update.engines = {
{ "fonts/old/", "texmf" },
{ "base/xetex/", "texmf" },
{ "bin/luatex//", "texmf-" },
+ { "bin/luajittex//","texmf-" },
{ "bin/xetex//", "texmf-" },
{ "bin/pdftex//", "texmf-" },
},
@@ -132,10 +150,10 @@ scripts.update.engines = {
scripts.update.goodies = {
["scite"] = {
- { "bin//scite/", "texmf-" },
+ { "bin//scite/", "texmf-" },
},
["texworks"] = {
- { "bin//texworks/", "texmf-" },
+ { "bin//texworks/", "texmf-" },
},
}
@@ -203,6 +221,17 @@ function scripts.update.fullpath(path)
end
end
+local rsync_variant = "cygwin" -- will be come mingw
+
+local function drive(d)
+ if rsync_variant == "cygwin" then
+ d = gsub(d,[[([a-zA-Z]):/]], "/cygdrive/%1/")
+ else
+ d = gsub(d,[[([a-zA-Z]):/]], "/%1/")
+ end
+ return d
+end
+
function scripts.update.synchronize()
report("update, start")
@@ -344,7 +373,7 @@ function scripts.update.synchronize()
destination = gsub(destination,"\\","/")
archive = gsub(archive,"",version)
if osplatform == "windows" or osplatform == "mswin" then
- destination = gsub(destination,"([a-zA-Z]):/", "/cygdrive/%1/") -- ^
+ destination = drive(destination)
end
individual[#individual+1] = { archive, destination }
end
@@ -419,11 +448,11 @@ function scripts.update.synchronize()
if platform then
local command
if platform == 'mswin' then
- bin = gsub(bin,"([a-zA-Z]):/", "/cygdrive/%1/")
- texroot = gsub(texroot,"([a-zA-Z]):/", "/cygdrive/%1/")
- command = format("%s -t %s/texmf-context/scripts/context/lua/%s.lua %s/texmf-mswin/bin/", bin, texroot, script, texroot)
+ bin = drive(bin)
+ texroot = drive(texroot)
+ command = format([[%s -t "%s/texmf-context/scripts/context/lua/%s.lua" "%s/texmf-mswin/bin/"]], bin, texroot, script, texroot)
else
- command = format("%s -tgo --chmod=a+x %s/texmf-context/scripts/context/lua/%s.lua %s/texmf-%s/bin/%s", bin, texroot, script, texroot, platform, script)
+ command = format([[%s -tgo --chmod=a+x '%s/texmf-context/scripts/context/lua/%s.lua' '%s/texmf-%s/bin/%s']], bin, texroot, script, texroot, platform, script)
end
report("updating %s for %s: %s", script, platform, command)
scripts.update.run(command)
@@ -496,6 +525,8 @@ function scripts.update.make()
for engine in next, engines do
if engine == "luatex" then
scripts.update.run(format('mtxrun --tree="%s" --script context --autogenerate --make',texroot))
+ elseif engine == "luajittex" then
+ scripts.update.run(format('mtxrun --tree="%s" --script context --autogenerate --make --engine=luajittex',texroot))
else
scripts.update.run(format('mtxrun --tree="%s" --script texexec --make --all --%s %s',texroot,engine,formatlist))
end
@@ -616,6 +647,12 @@ if environment.argument("state") then
environment.setargument("make",true)
end
+if environment.argument("mingw") then
+ rsync_variant = "mingw"
+elseif environment.argument("cygwin") then
+ rsync_variant = "cygwin"
+end
+
if environment.argument("update") then
scripts.update.synchronize()
if environment.argument("make") then
@@ -623,6 +660,8 @@ if environment.argument("update") then
end
elseif environment.argument("make") then
scripts.update.make()
+elseif environment.argument("exporthelp") then
+ application.export(environment.argument("exporthelp"),environment.files[1])
else
application.help()
end
diff --git a/Master/texmf-dist/scripts/context/lua/mtx-watch.lua b/Master/texmf-dist/scripts/context/lua/mtx-watch.lua
index 36a3176c41a..95323f571cf 100644
--- a/Master/texmf-dist/scripts/context/lua/mtx-watch.lua
+++ b/Master/texmf-dist/scripts/context/lua/mtx-watch.lua
@@ -7,14 +7,28 @@ if not modules then modules = { } end modules ['mtx-watch'] = {
}
local helpinfo = [[
---logpath optional path for log files
---watch watch given path [--delay]
---pipe use pipe instead of execute
---delay delay between sweeps
---automachine replace /machine/ in path //
---collect condense log files
---cleanup=delay remove files in given path [--force]
---showlog show log data
+
+
+
+ mtx-watch
+ ConTeXt Request Watchdog
+ 1.00
+
+
+
+
+ optional path for log files
+ watch given path [
+ use pipe instead of execute
+ delay between sweeps
+ replace /machine/ in path /servername/
+ condense log files
+ remove files in given path [
+ show log data
+
+
+
+
]]
local application = logs.application {
@@ -97,7 +111,7 @@ local function glob(files,path) -- some day: sort by name (order prefix) and ati
end
end
-local clock = os.gettimeofday or os.time -- we cannot trust os.clock on linux
+local clock = os.gettimeofday or (socket and socket.gettime) or os.time -- we cannot trust os.clock on linux
-- local function filenamesort(a,b)
-- local fa, da = a[1], a[2]
@@ -227,17 +241,6 @@ function scripts.watch.watch()
end
end
local n, start = 0, time()
---~ local function wait()
---~ io.flush()
---~ if not done then
---~ n = n + 1
---~ if n >= 10 then
---~ report("run time: %i seconds, memory usage: %0.3g MB", difftime(time(),start), (status.luastate_bytes/1024)/1000)
---~ n = 0
---~ end
---~ os.sleep(delay)
---~ end
---~ end
local wtime = 0
local function wait()
io.flush()
@@ -421,6 +424,8 @@ elseif environment.argument("cleanup") then
scripts.watch.save_logs(scripts.watch.cleanup_stale_files())
elseif environment.argument("showlog") then
scripts.watch.show_logs()
+elseif environment.argument("exporthelp") then
+ application.export(environment.argument("exporthelp"),environment.files[1])
else
application.help()
end
diff --git a/Master/texmf-dist/scripts/context/lua/mtxlibs.lua b/Master/texmf-dist/scripts/context/lua/mtxlibs.lua
new file mode 100644
index 00000000000..60889acde48
--- /dev/null
+++ b/Master/texmf-dist/scripts/context/lua/mtxlibs.lua
@@ -0,0 +1,240 @@
+if not modules then modules = { } end modules ['mtxlibs'] = {
+ version = 1.001,
+ comment = "a reasonable subset of mtxrun preloaded libraries",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- This file can be used to load a the (relevant) helper libraries that are also used
+-- in ConTeXt. You can use it as:
+--
+-- -- if needed (outside texlua):
+--
+-- -- require("lpeg") -- mandate
+-- -- require("md5") -- handy
+-- -- require("lfs") -- recommended
+-- -- require("slunicode") -- sort of obsolete
+--
+-- -- the library:
+--
+-- require("mtxlibs")
+--
+-- An alternative is to merge all libraries into this one so that you don't have to
+-- distribute them.
+--
+-- mtxlibs --selfmerge
+--
+-- If you need additional libraries, you can do something like this:
+--
+-- lua mtxlibs.lua --selfmerge my-web-project.lua trac-lmx util-jsn
+-- lua mtxlibs.lua --selfmerge my-sql-project.lua util-sql util-sql-imp-library util-sql-imp-client
+--
+-- That way you only need to update one file in a project and are not dependent on changes
+-- in the core ConTeXT libraries. The libraries are maintained as part of ConTeXt and used
+-- in projects so relative stable. The code works in Lua 5.1 as well as in 5.2. Not all
+-- functionality makes sense for users who are not familiar with ConTeXt but for instance
+-- trackers and loggers are included because that way we have can provide users with a
+-- consistent ecosystem.
+--
+-- Much of the provided functionality is described in cld-mkiv.pdf and related manuals, on
+-- contextgarden.net as well in articles. The XML subsystem is described in its own manual.
+-- Templates and SQL (not preloaded) is also has its own manual.
+--
+-- The next section contains the merged code, with each block ending uop in its own
+-- closure. The code gets somewhat compacted to save space and speed up loading.
+--
+-- There are some dependencies between the several modules. Also, quite some functions are added
+-- to the regular Lua namespaces. In due time I'll isolate them in their own namespaces but with
+-- the for context handy option to expose them in the normal ones. I might make the dependencies
+-- less but it probably makes no sense to waste time on them.
+
+xpcall(function() local _, t = require("lpeg") return end,function() end) if t then lpeg = t end
+xpcall(function() local _, t = require("md5") return end,function() end) if t then md5 = t end
+xpcall(function() local _, t = require("lfs") return end,function() end) if t then lfs = t end
+xpcall(function() local _, t = require("slunicode") return end,function() end) if t then unicode = t end
+
+-- begin library merge
+
+-- end library merge
+
+local gsub, gmatch, match, find = string.gsub, string.gmatch, string.match, string.find
+local concat = table.concat
+
+local ownname = arg and arg[0] or 'mtxlibs.lua'
+local ownpath = gsub(match(ownname,"^(.+)[\\/].-$") or ".","\\","/")
+local owntree = ownpath
+
+local ownlibs = {
+
+ "l-lua.lua",
+ "l-lpeg.lua",
+ "l-function.lua",
+ "l-string.lua",
+ "l-table.lua",
+ "l-io.lua",
+ "l-number.lua",
+ "l-set.lua",
+ "l-os.lua",
+ "l-file.lua", -- limited functionality when no lfs
+ "l-md5.lua", -- not loaded when no md5 library
+ "l-url.lua",
+ "l-dir.lua", -- limited functionality when no lfs
+ "l-boolean.lua",
+ "l-unicode.lua", -- nowadays independent of slunicode
+ "l-math.lua",
+
+ "util-str.lua",
+ "util-tab.lua",
+ "util-sto.lua",
+ -- "util-lua.lua", -- no need for compiling
+ "util-prs.lua",
+ -- "util-fmt.lua", -- no need for table formatters
+ -- "util-deb.lua", -- no need for debugging (and tracing)
+
+ "trac-set.lua",
+ "trac-log.lua",
+ -- "trac-pro.lua", -- not relevant outside context
+ "trac-inf.lua",
+
+ "util-mrg.lua",
+ "util-tpl.lua",
+
+ "util-env.lua",
+ -- "luat-env.lua", -- not relevant outside context
+
+ "lxml-tab.lua",
+ "lxml-lpt.lua",
+ "lxml-mis.lua",
+ "lxml-aux.lua",
+ "lxml-xml.lua",
+
+}
+
+package.path = "t:/sources/?.lua;t:/sources/?;" .. package.path
+
+local ownlist = {
+ '.',
+ ownpath ,
+ ownpath .. "/../sources", -- HH's development path
+ owntree .. "/../../texmf-local/tex/context/base",
+ owntree .. "/../../texmf-context/tex/context/base",
+ owntree .. "/../../texmf-dist/tex/context/base",
+ owntree .. "/../../texmf/tex/context/base",
+ owntree .. "/../../../texmf-local/tex/context/base",
+ owntree .. "/../../../texmf-context/tex/context/base",
+ owntree .. "/../../../texmf-dist/tex/context/base",
+ owntree .. "/../../../texmf/tex/context/base",
+}
+
+if ownpath == "." then table.remove(ownlist,1) end
+
+own = {
+ name = ownname,
+ path = ownpath,
+ tree = owntree,
+ list = ownlist,
+ libs = ownlibs,
+}
+
+local function locate_libs()
+ local name = ownlibs[1]
+ local done = false
+ for i=1,#ownlist do
+ local path = ownlist[i]
+ local filename = path .. "/" .. name
+ local f = io.open(filename)
+ if f then
+ f:close()
+ package.path = package.path .. ";" .. path .. "/?.lua" -- in case l-* does a require
+ done = path
+ break
+ end
+ end
+ locate_libs = function() return done end
+ return done
+end
+
+local function load_libs()
+ local found = locate_libs()
+ if found then
+ for i=1,#ownlibs do
+ local basename = ownlibs[i]
+ local filename = found .. "/" .. basename
+ local codeblob = loadfile(filename)
+ if codeblob then
+ package.preload[basename] = codeblob() or true
+ end
+ end
+ end
+end
+
+if not unicode then
+ load_libs()
+end
+
+local merger = utilities and utilities.merger
+
+if not merger then
+ return
+end
+
+local arguments = environment.arguments
+local files = environment.files
+
+if environment.ownname ~= "mtxlibs.lua" then
+ return
+end
+
+local helpinfo = [[
+usage: mtxlibs [options]
+
+--merge
+--merge targetfile extralibs
+--selfclean
+
+and in a lua file:
+
+require("mtxlibs")
+]]
+
+local application = logs.application {
+ name = "mtxlibs",
+ banner = "ConTeXt Basic Lua Libraries 1.00",
+ helpinfo = helpinfo,
+}
+
+local report = application.report
+
+if arguments.selfmerge then
+
+ report("merging libraries")
+ local found = locate_libs()
+ if found then
+ local target = files[1]
+ if target == ownname then
+ report("target cannot be this file")
+ return
+ elseif target then
+ report("target: %s",target)
+ for i=1,#files do
+ ownlibs[#ownlibs+1] = file.addsuffix(files[i],"lua")
+ end
+ end
+ merger.selfmerge(ownname,ownlibs,{ found },target)
+ report("done")
+ else
+ report("no libraries found")
+ end
+
+elseif arguments.selfclean then
+
+ report("cleaning libraries")
+ merger.selfclean(ownname)
+ report("done")
+
+elseif arguments.help or files[1] == "help" then
+
+ application.help()
+
+end
diff --git a/Master/texmf-dist/scripts/context/lua/mtxrun.lua b/Master/texmf-dist/scripts/context/lua/mtxrun.lua
index 108f2a8a112..00f63a5791d 100755
--- a/Master/texmf-dist/scripts/context/lua/mtxrun.lua
+++ b/Master/texmf-dist/scripts/context/lua/mtxrun.lua
@@ -1,5 +1,16 @@
#!/usr/bin/env texlua
+-- for k, v in next, _G.string do
+-- local tv = type(v)
+-- if tv == "table" then
+-- for kk, vv in next, v do
+-- print(k,kk,vv)
+-- end
+-- else
+-- print(tv,k,v)
+-- end
+-- end
+
if not modules then modules = { } end modules ['mtxrun'] = {
version = 1.001,
comment = "runner, lua replacement for texmfstart.rb",
@@ -43,3016 +54,7333 @@ if not modules then modules = { } end modules ['mtxrun'] = {
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-string'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
+package.loaded["l-lua"] = package.loaded["l-lua"] or true
+
+-- original size: 10048, stripped down to: 5684
+
+if not modules then modules={} end modules ['l-lua']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local major,minor=string.match(_VERSION,"^[^%d]+(%d+)%.(%d+).*$")
+_MAJORVERSION=tonumber(major) or 5
+_MINORVERSION=tonumber(minor) or 1
+_LUAVERSION=_MAJORVERSION+_MINORVERSION/10
+if not lpeg then
+ lpeg=require("lpeg")
+end
+if loadstring then
+ local loadnormal=load
+ function load(first,...)
+ if type(first)=="string" then
+ return loadstring(first,...)
+ else
+ return loadnormal(first,...)
+ end
+ end
+else
+ loadstring=load
+end
+if not ipairs then
+ local function iterate(a,i)
+ i=i+1
+ local v=a[i]
+ if v~=nil then
+ return i,v
+ end
+ end
+ function ipairs(a)
+ return iterate,a,0
+ end
+end
+if not pairs then
+ function pairs(t)
+ return next,t
+ end
+end
+if not table.unpack then
+ table.unpack=_G.unpack
+elseif not unpack then
+ _G.unpack=table.unpack
+end
+if not package.loaders then
+ package.loaders=package.searchers
+end
+local print,select,tostring=print,select,tostring
+local inspectors={}
+function setinspector(inspector)
+ inspectors[#inspectors+1]=inspector
+end
+function inspect(...)
+ for s=1,select("#",...) do
+ local value=select(s,...)
+ local done=false
+ for i=1,#inspectors do
+ done=inspectors[i](value)
+ if done then
+ break
+ end
+ end
+ if not done then
+ print(tostring(value))
+ end
+ end
+end
+local dummy=function() end
+function optionalrequire(...)
+ local ok,result=xpcall(require,dummy,...)
+ if ok then
+ return result
+ end
+end
+local type=type
+local gsub,format=string.gsub,string.format
+local package=package
+local searchers=package.searchers or package.loaders
+local libpaths=nil
+local clibpaths=nil
+local libhash={}
+local clibhash={}
+local libextras={}
+local clibextras={}
+local filejoin=file and file.join or function(path,name) return path.."/"..name end
+local isreadable=file and file.is_readable or function(name) local f=io.open(name) if f then f:close() return true end end
+local addsuffix=file and file.addsuffix or function(name,suffix) return name.."."..suffix end
+local function cleanpath(path)
+ return path
+end
+local helpers=package.helpers or {
+ libpaths=function() return {} end,
+ clibpaths=function() return {} end,
+ cleanpath=cleanpath,
+ trace=false,
+ report=function(...) print(format(...)) end,
}
+package.helpers=helpers
+local function getlibpaths()
+ return libpaths or helpers.libpaths(libhash)
+end
+local function getclibpaths()
+ return clibpaths or helpers.clibpaths(clibhash)
+end
+package.libpaths=getlibpaths
+package.clibpaths=getclibpaths
+local function addpath(what,paths,extras,hash,...)
+ local pathlist={... }
+ local cleanpath=helpers.cleanpath
+ local trace=helpers.trace
+ local report=helpers.report
+ local function add(path)
+ local path=cleanpath(path)
+ if not hash[path] then
+ if trace then
+ report("extra %s path: %s",what,path)
+ end
+ paths [#paths+1]=path
+ extras[#extras+1]=path
+ end
+ end
+ for p=1,#pathlist do
+ local path=pathlist[p]
+ if type(path)=="table" then
+ for i=1,#path do
+ add(path[i])
+ end
+ else
+ add(path)
+ end
+ end
+ return paths,extras
+end
+function package.extralibpath(...)
+ libpaths,libextras=addpath("lua",getlibpaths(),libextras,libhash,...)
+end
+function package.extraclibpath(...)
+ clibpaths,clibextras=addpath("lib",getclibpaths(),clibextras,clibhash,...)
+end
+if not searchers[-2] then
+ searchers[-2]=searchers[2]
+end
+searchers[2]=function(name)
+ return helpers.loaded(name)
+end
+searchers[3]=nil
+local function loadedaslib(resolved,rawname)
+ local init="luaopen_"..gsub(rawname,"%.","_")
+ if helpers.trace then
+ helpers.report("calling loadlib with '%s' with init '%s'",resolved,init)
+ end
+ return package.loadlib(resolved,init)
+end
+local function loadedbylua(name)
+ if helpers.trace then
+ helpers.report("locating '%s' using normal loader",name)
+ end
+ return true,searchers[-2](name)
+end
+local function loadedbypath(name,rawname,paths,islib,what)
+ local trace=helpers.trace
+ local report=helpers.report
+ if trace then
+ report("locating '%s' as '%s' on '%s' paths",rawname,name,what)
+ end
+ for p=1,#paths do
+ local path=paths[p]
+ local resolved=filejoin(path,name)
+ if trace then
+ report("checking for '%s' using '%s' path '%s'",name,what,path)
+ end
+ if isreadable(resolved) then
+ if trace then
+ report("lib '%s' located on '%s'",name,resolved)
+ end
+ if islib then
+ return true,loadedaslib(resolved,rawname)
+ else
+ return true,loadfile(resolved)
+ end
+ end
+ end
+end
+local function notloaded(name)
+ if helpers.trace then
+ helpers.report("? unable to locate library '%s'",name)
+ end
+end
+helpers.loadedaslib=loadedaslib
+helpers.loadedbylua=loadedbylua
+helpers.loadedbypath=loadedbypath
+helpers.notloaded=notloaded
+function helpers.loaded(name)
+ local thename=gsub(name,"%.","/")
+ local luaname=addsuffix(thename,"lua")
+ local libname=addsuffix(thename,os.libsuffix or "so")
+ local libpaths=getlibpaths()
+ local clibpaths=getclibpaths()
+ local done,result=loadedbypath(luaname,name,libpaths,false,"lua")
+ if done then
+ return result
+ end
+ local done,result=loadedbypath(luaname,name,clibpaths,false,"lua")
+ if done then
+ return result
+ end
+ local done,result=loadedbypath(libname,name,clibpaths,true,"lib")
+ if done then
+ return result
+ end
+ local done,result=loadedbylua(name)
+ if done then
+ return result
+ end
+ return notloaded(name)
+end
-local string = string
-local sub, gsub, find, match, gmatch, format, char, byte, rep, lower = string.sub, string.gsub, string.find, string.match, string.gmatch, string.format, string.char, string.byte, string.rep, string.lower
-local lpegmatch, S, C, Ct = lpeg.match, lpeg.S, lpeg.C, lpeg.Ct
--- some functions may disappear as they are not used anywhere
+end -- of closure
-if not string.split then
+do -- create closure to overcome 200 locals limit
- -- this will be overloaded by a faster lpeg variant
+package.loaded["l-lpeg"] = package.loaded["l-lpeg"] or true
- function string.split(str,pattern)
- local t = { }
- if #str > 0 then
- local n = 1
- for s in gmatch(str..pattern,"(.-)"..pattern) do
- t[n] = s
- n = n + 1
- end
- end
- return t
- end
+-- original size: 26252, stripped down to: 14371
+if not modules then modules={} end modules ['l-lpeg']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+lpeg=require("lpeg")
+local type,next,tostring=type,next,tostring
+local byte,char,gmatch,format=string.byte,string.char,string.gmatch,string.format
+local floor=math.floor
+local P,R,S,V,Ct,C,Cs,Cc,Cp,Cmt=lpeg.P,lpeg.R,lpeg.S,lpeg.V,lpeg.Ct,lpeg.C,lpeg.Cs,lpeg.Cc,lpeg.Cp,lpeg.Cmt
+local lpegtype,lpegmatch,lpegprint=lpeg.type,lpeg.match,lpeg.print
+setinspector(function(v) if lpegtype(v) then lpegprint(v) return true end end)
+lpeg.patterns=lpeg.patterns or {}
+local patterns=lpeg.patterns
+local anything=P(1)
+local endofstring=P(-1)
+local alwaysmatched=P(true)
+patterns.anything=anything
+patterns.endofstring=endofstring
+patterns.beginofstring=alwaysmatched
+patterns.alwaysmatched=alwaysmatched
+local digit,sign=R('09'),S('+-')
+local cr,lf,crlf=P("\r"),P("\n"),P("\r\n")
+local newline=crlf+S("\r\n")
+local escaped=P("\\")*anything
+local squote=P("'")
+local dquote=P('"')
+local space=P(" ")
+local utfbom_32_be=P('\000\000\254\255')
+local utfbom_32_le=P('\255\254\000\000')
+local utfbom_16_be=P('\255\254')
+local utfbom_16_le=P('\254\255')
+local utfbom_8=P('\239\187\191')
+local utfbom=utfbom_32_be+utfbom_32_le+utfbom_16_be+utfbom_16_le+utfbom_8
+local utftype=utfbom_32_be*Cc("utf-32-be")+utfbom_32_le*Cc("utf-32-le")+utfbom_16_be*Cc("utf-16-be")+utfbom_16_le*Cc("utf-16-le")+utfbom_8*Cc("utf-8")+alwaysmatched*Cc("utf-8")
+local utfoffset=utfbom_32_be*Cc(4)+utfbom_32_le*Cc(4)+utfbom_16_be*Cc(2)+utfbom_16_le*Cc(2)+utfbom_8*Cc(3)+Cc(0)
+local utf8next=R("\128\191")
+patterns.utf8one=R("\000\127")
+patterns.utf8two=R("\194\223")*utf8next
+patterns.utf8three=R("\224\239")*utf8next*utf8next
+patterns.utf8four=R("\240\244")*utf8next*utf8next*utf8next
+patterns.utfbom=utfbom
+patterns.utftype=utftype
+patterns.utfoffset=utfoffset
+local utf8char=patterns.utf8one+patterns.utf8two+patterns.utf8three+patterns.utf8four
+local validutf8char=utf8char^0*endofstring*Cc(true)+Cc(false)
+local utf8character=P(1)*R("\128\191")^0
+patterns.utf8=utf8char
+patterns.utf8char=utf8char
+patterns.utf8character=utf8character
+patterns.validutf8=validutf8char
+patterns.validutf8char=validutf8char
+local eol=S("\n\r")
+local spacer=S(" \t\f\v")
+local whitespace=eol+spacer
+local nonspacer=1-spacer
+local nonwhitespace=1-whitespace
+patterns.eol=eol
+patterns.spacer=spacer
+patterns.whitespace=whitespace
+patterns.nonspacer=nonspacer
+patterns.nonwhitespace=nonwhitespace
+local stripper=spacer^0*C((spacer^0*nonspacer^1)^0)
+local collapser=Cs(spacer^0/""*nonspacer^0*((spacer^0/" "*nonspacer^1)^0))
+patterns.stripper=stripper
+patterns.collapser=collapser
+patterns.digit=digit
+patterns.sign=sign
+patterns.cardinal=sign^0*digit^1
+patterns.integer=sign^0*digit^1
+patterns.unsigned=digit^0*P('.')*digit^1
+patterns.float=sign^0*patterns.unsigned
+patterns.cunsigned=digit^0*P(',')*digit^1
+patterns.cfloat=sign^0*patterns.cunsigned
+patterns.number=patterns.float+patterns.integer
+patterns.cnumber=patterns.cfloat+patterns.integer
+patterns.oct=P("0")*R("07")^1
+patterns.octal=patterns.oct
+patterns.HEX=P("0x")*R("09","AF")^1
+patterns.hex=P("0x")*R("09","af")^1
+patterns.hexadecimal=P("0x")*R("09","AF","af")^1
+patterns.lowercase=R("az")
+patterns.uppercase=R("AZ")
+patterns.letter=patterns.lowercase+patterns.uppercase
+patterns.space=space
+patterns.tab=P("\t")
+patterns.spaceortab=patterns.space+patterns.tab
+patterns.newline=newline
+patterns.emptyline=newline^1
+patterns.equal=P("=")
+patterns.comma=P(",")
+patterns.commaspacer=P(",")*spacer^0
+patterns.period=P(".")
+patterns.colon=P(":")
+patterns.semicolon=P(";")
+patterns.underscore=P("_")
+patterns.escaped=escaped
+patterns.squote=squote
+patterns.dquote=dquote
+patterns.nosquote=(escaped+(1-squote))^0
+patterns.nodquote=(escaped+(1-dquote))^0
+patterns.unsingle=(squote/"")*patterns.nosquote*(squote/"")
+patterns.undouble=(dquote/"")*patterns.nodquote*(dquote/"")
+patterns.unquoted=patterns.undouble+patterns.unsingle
+patterns.unspacer=((patterns.spacer^1)/"")^0
+patterns.singlequoted=squote*patterns.nosquote*squote
+patterns.doublequoted=dquote*patterns.nodquote*dquote
+patterns.quoted=patterns.doublequoted+patterns.singlequoted
+patterns.propername=R("AZ","az","__")*R("09","AZ","az","__")^0*P(-1)
+patterns.somecontent=(anything-newline-space)^1
+patterns.beginline=#(1-newline)
+patterns.longtostring=Cs(whitespace^0/""*nonwhitespace^0*((whitespace^0/" "*(patterns.quoted+nonwhitespace)^1)^0))
+local function anywhere(pattern)
+ return P { P(pattern)+1*V(1) }
+end
+lpeg.anywhere=anywhere
+function lpeg.instringchecker(p)
+ p=anywhere(p)
+ return function(str)
+ return lpegmatch(p,str) and true or false
+ end
+end
+function lpeg.splitter(pattern,action)
+ return (((1-P(pattern))^1)/action+1)^0
+end
+function lpeg.tsplitter(pattern,action)
+ return Ct((((1-P(pattern))^1)/action+1)^0)
+end
+local splitters_s,splitters_m,splitters_t={},{},{}
+local function splitat(separator,single)
+ local splitter=(single and splitters_s[separator]) or splitters_m[separator]
+ if not splitter then
+ separator=P(separator)
+ local other=C((1-separator)^0)
+ if single then
+ local any=anything
+ splitter=other*(separator*C(any^0)+"")
+ splitters_s[separator]=splitter
+ else
+ splitter=other*(separator*other)^0
+ splitters_m[separator]=splitter
+ end
+ end
+ return splitter
end
-
-function string.unquoted(str)
- return (gsub(str,"^([\"\'])(.*)%1$","%2"))
+local function tsplitat(separator)
+ local splitter=splitters_t[separator]
+ if not splitter then
+ splitter=Ct(splitat(separator))
+ splitters_t[separator]=splitter
+ end
+ return splitter
+end
+lpeg.splitat=splitat
+lpeg.tsplitat=tsplitat
+function string.splitup(str,separator)
+ if not separator then
+ separator=","
+ end
+ return lpegmatch(splitters_m[separator] or splitat(separator),str)
end
-
-
-function string.quoted(str)
- return format("%q",str) -- always "
+local cache={}
+function lpeg.split(separator,str)
+ local c=cache[separator]
+ if not c then
+ c=tsplitat(separator)
+ cache[separator]=c
+ end
+ return lpegmatch(c,str)
end
-
-function string.count(str,pattern) -- variant 3
- local n = 0
- for _ in gmatch(str,pattern) do -- not for utf
- n = n + 1
+function string.split(str,separator)
+ if separator then
+ local c=cache[separator]
+ if not c then
+ c=tsplitat(separator)
+ cache[separator]=c
+ end
+ return lpegmatch(c,str)
+ else
+ return { str }
+ end
+end
+local spacing=patterns.spacer^0*newline
+local empty=spacing*Cc("")
+local nonempty=Cs((1-spacing)^1)*spacing^-1
+local content=(empty+nonempty)^1
+patterns.textline=content
+local linesplitter=tsplitat(newline)
+patterns.linesplitter=linesplitter
+function string.splitlines(str)
+ return lpegmatch(linesplitter,str)
+end
+local cache={}
+function lpeg.checkedsplit(separator,str)
+ local c=cache[separator]
+ if not c then
+ separator=P(separator)
+ local other=C((1-separator)^1)
+ c=Ct(separator^0*other*(separator^1*other)^0)
+ cache[separator]=c
+ end
+ return lpegmatch(c,str)
+end
+function string.checkedsplit(str,separator)
+ local c=cache[separator]
+ if not c then
+ separator=P(separator)
+ local other=C((1-separator)^1)
+ c=Ct(separator^0*other*(separator^1*other)^0)
+ cache[separator]=c
+ end
+ return lpegmatch(c,str)
+end
+local function f2(s) local c1,c2=byte(s,1,2) return c1*64+c2-12416 end
+local function f3(s) local c1,c2,c3=byte(s,1,3) return (c1*64+c2)*64+c3-925824 end
+local function f4(s) local c1,c2,c3,c4=byte(s,1,4) return ((c1*64+c2)*64+c3)*64+c4-63447168 end
+local utf8byte=patterns.utf8one/byte+patterns.utf8two/f2+patterns.utf8three/f3+patterns.utf8four/f4
+patterns.utf8byte=utf8byte
+local cache={}
+function lpeg.stripper(str)
+ if type(str)=="string" then
+ local s=cache[str]
+ if not s then
+ s=Cs(((S(str)^1)/""+1)^0)
+ cache[str]=s
end
- return n
+ return s
+ else
+ return Cs(((str^1)/""+1)^0)
+ end
end
-
-function string.limit(str,n,sentinel) -- not utf proof
- if #str > n then
- sentinel = sentinel or "..."
- return sub(str,1,(n-#sentinel)) .. sentinel
+local cache={}
+function lpeg.keeper(str)
+ if type(str)=="string" then
+ local s=cache[str]
+ if not s then
+ s=Cs((((1-S(str))^1)/""+1)^0)
+ cache[str]=s
+ end
+ return s
+ else
+ return Cs((((1-str)^1)/""+1)^0)
+ end
+end
+function lpeg.frontstripper(str)
+ return (P(str)+P(true))*Cs(anything^0)
+end
+function lpeg.endstripper(str)
+ return Cs((1-P(str)*endofstring)^0)
+end
+function lpeg.replacer(one,two,makefunction,isutf)
+ local pattern
+ local u=isutf and utf8char or 1
+ if type(one)=="table" then
+ local no=#one
+ local p=P(false)
+ if no==0 then
+ for k,v in next,one do
+ p=p+P(k)/v
+ end
+ pattern=Cs((p+u)^0)
+ elseif no==1 then
+ local o=one[1]
+ one,two=P(o[1]),o[2]
+ pattern=Cs((one/two+u)^0)
+ else
+ for i=1,no do
+ local o=one[i]
+ p=p+P(o[1])/o[2]
+ end
+ pattern=Cs((p+u)^0)
+ end
+ else
+ pattern=Cs((P(one)/(two or "")+u)^0)
+ end
+ if makefunction then
+ return function(str)
+ return lpegmatch(pattern,str)
+ end
+ else
+ return pattern
+ end
+end
+function lpeg.finder(lst,makefunction)
+ local pattern
+ if type(lst)=="table" then
+ pattern=P(false)
+ if #lst==0 then
+ for k,v in next,lst do
+ pattern=pattern+P(k)
+ end
else
- return str
+ for i=1,#lst do
+ pattern=pattern+P(lst[i])
+ end
+ end
+ else
+ pattern=P(lst)
+ end
+ pattern=(1-pattern)^0*pattern
+ if makefunction then
+ return function(str)
+ return lpegmatch(pattern,str)
+ end
+ else
+ return pattern
+ end
+end
+local splitters_f,splitters_s={},{}
+function lpeg.firstofsplit(separator)
+ local splitter=splitters_f[separator]
+ if not splitter then
+ separator=P(separator)
+ splitter=C((1-separator)^0)
+ splitters_f[separator]=splitter
+ end
+ return splitter
+end
+function lpeg.secondofsplit(separator)
+ local splitter=splitters_s[separator]
+ if not splitter then
+ separator=P(separator)
+ splitter=(1-separator)^0*separator*C(anything^0)
+ splitters_s[separator]=splitter
+ end
+ return splitter
+end
+function lpeg.balancer(left,right)
+ left,right=P(left),P(right)
+ return P { left*((1-left-right)+V(1))^0*right }
+end
+local nany=utf8char/""
+function lpeg.counter(pattern)
+ pattern=Cs((P(pattern)/" "+nany)^0)
+ return function(str)
+ return #lpegmatch(pattern,str)
+ end
+end
+utf=utf or (unicode and unicode.utf8) or {}
+local utfcharacters=utf and utf.characters or string.utfcharacters
+local utfgmatch=utf and utf.gmatch
+local utfchar=utf and utf.char
+lpeg.UP=lpeg.P
+if utfcharacters then
+ function lpeg.US(str)
+ local p=P(false)
+ for uc in utfcharacters(str) do
+ p=p+P(uc)
+ end
+ return p
+ end
+elseif utfgmatch then
+ function lpeg.US(str)
+ local p=P(false)
+ for uc in utfgmatch(str,".") do
+ p=p+P(uc)
+ end
+ return p
+ end
+else
+ function lpeg.US(str)
+ local p=P(false)
+ local f=function(uc)
+ p=p+P(uc)
end
+ lpegmatch((utf8char/f)^0,str)
+ return p
+ end
end
-
-local space = S(" \t\v\n")
-local nospace = 1 - space
-local stripper = space^0 * C((space^0 * nospace^1)^0) -- roberto's code
-
-function string.strip(str)
- return lpegmatch(stripper,str) or ""
+local range=utf8byte*utf8byte+Cc(false)
+function lpeg.UR(str,more)
+ local first,last
+ if type(str)=="number" then
+ first=str
+ last=more or first
+ else
+ first,last=lpegmatch(range,str)
+ if not last then
+ return P(str)
+ end
+ end
+ if first==last then
+ return P(str)
+ elseif utfchar and (last-first<8) then
+ local p=P(false)
+ for i=first,last do
+ p=p+P(utfchar(i))
+ end
+ return p
+ else
+ local f=function(b)
+ return b>=first and b<=last
+ end
+ return utf8byte/f
+ end
end
-
-function string.is_empty(str)
- return not find(str,"%S")
+function lpeg.is_lpeg(p)
+ return p and lpegtype(p)=="pattern"
+end
+function lpeg.oneof(list,...)
+ if type(list)~="table" then
+ list={ list,... }
+ end
+ local p=P(list[1])
+ for l=2,#list do
+ p=p+P(list[l])
+ end
+ return p
+end
+local sort=table.sort
+local function copyindexed(old)
+ local new={}
+ for i=1,#old do
+ new[i]=old
+ end
+ return new
end
-
-local patterns_escapes = {
- ["%"] = "%%",
- ["."] = "%.",
- ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
- ["["] = "%[", ["]"] = "%]",
- ["("] = "%(", [")"] = "%)",
- -- ["{"] = "%{", ["}"] = "%}"
- -- ["^"] = "%^", ["$"] = "%$",
-}
-
-local simple_escapes = {
- ["-"] = "%-",
- ["."] = "%.",
- ["?"] = ".",
- ["*"] = ".*",
-}
-
-function string.escapedpattern(str,simple)
- return (gsub(str,".",simple and simple_escapes or patterns_escapes))
+local function sortedkeys(tab)
+ local keys,s={},0
+ for key,_ in next,tab do
+ s=s+1
+ keys[s]=key
+ end
+ sort(keys)
+ return keys
end
-
-function string.topattern(str,lowercase,strict)
- if str == "" then
- return ".*"
+function lpeg.append(list,pp,delayed,checked)
+ local p=pp
+ if #list>0 then
+ local keys=copyindexed(list)
+ sort(keys)
+ for i=#keys,1,-1 do
+ local k=keys[i]
+ if p then
+ p=P(k)+p
+ else
+ p=P(k)
+ end
+ end
+ elseif delayed then
+ local keys=sortedkeys(list)
+ if p then
+ for i=1,#keys,1 do
+ local k=keys[i]
+ local v=list[k]
+ p=P(k)/list+p
+ end
else
- str = gsub(str,".",simple_escapes)
- if lowercase then
- str = lower(str)
+ for i=1,#keys do
+ local k=keys[i]
+ local v=list[k]
+ if p then
+ p=P(k)+p
+ else
+ p=P(k)
+ end
+ end
+ if p then
+ p=p/list
+ end
+ end
+ elseif checked then
+ local keys=sortedkeys(list)
+ for i=1,#keys do
+ local k=keys[i]
+ local v=list[k]
+ if p then
+ if k==v then
+ p=P(k)+p
+ else
+ p=P(k)/v+p
end
- if strict then
- return "^" .. str .. "$"
+ else
+ if k==v then
+ p=P(k)
else
- return str
+ p=P(k)/v
end
+ end
+ end
+ else
+ local keys=sortedkeys(list)
+ for i=1,#keys do
+ local k=keys[i]
+ local v=list[k]
+ if p then
+ p=P(k)/v+p
+ else
+ p=P(k)/v
+ end
end
+ end
+ return p
end
-
--- obsolete names:
-
-string.quote = string.quoted
-string.unquote = string.unquoted
+local function make(t)
+ local p
+ local keys=sortedkeys(t)
+ for i=1,#keys do
+ local k=keys[i]
+ local v=t[k]
+ if not p then
+ if next(v) then
+ p=P(k)*make(v)
+ else
+ p=P(k)
+ end
+ else
+ if next(v) then
+ p=p+P(k)*make(v)
+ else
+ p=p+P(k)
+ end
+ end
+ end
+ return p
+end
+function lpeg.utfchartabletopattern(list)
+ local tree={}
+ for i=1,#list do
+ local t=tree
+ for c in gmatch(list[i],".") do
+ if not t[c] then
+ t[c]={}
+ end
+ t=t[c]
+ end
+ end
+ return make(tree)
+end
+patterns.containseol=lpeg.finder(eol)
+local function nextstep(n,step,result)
+ local m=n%step
+ local d=floor(n/step)
+ if d>0 then
+ local v=V(tostring(step))
+ local s=result.start
+ for i=1,d do
+ if s then
+ s=v*s
+ else
+ s=v
+ end
+ end
+ result.start=s
+ end
+ if step>1 and result.start then
+ local v=V(tostring(step/2))
+ result[tostring(step)]=v*v
+ end
+ if step>0 then
+ return nextstep(m,step/2,result)
+ else
+ return result
+ end
+end
+function lpeg.times(pattern,n)
+ return P(nextstep(n,2^16,{ "start",["1"]=pattern }))
+end
+local digit=R("09")
+local period=P(".")
+local zero=P("0")
+local trailingzeros=zero^0*-digit
+local case_1=period*trailingzeros/""
+local case_2=period*(digit-trailingzeros)^1*(trailingzeros/"")
+local number=digit^1*(case_1+case_2)
+local stripper=Cs((number+1)^0)
+lpeg.patterns.stripzeros=stripper
end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-table'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local type, next, tostring, tonumber, ipairs, table, string = type, next, tostring, tonumber, ipairs, table, string
-local concat, sort, insert, remove = table.concat, table.sort, table.insert, table.remove
-local format, find, gsub, lower, dump, match = string.format, string.find, string.gsub, string.lower, string.dump, string.match
-local getmetatable, setmetatable = getmetatable, setmetatable
-local getinfo = debug.getinfo
+package.loaded["l-function"] = package.loaded["l-function"] or true
--- Starting with version 5.2 Lua no longer provide ipairs, which makes
--- sense. As we already used the for loop and # in most places the
--- impact on ConTeXt was not that large; the remaining ipairs already
--- have been replaced. In a similar fashion we also hardly used pairs.
---
--- Just in case, we provide the fallbacks as discussed in Programming
--- in Lua (http://www.lua.org/pil/7.3.html):
+-- original size: 361, stripped down to: 322
-if not ipairs then
+if not modules then modules={} end modules ['l-functions']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+functions=functions or {}
+function functions.dummy() end
- -- for k, v in ipairs(t) do ... end
- -- for k=1,#t do local v = t[k] ... end
- local function iterate(a,i)
- i = i + 1
- local v = a[i]
- if v ~= nil then
- return i, v --, nil
- end
- end
+end -- of closure
- function ipairs(a)
- return iterate, a, 0
- end
+do -- create closure to overcome 200 locals limit
-end
+package.loaded["l-string"] = package.loaded["l-string"] or true
-if not pairs then
+-- original size: 5513, stripped down to: 2708
- -- for k, v in pairs(t) do ... end
- -- for k, v in next, t do ... end
+if not modules then modules={} end modules ['l-string']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local string=string
+local sub,gmatch,format,char,byte,rep,lower=string.sub,string.gmatch,string.format,string.char,string.byte,string.rep,string.lower
+local lpegmatch,patterns=lpeg.match,lpeg.patterns
+local P,S,C,Ct,Cc,Cs=lpeg.P,lpeg.S,lpeg.C,lpeg.Ct,lpeg.Cc,lpeg.Cs
+local unquoted=patterns.squote*C(patterns.nosquote)*patterns.squote+patterns.dquote*C(patterns.nodquote)*patterns.dquote
+function string.unquoted(str)
+ return lpegmatch(unquoted,str) or str
+end
+function string.quoted(str)
+ return format("%q",str)
+end
+function string.count(str,pattern)
+ local n=0
+ for _ in gmatch(str,pattern) do
+ n=n+1
+ end
+ return n
+end
+function string.limit(str,n,sentinel)
+ if #str>n then
+ sentinel=sentinel or "..."
+ return sub(str,1,(n-#sentinel))..sentinel
+ else
+ return str
+ end
+end
+local stripper=patterns.stripper
+local collapser=patterns.collapser
+local longtostring=patterns.longtostring
+function string.strip(str)
+ return lpegmatch(stripper,str) or ""
+end
+function string.collapsespaces(str)
+ return lpegmatch(collapser,str) or ""
+end
+function string.longtostring(str)
+ return lpegmatch(longtostring,str) or ""
+end
+local pattern=P(" ")^0*P(-1)
+function string.is_empty(str)
+ if str=="" then
+ return true
+ else
+ return lpegmatch(pattern,str) and true or false
+ end
+end
+local anything=patterns.anything
+local allescapes=Cc("%")*S(".-+%?()[]*")
+local someescapes=Cc("%")*S(".-+%()[]")
+local matchescapes=Cc(".")*S("*?")
+local pattern_a=Cs ((allescapes+anything )^0 )
+local pattern_b=Cs ((someescapes+matchescapes+anything )^0 )
+local pattern_c=Cs (Cc("^")*(someescapes+matchescapes+anything )^0*Cc("$") )
+function string.escapedpattern(str,simple)
+ return lpegmatch(simple and pattern_b or pattern_a,str)
+end
+function string.topattern(str,lowercase,strict)
+ if str=="" or type(str)~="string" then
+ return ".*"
+ elseif strict then
+ str=lpegmatch(pattern_c,str)
+ else
+ str=lpegmatch(pattern_b,str)
+ end
+ if lowercase then
+ return lower(str)
+ else
+ return str
+ end
+end
+function string.valid(str,default)
+ return (type(str)=="string" and str~="" and str) or default or nil
+end
+string.itself=function(s) return s end
+local pattern=Ct(C(1)^0)
+function string.totable(str)
+ return lpegmatch(pattern,str)
+end
+local replacer=lpeg.replacer("@","%%")
+function string.tformat(fmt,...)
+ return format(lpegmatch(replacer,fmt),...)
+end
+string.quote=string.quoted
+string.unquote=string.unquoted
- function pairs(t)
- return next, t -- , nil
- end
-end
+end -- of closure
--- Also, unpack has been moved to the table table, and for compatiility
--- reasons we provide both now.
+do -- create closure to overcome 200 locals limit
-if not table.unpack then
- table.unpack = _G.unpack
-elseif not unpack then
- _G.unpack = table.unpack
-end
+package.loaded["l-table"] = package.loaded["l-table"] or true
--- extra functions, some might go (when not used)
+-- original size: 44643, stripped down to: 19717
+if not modules then modules={} end modules ['l-table']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local type,next,tostring,tonumber,ipairs,select=type,next,tostring,tonumber,ipairs,select
+local table,string=table,string
+local concat,sort,insert,remove=table.concat,table.sort,table.insert,table.remove
+local format,lower,dump=string.format,string.lower,string.dump
+local getmetatable,setmetatable=getmetatable,setmetatable
+local getinfo=debug.getinfo
+local lpegmatch,patterns=lpeg.match,lpeg.patterns
+local floor=math.floor
+local stripper=patterns.stripper
function table.strip(tab)
- local lst, l = { }, 0
- for i=1,#tab do
- local s = gsub(tab[i],"^%s*(.-)%s*$","%1")
- if s == "" then
- -- skip this one
- else
- l = l + 1
- lst[l] = s
- end
+ local lst,l={},0
+ for i=1,#tab do
+ local s=lpegmatch(stripper,tab[i]) or ""
+ if s=="" then
+ else
+ l=l+1
+ lst[l]=s
end
- return lst
+ end
+ return lst
end
-
function table.keys(t)
- local keys, k = { }, 0
- for key, _ in next, t do
- k = k + 1
- keys[k] = key
+ if t then
+ local keys,k={},0
+ for key,_ in next,t do
+ k=k+1
+ keys[k]=key
end
return keys
+ else
+ return {}
+ end
end
-
local function compare(a,b)
- local ta, tb = type(a), type(b) -- needed, else 11 < 2
- if ta == tb then
- return a < b
- else
- return tostring(a) < tostring(b)
- end
+ local ta,tb=type(a),type(b)
+ if ta==tb then
+ return a0 then
+ local n=0
+ for _,v in next,t do
+ n=n+1
+ end
+ if n==#t then
+ local tt,nt={},0
+ for i=1,#t do
+ local v=t[i]
+ local tv=type(v)
+ if tv=="number" then
+ nt=nt+1
+ if hexify then
+ tt[nt]=format("0x%04X",v)
+ else
+ tt[nt]=tostring(v)
+ end
+ elseif tv=="boolean" then
+ nt=nt+1
+ tt[nt]=tostring(v)
+ elseif tv=="string" then
+ nt=nt+1
+ tt[nt]=format("%q",v)
+ else
+ tt=nil
+ break
end
+ end
+ return tt
end
- return tmp
+ end
+ return nil
end
-
-local function fastcopy(old,metatabletoo) -- fast one
- if old then
- local new = { }
- for k,v in next, old do
- if type(v) == "table" then
- new[k] = fastcopy(v,metatabletoo) -- was just table.copy
- else
- new[k] = v
- end
+local propername=patterns.propername
+local function dummy() end
+local function do_serialize(root,name,depth,level,indexed)
+ if level>0 then
+ depth=depth.." "
+ if indexed then
+ handle(format("%s{",depth))
+ else
+ local tn=type(name)
+ if tn=="number" then
+ if hexify then
+ handle(format("%s[0x%04X]={",depth,name))
+ else
+ handle(format("%s[%s]={",depth,name))
end
- if metatabletoo then
- -- optional second arg
- local mt = getmetatable(old)
- if mt then
- setmetatable(new,mt)
+ elseif tn=="string" then
+ if noquotes and not reserved[name] and lpegmatch(propername,name) then
+ handle(format("%s%s={",depth,name))
+ else
+ handle(format("%s[%q]={",depth,name))
+ end
+ elseif tn=="boolean" then
+ handle(format("%s[%s]={",depth,tostring(name)))
+ else
+ handle(format("%s{",depth))
+ end
+ end
+ end
+ if root and next(root) then
+ local first,last=nil,0
+ if compact then
+ last=#root
+ for k=1,last do
+ if root[k]==nil then
+ last=k-1
+ break
+ end
+ end
+ if last>0 then
+ first=1
+ end
+ end
+ local sk=sortedkeys(root)
+ for i=1,#sk do
+ local k=sk[i]
+ local v=root[k]
+ local t,tk=type(v),type(k)
+ if compact and first and tk=="number" and k>=first and k<=last then
+ if t=="number" then
+ if hexify then
+ handle(format("%s 0x%04X,",depth,v))
+ else
+ handle(format("%s %s,",depth,v))
+ end
+ elseif t=="string" then
+ if reduce and tonumber(v) then
+ handle(format("%s %s,",depth,v))
+ else
+ handle(format("%s %q,",depth,v))
+ end
+ elseif t=="table" then
+ if not next(v) then
+ handle(format("%s {},",depth))
+ elseif inline then
+ local st=simple_table(v)
+ if st then
+ handle(format("%s { %s },",depth,concat(st,", ")))
+ else
+ do_serialize(v,k,depth,level+1,true)
+ end
+ else
+ do_serialize(v,k,depth,level+1,true)
+ end
+ elseif t=="boolean" then
+ handle(format("%s %s,",depth,tostring(v)))
+ elseif t=="function" then
+ if functions then
+ handle(format('%s load(%q),',depth,dump(v)))
+ else
+ handle(format('%s "function",',depth))
+ end
+ else
+ handle(format("%s %q,",depth,tostring(v)))
+ end
+ elseif k=="__p__" then
+ if false then
+ handle(format("%s __p__=nil,",depth))
+ end
+ elseif t=="number" then
+ if tk=="number" then
+ if hexify then
+ handle(format("%s [0x%04X]=0x%04X,",depth,k,v))
+ else
+ handle(format("%s [%s]=%s,",depth,k,v))
+ end
+ elseif tk=="boolean" then
+ if hexify then
+ handle(format("%s [%s]=0x%04X,",depth,tostring(k),v))
+ else
+ handle(format("%s [%s]=%s,",depth,tostring(k),v))
+ end
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
+ if hexify then
+ handle(format("%s %s=0x%04X,",depth,k,v))
+ else
+ handle(format("%s %s=%s,",depth,k,v))
+ end
+ else
+ if hexify then
+ handle(format("%s [%q]=0x%04X,",depth,k,v))
+ else
+ handle(format("%s [%q]=%s,",depth,k,v))
+ end
+ end
+ elseif t=="string" then
+ if reduce and tonumber(v) then
+ if tk=="number" then
+ if hexify then
+ handle(format("%s [0x%04X]=%s,",depth,k,v))
+ else
+ handle(format("%s [%s]=%s,",depth,k,v))
+ end
+ elseif tk=="boolean" then
+ handle(format("%s [%s]=%s,",depth,tostring(k),v))
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
+ handle(format("%s %s=%s,",depth,k,v))
+ else
+ handle(format("%s [%q]=%s,",depth,k,v))
+ end
+ else
+ if tk=="number" then
+ if hexify then
+ handle(format("%s [0x%04X]=%q,",depth,k,v))
+ else
+ handle(format("%s [%s]=%q,",depth,k,v))
+ end
+ elseif tk=="boolean" then
+ handle(format("%s [%s]=%q,",depth,tostring(k),v))
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
+ handle(format("%s %s=%q,",depth,k,v))
+ else
+ handle(format("%s [%q]=%q,",depth,k,v))
+ end
+ end
+ elseif t=="table" then
+ if not next(v) then
+ if tk=="number" then
+ if hexify then
+ handle(format("%s [0x%04X]={},",depth,k))
+ else
+ handle(format("%s [%s]={},",depth,k))
+ end
+ elseif tk=="boolean" then
+ handle(format("%s [%s]={},",depth,tostring(k)))
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
+ handle(format("%s %s={},",depth,k))
+ else
+ handle(format("%s [%q]={},",depth,k))
+ end
+ elseif inline then
+ local st=simple_table(v)
+ if st then
+ if tk=="number" then
+ if hexify then
+ handle(format("%s [0x%04X]={ %s },",depth,k,concat(st,", ")))
+ else
+ handle(format("%s [%s]={ %s },",depth,k,concat(st,", ")))
+ end
+ elseif tk=="boolean" then
+ handle(format("%s [%s]={ %s },",depth,tostring(k),concat(st,", ")))
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
+ handle(format("%s %s={ %s },",depth,k,concat(st,", ")))
+ else
+ handle(format("%s [%q]={ %s },",depth,k,concat(st,", ")))
end
+ else
+ do_serialize(v,k,depth,level+1)
+ end
+ else
+ do_serialize(v,k,depth,level+1)
+ end
+ elseif t=="boolean" then
+ if tk=="number" then
+ if hexify then
+ handle(format("%s [0x%04X]=%s,",depth,k,tostring(v)))
+ else
+ handle(format("%s [%s]=%s,",depth,k,tostring(v)))
+ end
+ elseif tk=="boolean" then
+ handle(format("%s [%s]=%s,",depth,tostring(k),tostring(v)))
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
+ handle(format("%s %s=%s,",depth,k,tostring(v)))
+ else
+ handle(format("%s [%q]=%s,",depth,k,tostring(v)))
end
- return new
+ elseif t=="function" then
+ if functions then
+ local f=getinfo(v).what=="C" and dump(dummy) or dump(v)
+ if tk=="number" then
+ if hexify then
+ handle(format("%s [0x%04X]=load(%q),",depth,k,f))
+ else
+ handle(format("%s [%s]=load(%q),",depth,k,f))
+ end
+ elseif tk=="boolean" then
+ handle(format("%s [%s]=load(%q),",depth,tostring(k),f))
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
+ handle(format("%s %s=load(%q),",depth,k,f))
+ else
+ handle(format("%s [%q]=load(%q),",depth,k,f))
+ end
+ end
+ else
+ if tk=="number" then
+ if hexify then
+ handle(format("%s [0x%04X]=%q,",depth,k,tostring(v)))
+ else
+ handle(format("%s [%s]=%q,",depth,k,tostring(v)))
+ end
+ elseif tk=="boolean" then
+ handle(format("%s [%s]=%q,",depth,tostring(k),tostring(v)))
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
+ handle(format("%s %s=%q,",depth,k,tostring(v)))
+ else
+ handle(format("%s [%q]=%q,",depth,k,tostring(v)))
+ end
+ end
+ end
+ end
+ if level>0 then
+ handle(format("%s},",depth))
+ end
+end
+local function serialize(_handle,root,name,specification)
+ local tname=type(name)
+ if type(specification)=="table" then
+ noquotes=specification.noquotes
+ hexify=specification.hexify
+ handle=_handle or specification.handle or print
+ reduce=specification.reduce or false
+ functions=specification.functions
+ compact=specification.compact
+ inline=specification.inline and compact
+ if functions==nil then
+ functions=true
+ end
+ if compact==nil then
+ compact=true
+ end
+ if inline==nil then
+ inline=compact
+ end
+ else
+ noquotes=false
+ hexify=false
+ handle=_handle or print
+ reduce=false
+ compact=true
+ inline=true
+ functions=true
+ end
+ if tname=="string" then
+ if name=="return" then
+ handle("return {")
else
- return { }
+ handle(name.."={")
end
-end
-
--- todo : copy without metatable
-
-local function copy(t, tables) -- taken from lua wiki, slightly adapted
- tables = tables or { }
- local tcopy = {}
- if not tables[t] then
- tables[t] = tcopy
+ elseif tname=="number" then
+ if hexify then
+ handle(format("[0x%04X]={",name))
+ else
+ handle("["..name.."]={")
end
- for i,v in next, t do -- brrr, what happens with sparse indexed
- if type(i) == "table" then
- if tables[i] then
- i = tables[i]
- else
- i = copy(i, tables)
- end
- end
- if type(v) ~= "table" then
- tcopy[i] = v
- elseif tables[v] then
- tcopy[i] = tables[v]
- else
- tcopy[i] = copy(v, tables)
- end
+ elseif tname=="boolean" then
+ if name then
+ handle("return {")
+ else
+ handle("{")
end
- local mt = getmetatable(t)
- if mt then
- setmetatable(tcopy,mt)
+ else
+ handle("t={")
+ end
+ if root then
+ if getmetatable(root) then
+ local dummy=root._w_h_a_t_e_v_e_r_
+ root._w_h_a_t_e_v_e_r_=nil
end
- return tcopy
-end
-
-table.fastcopy = fastcopy
-table.copy = copy
-
-function table.derive(parent)
- local child = { }
- if parent then
- setmetatable(child,{ __index = parent })
+ if next(root) then
+ do_serialize(root,name,"",0)
end
- return child
+ end
+ handle("}")
end
-
-function table.tohash(t,value)
- local h = { }
- if t then
- if value == nil then value = true end
- for _, v in next, t do -- no ipairs here
- h[v] = value
- end
+function table.serialize(root,name,specification)
+ local t,n={},0
+ local function flush(s)
+ n=n+1
+ t[n]=s
+ end
+ serialize(flush,root,name,specification)
+ return concat(t,"\n")
+end
+table.tohandle=serialize
+local maxtab=2*1024
+function table.tofile(filename,root,name,specification)
+ local f=io.open(filename,'w')
+ if f then
+ if maxtab>1 then
+ local t,n={},0
+ local function flush(s)
+ n=n+1
+ t[n]=s
+ if n>maxtab then
+ f:write(concat(t,"\n"),"\n")
+ t,n={},0
+ end
+ end
+ serialize(flush,root,name,specification)
+ f:write(concat(t,"\n"),"\n")
+ else
+ local function flush(s)
+ f:write(s,"\n")
+ end
+ serialize(flush,root,name,specification)
end
- return h
+ f:close()
+ io.flush()
+ end
end
-
-function table.fromhash(t)
- local hsh, h = { }, 0
- for k, v in next, t do -- no ipairs here
- if v then
- h = h + 1
- hsh[h] = k
- end
+local function flattened(t,f,depth)
+ if f==nil then
+ f={}
+ depth=0xFFFF
+ elseif tonumber(f) then
+ depth=f
+ f={}
+ elseif not depth then
+ depth=0xFFFF
+ end
+ for k,v in next,t do
+ if type(k)~="number" then
+ if depth>0 and type(v)=="table" then
+ flattened(v,f,depth-1)
+ else
+ f[k]=v
+ end
+ end
+ end
+ local n=#f
+ for k=1,#t do
+ local v=t[k]
+ if depth>0 and type(v)=="table" then
+ flattened(v,f,depth-1)
+ n=#f
+ else
+ n=n+1
+ f[n]=v
+ end
+ end
+ return f
+end
+table.flattened=flattened
+local function unnest(t,f)
+ if not f then
+ f={}
+ end
+ for i=1,#t do
+ local v=t[i]
+ if type(v)=="table" then
+ if type(v[1])=="table" then
+ unnest(v,f)
+ else
+ f[#f+1]=v
+ end
+ else
+ f[#f+1]=v
+ end
+ end
+ return f
+end
+function table.unnest(t)
+ return unnest(t)
+end
+local function are_equal(a,b,n,m)
+ if a and b and #a==#b then
+ n=n or 1
+ m=m or #a
+ for i=n,m do
+ local ai,bi=a[i],b[i]
+ if ai==bi then
+ elseif type(ai)=="table" and type(bi)=="table" then
+ if not are_equal(ai,bi) then
+ return false
+ end
+ else
+ return false
+ end
end
- return hsh
-end
-
-local noquotes, hexify, handle, reduce, compact, inline, functions
-
-local reserved = table.tohash { -- intercept a language inconvenience: no reserved words as key
- 'and', 'break', 'do', 'else', 'elseif', 'end', 'false', 'for', 'function', 'if',
- 'in', 'local', 'nil', 'not', 'or', 'repeat', 'return', 'then', 'true', 'until', 'while',
-}
-
-local function simple_table(t)
- if #t > 0 then
- local n = 0
- for _,v in next, t do
- n = n + 1
- end
- if n == #t then
- local tt, nt = { }, 0
- for i=1,#t do
- local v = t[i]
- local tv = type(v)
- if tv == "number" then
- nt = nt + 1
- if hexify then
- tt[nt] = format("0x%04X",v)
- else
- tt[nt] = tostring(v) -- tostring not needed
- end
- elseif tv == "boolean" then
- nt = nt + 1
- tt[nt] = tostring(v)
- elseif tv == "string" then
- nt = nt + 1
- tt[nt] = format("%q",v)
- else
- tt = nil
- break
- end
- end
- return tt
- end
+ return true
+ else
+ return false
+ end
+end
+local function identical(a,b)
+ for ka,va in next,a do
+ local vb=b[ka]
+ if va==vb then
+ elseif type(va)=="table" and type(vb)=="table" then
+ if not identical(va,vb) then
+ return false
+ end
+ else
+ return false
end
- return nil
+ end
+ return true
end
-
--- Because this is a core function of mkiv I moved some function calls
--- inline.
---
--- twice as fast in a test:
---
--- local propername = lpeg.P(lpeg.R("AZ","az","__") * lpeg.R("09","AZ","az", "__")^0 * lpeg.P(-1) )
-
--- problem: there no good number_to_string converter with the best resolution
-
-local function dummy() end
-
-local function do_serialize(root,name,depth,level,indexed)
- if level > 0 then
- depth = depth .. " "
- if indexed then
- handle(format("%s{",depth))
- else
- local tn = type(name)
- if tn == "number" then -- or find(k,"^%d+$") then
- if hexify then
- handle(format("%s[0x%04X]={",depth,name))
- else
- handle(format("%s[%s]={",depth,name))
- end
- elseif tn == "string" then
- if noquotes and not reserved[name] and find(name,"^%a[%w%_]*$") then
- handle(format("%s%s={",depth,name))
- else
- handle(format("%s[%q]={",depth,name))
- end
- elseif tn == "boolean" then
- handle(format("%s[%s]={",depth,tostring(name)))
- else
- handle(format("%s{",depth))
- end
- end
- end
- -- we could check for k (index) being number (cardinal)
- if root and next(root) then
- local first, last = nil, 0 -- #root cannot be trusted here (will be ok in 5.2 when ipairs is gone)
- if compact then
- -- NOT: for k=1,#root do (we need to quit at nil)
- for k,v in ipairs(root) do -- can we use next?
- if not first then first = k end
- last = last + 1
- end
- end
- local sk = sortedkeys(root)
- for i=1,#sk do
- local k = sk[i]
- local v = root[k]
- -- circular
- local t, tk = type(v), type(k)
- if compact and first and tk == "number" and k >= first and k <= last then
- if t == "number" then
- if hexify then
- handle(format("%s 0x%04X,",depth,v))
- else
- handle(format("%s %s,",depth,v)) -- %.99g
- end
- elseif t == "string" then
- if reduce and tonumber(v) then
- handle(format("%s %s,",depth,v))
- else
- handle(format("%s %q,",depth,v))
- end
- elseif t == "table" then
- if not next(v) then
- handle(format("%s {},",depth))
- elseif inline then -- and #t > 0
- local st = simple_table(v)
- if st then
- handle(format("%s { %s },",depth,concat(st,", ")))
- else
- do_serialize(v,k,depth,level+1,true)
- end
- else
- do_serialize(v,k,depth,level+1,true)
- end
- elseif t == "boolean" then
- handle(format("%s %s,",depth,tostring(v)))
- elseif t == "function" then
- if functions then
- handle(format('%s loadstring(%q),',depth,dump(v)))
- else
- handle(format('%s "function",',depth))
- end
- else
- handle(format("%s %q,",depth,tostring(v)))
- end
- elseif k == "__p__" then -- parent
- if false then
- handle(format("%s __p__=nil,",depth))
- end
- elseif t == "number" then
- if tk == "number" then -- or find(k,"^%d+$") then
- if hexify then
- handle(format("%s [0x%04X]=0x%04X,",depth,k,v))
- else
- handle(format("%s [%s]=%s,",depth,k,v)) -- %.99g
- end
- elseif tk == "boolean" then
- if hexify then
- handle(format("%s [%s]=0x%04X,",depth,tostring(k),v))
- else
- handle(format("%s [%s]=%s,",depth,tostring(k),v)) -- %.99g
- end
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
- if hexify then
- handle(format("%s %s=0x%04X,",depth,k,v))
- else
- handle(format("%s %s=%s,",depth,k,v)) -- %.99g
- end
- else
- if hexify then
- handle(format("%s [%q]=0x%04X,",depth,k,v))
- else
- handle(format("%s [%q]=%s,",depth,k,v)) -- %.99g
- end
- end
- elseif t == "string" then
- if reduce and tonumber(v) then
- if tk == "number" then -- or find(k,"^%d+$") then
- if hexify then
- handle(format("%s [0x%04X]=%s,",depth,k,v))
- else
- handle(format("%s [%s]=%s,",depth,k,v))
- end
- elseif tk == "boolean" then
- handle(format("%s [%s]=%s,",depth,tostring(k),v))
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
- handle(format("%s %s=%s,",depth,k,v))
- else
- handle(format("%s [%q]=%s,",depth,k,v))
- end
- else
- if tk == "number" then -- or find(k,"^%d+$") then
- if hexify then
- handle(format("%s [0x%04X]=%q,",depth,k,v))
- else
- handle(format("%s [%s]=%q,",depth,k,v))
- end
- elseif tk == "boolean" then
- handle(format("%s [%s]=%q,",depth,tostring(k),v))
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
- handle(format("%s %s=%q,",depth,k,v))
- else
- handle(format("%s [%q]=%q,",depth,k,v))
- end
- end
- elseif t == "table" then
- if not next(v) then
- if tk == "number" then -- or find(k,"^%d+$") then
- if hexify then
- handle(format("%s [0x%04X]={},",depth,k))
- else
- handle(format("%s [%s]={},",depth,k))
- end
- elseif tk == "boolean" then
- handle(format("%s [%s]={},",depth,tostring(k)))
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
- handle(format("%s %s={},",depth,k))
- else
- handle(format("%s [%q]={},",depth,k))
- end
- elseif inline then
- local st = simple_table(v)
- if st then
- if tk == "number" then -- or find(k,"^%d+$") then
- if hexify then
- handle(format("%s [0x%04X]={ %s },",depth,k,concat(st,", ")))
- else
- handle(format("%s [%s]={ %s },",depth,k,concat(st,", ")))
- end
- elseif tk == "boolean" then -- or find(k,"^%d+$") then
- handle(format("%s [%s]={ %s },",depth,tostring(k),concat(st,", ")))
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
- handle(format("%s %s={ %s },",depth,k,concat(st,", ")))
- else
- handle(format("%s [%q]={ %s },",depth,k,concat(st,", ")))
- end
- else
- do_serialize(v,k,depth,level+1)
- end
- else
- do_serialize(v,k,depth,level+1)
- end
- elseif t == "boolean" then
- if tk == "number" then -- or find(k,"^%d+$") then
- if hexify then
- handle(format("%s [0x%04X]=%s,",depth,k,tostring(v)))
- else
- handle(format("%s [%s]=%s,",depth,k,tostring(v)))
- end
- elseif tk == "boolean" then -- or find(k,"^%d+$") then
- handle(format("%s [%s]=%s,",depth,tostring(k),tostring(v)))
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
- handle(format("%s %s=%s,",depth,k,tostring(v)))
- else
- handle(format("%s [%q]=%s,",depth,k,tostring(v)))
- end
- elseif t == "function" then
- if functions then
- local f = getinfo(v).what == "C" and dump(dummy) or dump(v)
- -- local f = getinfo(v).what == "C" and dump(function(...) return v(...) end) or dump(v)
- if tk == "number" then -- or find(k,"^%d+$") then
- if hexify then
- handle(format("%s [0x%04X]=loadstring(%q),",depth,k,f))
- else
- handle(format("%s [%s]=loadstring(%q),",depth,k,f))
- end
- elseif tk == "boolean" then
- handle(format("%s [%s]=loadstring(%q),",depth,tostring(k),f))
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
- handle(format("%s %s=loadstring(%q),",depth,k,f))
- else
- handle(format("%s [%q]=loadstring(%q),",depth,k,f))
- end
- end
- else
- if tk == "number" then -- or find(k,"^%d+$") then
- if hexify then
- handle(format("%s [0x%04X]=%q,",depth,k,tostring(v)))
- else
- handle(format("%s [%s]=%q,",depth,k,tostring(v)))
- end
- elseif tk == "boolean" then -- or find(k,"^%d+$") then
- handle(format("%s [%s]=%q,",depth,tostring(k),tostring(v)))
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
- handle(format("%s %s=%q,",depth,k,tostring(v)))
- else
- handle(format("%s [%q]=%q,",depth,k,tostring(v)))
- end
- end
- end
+table.identical=identical
+table.are_equal=are_equal
+function table.compact(t)
+ if t then
+ for k,v in next,t do
+ if not next(v) then
+ t[k]=nil
+ end
end
- if level > 0 then
- handle(format("%s},",depth))
+ end
+end
+function table.contains(t,v)
+ if t then
+ for i=1,#t do
+ if t[i]==v then
+ return i
+ end
end
+ end
+ return false
end
-
--- replacing handle by a direct t[#t+1] = ... (plus test) is not much
--- faster (0.03 on 1.00 for zapfino.tma)
-
-local function serialize(_handle,root,name,specification) -- handle wins
- local tname = type(name)
- if type(specification) == "table" then
- noquotes = specification.noquotes
- hexify = specification.hexify
- handle = _handle or specification.handle or print
- reduce = specification.reduce or false
- functions = specification.functions
- compact = specification.compact
- inline = specification.inline and compact
- if functions == nil then
- functions = true
- end
- if compact == nil then
- compact = true
- end
- if inline == nil then
- inline = compact
- end
- else
- noquotes = false
- hexify = false
- handle = _handle or print
- reduce = false
- compact = true
- inline = true
- functions = true
- end
- if tname == "string" then
- if name == "return" then
- handle("return {")
- else
- handle(name .. "={")
- end
- elseif tname == "number" then
- if hexify then
- handle(format("[0x%04X]={",name))
- else
- handle("[" .. name .. "]={")
- end
- elseif tname == "boolean" then
- if name then
- handle("return {")
- else
- handle("{")
- end
- else
- handle("t={")
- end
- if root then
- -- The dummy access will initialize a table that has a delayed initialization
- -- using a metatable. (maybe explicitly test for metatable)
- if getmetatable(root) then -- todo: make this an option, maybe even per subtable
- local dummy = root._w_h_a_t_e_v_e_r_
- root._w_h_a_t_e_v_e_r_ = nil
- end
- -- Let's forget about empty tables.
- if next(root) then
- do_serialize(root,name,"",0)
- end
+function table.count(t)
+ local n=0
+ for k,v in next,t do
+ n=n+1
+ end
+ return n
+end
+function table.swapped(t,s)
+ local n={}
+ if s then
+ for k,v in next,s do
+ n[k]=v
+ end
+ end
+ for k,v in next,t do
+ n[v]=k
+ end
+ return n
+end
+function table.mirrored(t)
+ local n={}
+ for k,v in next,t do
+ n[v]=k
+ n[k]=v
+ end
+ return n
+end
+function table.reversed(t)
+ if t then
+ local tt,tn={},#t
+ if tn>0 then
+ local ttn=0
+ for i=tn,1,-1 do
+ ttn=ttn+1
+ tt[ttn]=t[i]
+ end
+ end
+ return tt
+ end
+end
+function table.reverse(t)
+ if t then
+ local n=#t
+ for i=1,floor(n/2) do
+ local j=n-i+1
+ t[i],t[j]=t[j],t[i]
end
- handle("}")
+ return t
+ end
end
-
-
-function table.serialize(root,name,specification)
- local t, n = { }, 0
- local function flush(s)
- n = n + 1
- t[n] = s
+function table.sequenced(t,sep,simple)
+ if not t then
+ return ""
+ end
+ local n=#t
+ local s={}
+ if n>0 then
+ for i=1,n do
+ s[i]=tostring(t[i])
+ end
+ else
+ n=0
+ for k,v in sortedhash(t) do
+ if simple then
+ if v==true then
+ n=n+1
+ s[n]=k
+ elseif v and v~="" then
+ n=n+1
+ s[n]=k.."="..tostring(v)
+ end
+ else
+ n=n+1
+ s[n]=k.."="..tostring(v)
+ end
+ end
+ end
+ return concat(s,sep or " | ")
+end
+function table.print(t,...)
+ if type(t)~="table" then
+ print(tostring(t))
+ else
+ serialize(print,t,...)
+ end
+end
+setinspector(function(v) if type(v)=="table" then serialize(print,v,"table") return true end end)
+function table.sub(t,i,j)
+ return { unpack(t,i,j) }
+end
+function table.is_empty(t)
+ return not t or not next(t)
+end
+function table.has_one_entry(t)
+ return t and not next(t,next(t))
+end
+function table.loweredkeys(t)
+ local l={}
+ for k,v in next,t do
+ l[lower(k)]=v
+ end
+ return l
+end
+function table.unique(old)
+ local hash={}
+ local new={}
+ local n=0
+ for i=1,#old do
+ local oi=old[i]
+ if not hash[oi] then
+ n=n+1
+ new[n]=oi
+ hash[oi]=true
end
- serialize(flush,root,name,specification)
- return concat(t,"\n")
+ end
+ return new
+end
+function table.sorted(t,...)
+ sort(t,...)
+ return t
end
-table.tohandle = serialize
-
--- sometimes tables are real use (zapfino extra pro is some 85M) in which
--- case a stepwise serialization is nice; actually, we could consider:
---
--- for line in table.serializer(root,name,reduce,noquotes) do
--- ...(line)
--- end
---
--- so this is on the todo list
-local maxtab = 2*1024
+end -- of closure
-function table.tofile(filename,root,name,specification)
- local f = io.open(filename,'w')
- if f then
- if maxtab > 1 then
- local t, n = { }, 0
- local function flush(s)
- n = n + 1
- t[n] = s
- if n > maxtab then
- f:write(concat(t,"\n"),"\n") -- hm, write(sometable) should be nice
- t, n = { }, 0 -- we could recycle t if needed
- end
- end
- serialize(flush,root,name,specification)
- f:write(concat(t,"\n"),"\n")
- else
- local function flush(s)
- f:write(s,"\n")
- end
- serialize(flush,root,name,specification)
- end
- f:close()
- io.flush()
- end
-end
+do -- create closure to overcome 200 locals limit
-local function flattened(t,f,depth)
- if f == nil then
- f = { }
- depth = 0xFFFF
- elseif tonumber(f) then
- -- assume then only two arguments are given
- depth = f
- f = { }
- elseif not depth then
- depth = 0xFFFF
- end
- for k, v in next, t do
- if type(k) ~= "number" then
- if depth > 0 and type(v) == "table" then
- flattened(v,f,depth-1)
- else
- f[k] = v
- end
- end
- end
- local n = #f
- for k=1,#t do
- local v = t[k]
- if depth > 0 and type(v) == "table" then
- flattened(v,f,depth-1)
- n = #f
- else
- n = n + 1
- f[n] = v
- end
- end
- return f
-end
+package.loaded["l-io"] = package.loaded["l-io"] or true
-table.flattened = flattened
+-- original size: 8799, stripped down to: 6325
-local function unnest(t,f) -- only used in mk, for old times sake
- if not f then -- and only relevant for token lists
- f = { }
- end
- for i=1,#t do
- local v = t[i]
- if type(v) == "table" then
- if type(v[1]) == "table" then
- unnest(v,f)
- else
- f[#f+1] = v
- end
- else
- f[#f+1] = v
- end
- end
- return f
+if not modules then modules={} end modules ['l-io']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local io=io
+local byte,find,gsub,format=string.byte,string.find,string.gsub,string.format
+local concat=table.concat
+local floor=math.floor
+local type=type
+if string.find(os.getenv("PATH"),";") then
+ io.fileseparator,io.pathseparator="\\",";"
+else
+ io.fileseparator,io.pathseparator="/",":"
end
-
-function table.unnest(t) -- bad name
- return unnest(t)
+local function readall(f)
+ return f:read("*all")
end
-
-local function are_equal(a,b,n,m) -- indexed
- if a and b and #a == #b then
- n = n or 1
- m = m or #a
- for i=n,m do
- local ai, bi = a[i], b[i]
- if ai==bi then
- -- same
- elseif type(ai)=="table" and type(bi)=="table" then
- if not are_equal(ai,bi) then
- return false
- end
- else
- return false
- end
- end
- return true
+local function readall(f)
+ local size=f:seek("end")
+ if size==0 then
+ return ""
+ elseif size<1024*1024 then
+ f:seek("set",0)
+ return f:read('*all')
+ else
+ local done=f:seek("set",0)
+ if size<1024*1024 then
+ step=1024*1024
+ elseif size>16*1024*1024 then
+ step=16*1024*1024
else
- return false
+ step=floor(size/(1024*1024))*1024*1024/8
end
+ local data={}
+ while true do
+ local r=f:read(step)
+ if not r then
+ return concat(data)
+ else
+ data[#data+1]=r
+ end
+ end
+ end
+end
+io.readall=readall
+function io.loaddata(filename,textmode)
+ local f=io.open(filename,(textmode and 'r') or 'rb')
+ if f then
+ local data=readall(f)
+ f:close()
+ if #data>0 then
+ return data
+ end
+ end
end
-
-local function identical(a,b) -- assumes same structure
- for ka, va in next, a do
- local vb = b[ka]
- if va == vb then
- -- same
- elseif type(va) == "table" and type(vb) == "table" then
- if not identical(va,vb) then
- return false
- end
- else
- return false
- end
+function io.savedata(filename,data,joiner)
+ local f=io.open(filename,"wb")
+ if f then
+ if type(data)=="table" then
+ f:write(concat(data,joiner or ""))
+ elseif type(data)=="function" then
+ data(f)
+ else
+ f:write(data or "")
end
+ f:close()
+ io.flush()
return true
+ else
+ return false
+ end
+end
+function io.loadlines(filename,n)
+ local f=io.open(filename,'r')
+ if not f then
+ elseif n then
+ local lines={}
+ for i=1,n do
+ local line=f:read("*lines")
+ if line then
+ lines[#lines+1]=line
+ else
+ break
+ end
+ end
+ f:close()
+ lines=concat(lines,"\n")
+ if #lines>0 then
+ return lines
+ end
+ else
+ local line=f:read("*line") or ""
+ f:close()
+ if #line>0 then
+ return line
+ end
+ end
+end
+function io.loadchunk(filename,n)
+ local f=io.open(filename,'rb')
+ if f then
+ local data=f:read(n or 1024)
+ f:close()
+ if #data>0 then
+ return data
+ end
+ end
end
-
-table.identical = identical
-table.are_equal = are_equal
-
--- maybe also make a combined one
-
-function table.compact(t)
- if t then
- for k,v in next, t do
- if not next(v) then
- t[k] = nil
- end
- end
- end
-end
-
-function table.contains(t, v)
- if t then
- for i=1, #t do
- if t[i] == v then
- return i
- end
- end
- end
+function io.exists(filename)
+ local f=io.open(filename)
+ if f==nil then
return false
+ else
+ f:close()
+ return true
+ end
end
-
-function table.count(t)
- local n = 0
- for k, v in next, t do
- n = n + 1
- end
- return n
+function io.size(filename)
+ local f=io.open(filename)
+ if f==nil then
+ return 0
+ else
+ local s=f:seek("end")
+ f:close()
+ return s
+ end
end
-
-function table.swapped(t,s) -- hash
- local n = { }
- if s then
- for k, v in next, s do
- n[k] = v
- end
+function io.noflines(f)
+ if type(f)=="string" then
+ local f=io.open(filename)
+ if f then
+ local n=f and io.noflines(f) or 0
+ f:close()
+ return n
+ else
+ return 0
end
- for k, v in next, t do
- n[v] = k
+ else
+ local n=0
+ for _ in f:lines() do
+ n=n+1
end
+ f:seek('set',0)
return n
+ end
+end
+local nextchar={
+ [ 4]=function(f)
+ return f:read(1,1,1,1)
+ end,
+ [ 2]=function(f)
+ return f:read(1,1)
+ end,
+ [ 1]=function(f)
+ return f:read(1)
+ end,
+ [-2]=function(f)
+ local a,b=f:read(1,1)
+ return b,a
+ end,
+ [-4]=function(f)
+ local a,b,c,d=f:read(1,1,1,1)
+ return d,c,b,a
+ end
+}
+function io.characters(f,n)
+ if f then
+ return nextchar[n or 1],f
+ end
end
-
-function table.reversed(t)
- if t then
- local tt, tn = { }, #t
- if tn > 0 then
- local ttn = 0
- for i=tn,1,-1 do
- ttn = ttn + 1
- tt[ttn] = t[i]
- end
- end
- return tt
+local nextbyte={
+ [4]=function(f)
+ local a,b,c,d=f:read(1,1,1,1)
+ if d then
+ return byte(a),byte(b),byte(c),byte(d)
+ end
+ end,
+ [3]=function(f)
+ local a,b,c=f:read(1,1,1)
+ if b then
+ return byte(a),byte(b),byte(c)
+ end
+ end,
+ [2]=function(f)
+ local a,b=f:read(1,1)
+ if b then
+ return byte(a),byte(b)
+ end
+ end,
+ [1]=function (f)
+ local a=f:read(1)
+ if a then
+ return byte(a)
+ end
+ end,
+ [-2]=function (f)
+ local a,b=f:read(1,1)
+ if b then
+ return byte(b),byte(a)
+ end
+ end,
+ [-3]=function(f)
+ local a,b,c=f:read(1,1,1)
+ if b then
+ return byte(c),byte(b),byte(a)
+ end
+ end,
+ [-4]=function(f)
+ local a,b,c,d=f:read(1,1,1,1)
+ if d then
+ return byte(d),byte(c),byte(b),byte(a)
end
+ end
+}
+function io.bytes(f,n)
+ if f then
+ return nextbyte[n or 1],f
+ else
+ return nil,nil
+ end
end
-
-function table.sequenced(t,sep,simple) -- hash only
- local s, n = { }, 0
- for k, v in sortedhash(t) do
- if simple then
- if v == true then
- n = n + 1
- s[n] = k
- elseif v and v~= "" then
- n = n + 1
- s[n] = k .. "=" .. tostring(v)
- end
- else
- n = n + 1
- s[n] = k .. "=" .. tostring(v)
+function io.ask(question,default,options)
+ while true do
+ io.write(question)
+ if options then
+ io.write(format(" [%s]",concat(options,"|")))
+ end
+ if default then
+ io.write(format(" [%s]",default))
+ end
+ io.write(format(" "))
+ io.flush()
+ local answer=io.read()
+ answer=gsub(answer,"^%s*(.*)%s*$","%1")
+ if answer=="" and default then
+ return default
+ elseif not options then
+ return answer
+ else
+ for k=1,#options do
+ if options[k]==answer then
+ return answer
+ end
+ end
+ local pattern="^"..answer
+ for k=1,#options do
+ local v=options[k]
+ if find(v,pattern) then
+ return v
end
+ end
end
- return concat(s, sep or " | ")
+ end
end
-
-function table.print(t,...)
- if type(t) ~= "table" then
- print(tostring(t))
- else
- table.tohandle(print,t,...)
- end
+local function readnumber(f,n,m)
+ if m then
+ f:seek("set",n)
+ n=m
+ end
+ if n==1 then
+ return byte(f:read(1))
+ elseif n==2 then
+ local a,b=byte(f:read(2),1,2)
+ return 256*a+b
+ elseif n==3 then
+ local a,b,c=byte(f:read(3),1,3)
+ return 256*256*a+256*b+c
+ elseif n==4 then
+ local a,b,c,d=byte(f:read(4),1,4)
+ return 256*256*256*a+256*256*b+256*c+d
+ elseif n==8 then
+ local a,b=readnumber(f,4),readnumber(f,4)
+ return 256*a+b
+ elseif n==12 then
+ local a,b,c=readnumber(f,4),readnumber(f,4),readnumber(f,4)
+ return 256*256*a+256*b+c
+ elseif n==-2 then
+ local b,a=byte(f:read(2),1,2)
+ return 256*a+b
+ elseif n==-3 then
+ local c,b,a=byte(f:read(3),1,3)
+ return 256*256*a+256*b+c
+ elseif n==-4 then
+ local d,c,b,a=byte(f:read(4),1,4)
+ return 256*256*256*a+256*256*b+256*c+d
+ elseif n==-8 then
+ local h,g,f,e,d,c,b,a=byte(f:read(8),1,8)
+ return 256*256*256*256*256*256*256*a+256*256*256*256*256*256*b+256*256*256*256*256*c+256*256*256*256*d+256*256*256*e+256*256*f+256*g+h
+ else
+ return 0
+ end
end
-
--- -- -- obsolete but we keep them for a while and might comment them later -- -- --
-
--- roughly: copy-loop : unpack : sub == 0.9 : 0.4 : 0.45 (so in critical apps, use unpack)
-
-function table.sub(t,i,j)
- return { unpack(t,i,j) }
+io.readnumber=readnumber
+function io.readstring(f,n,m)
+ if m then
+ f:seek("set",n)
+ n=m
+ end
+ local str=gsub(f:read(n),"\000","")
+ return str
end
+if not io.i_limiter then function io.i_limiter() end end
+if not io.o_limiter then function io.o_limiter() end end
--- slower than #t on indexed tables (#t only returns the size of the numerically indexed slice)
-
-function table.is_empty(t)
- return not t or not next(t)
-end
-function table.has_one_entry(t)
- return t and not next(t,next(t))
-end
+end -- of closure
--- new
+do -- create closure to overcome 200 locals limit
-function table.loweredkeys(t) -- maybe utf
- local l = { }
- for k, v in next, t do
- l[lower(k)] = v
- end
- return l
-end
+package.loaded["l-number"] = package.loaded["l-number"] or true
--- new, might move (maybe duplicate)
+-- original size: 4939, stripped down to: 2830
-function table.unique(old)
- local hash = { }
- local new = { }
- local n = 0
- for i=1,#old do
- local oi = old[i]
- if not hash[oi] then
- n = n + 1
- new[n] = oi
- hash[oi] = true
- end
+if not modules then modules={} end modules ['l-number']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local tostring,tonumber=tostring,tonumber
+local format,floor,match,rep=string.format,math.floor,string.match,string.rep
+local concat,insert=table.concat,table.insert
+local lpegmatch=lpeg.match
+number=number or {}
+local number=number
+if bit32 then
+ local btest,bor=bit32.btest,bit32.bor
+ function number.bit(p)
+ return 2^(p-1)
+ end
+ number.hasbit=btest
+ number.setbit=bor
+ function number.setbit(x,p)
+ return btest(x,p) and x or x+p
+ end
+ function number.clearbit(x,p)
+ return btest(x,p) and x-p or x
+ end
+else
+ function number.bit(p)
+ return 2^(p-1)
+ end
+ function number.hasbit(x,p)
+ return x%(p+p)>=p
+ end
+ function number.setbit(x,p)
+ return (x%(p+p)>=p) and x or x+p
+ end
+ function number.clearbit(x,p)
+ return (x%(p+p)>=p) and x-p or x
+ end
+end
+if bit32 then
+ local bextract=bit32.extract
+ local t={
+ "0","0","0","0","0","0","0","0",
+ "0","0","0","0","0","0","0","0",
+ "0","0","0","0","0","0","0","0",
+ "0","0","0","0","0","0","0","0",
+ }
+ function number.tobitstring(b,m)
+ local n=32
+ for i=0,31 do
+ local v=bextract(b,i)
+ local k=32-i
+ if v==1 then
+ n=k
+ t[k]="1"
+ else
+ t[k]="0"
+ end
end
- return new
-end
-
--- function table.sorted(t,...)
--- table.sort(t,...)
--- return t -- still sorts in-place
--- end
+ if m then
+ m=33-m*8
+ if m<1 then
+ m=1
+ end
+ return concat(t,"",m)
+ elseif n<8 then
+ return concat(t)
+ elseif n<16 then
+ return concat(t,"",9)
+ elseif n<24 then
+ return concat(t,"",17)
+ else
+ return concat(t,"",25)
+ end
+ end
+else
+ function number.tobitstring(n,m)
+ if n>0 then
+ local t={}
+ while n>0 do
+ insert(t,1,n%2>0 and 1 or 0)
+ n=floor(n/2)
+ end
+ local nn=8-#t%8
+ if nn>0 and nn<8 then
+ for i=1,nn do
+ insert(t,1,0)
+ end
+ end
+ if m then
+ m=m*8-#t
+ if m>0 then
+ insert(t,1,rep("0",m))
+ end
+ end
+ return concat(t)
+ elseif m then
+ rep("00000000",m)
+ else
+ return "00000000"
+ end
+ end
+end
+function number.valid(str,default)
+ return tonumber(str) or default or nil
+end
+function number.toevenhex(n)
+ local s=format("%X",n)
+ if #s%2==0 then
+ return s
+ else
+ return "0"..s
+ end
+end
+local one=lpeg.C(1-lpeg.S('')/tonumber)^1
+function number.toset(n)
+ return lpegmatch(one,tostring(n))
+end
+local function bits(n,i,...)
+ if n>0 then
+ local m=n%2
+ local n=floor(n/2)
+ if m>0 then
+ return bits(n,i+1,i,...)
+ else
+ return bits(n,i+1,...)
+ end
+ else
+ return...
+ end
+end
+function number.bits(n)
+ return { bits(n,1) }
+end
end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-lpeg'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
+package.loaded["l-set"] = package.loaded["l-set"] or true
--- a new lpeg fails on a #(1-P(":")) test and really needs a + P(-1)
-
-local lpeg = require("lpeg")
-
--- tracing (only used when we encounter a problem in integration of lpeg in luatex)
-
-local report = texio and texio.write_nl or print
-
--- local lpmatch = lpeg.match
--- local lpprint = lpeg.print
--- local lpp = lpeg.P
--- local lpr = lpeg.R
--- local lps = lpeg.S
--- local lpc = lpeg.C
--- local lpb = lpeg.B
--- local lpv = lpeg.V
--- local lpcf = lpeg.Cf
--- local lpcb = lpeg.Cb
--- local lpcg = lpeg.Cg
--- local lpct = lpeg.Ct
--- local lpcs = lpeg.Cs
--- local lpcc = lpeg.Cc
--- local lpcmt = lpeg.Cmt
--- local lpcarg = lpeg.Carg
-
--- function lpeg.match(l,...) report("LPEG MATCH") lpprint(l) return lpmatch(l,...) end
-
--- function lpeg.P (l) local p = lpp (l) report("LPEG P =") lpprint(l) return p end
--- function lpeg.R (l) local p = lpr (l) report("LPEG R =") lpprint(l) return p end
--- function lpeg.S (l) local p = lps (l) report("LPEG S =") lpprint(l) return p end
--- function lpeg.C (l) local p = lpc (l) report("LPEG C =") lpprint(l) return p end
--- function lpeg.B (l) local p = lpb (l) report("LPEG B =") lpprint(l) return p end
--- function lpeg.V (l) local p = lpv (l) report("LPEG V =") lpprint(l) return p end
--- function lpeg.Cf (l) local p = lpcf (l) report("LPEG Cf =") lpprint(l) return p end
--- function lpeg.Cb (l) local p = lpcb (l) report("LPEG Cb =") lpprint(l) return p end
--- function lpeg.Cg (l) local p = lpcg (l) report("LPEG Cg =") lpprint(l) return p end
--- function lpeg.Ct (l) local p = lpct (l) report("LPEG Ct =") lpprint(l) return p end
--- function lpeg.Cs (l) local p = lpcs (l) report("LPEG Cs =") lpprint(l) return p end
--- function lpeg.Cc (l) local p = lpcc (l) report("LPEG Cc =") lpprint(l) return p end
--- function lpeg.Cmt (l) local p = lpcmt (l) report("LPEG Cmt =") lpprint(l) return p end
--- function lpeg.Carg (l) local p = lpcarg(l) report("LPEG Carg =") lpprint(l) return p end
-
-local type = type
-local byte, char, gmatch = string.byte, string.char, string.gmatch
-
--- Beware, we predefine a bunch of patterns here and one reason for doing so
--- is that we get consistent behaviour in some of the visualizers.
-
-lpeg.patterns = lpeg.patterns or { } -- so that we can share
-local patterns = lpeg.patterns
-
-local P, R, S, V, match = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.match
-local Ct, C, Cs, Cc = lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc
-local lpegtype = lpeg.type
-
-local utfcharacters = string.utfcharacters
-local utfgmatch = unicode and unicode.utf8.gmatch
-
-local anything = P(1)
-local endofstring = P(-1)
-local alwaysmatched = P(true)
-
-patterns.anything = anything
-patterns.endofstring = endofstring
-patterns.beginofstring = alwaysmatched
-patterns.alwaysmatched = alwaysmatched
-
-local digit, sign = R('09'), S('+-')
-local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
-local newline = crlf + S("\r\n") -- cr + lf
-local escaped = P("\\") * anything
-local squote = P("'")
-local dquote = P('"')
-local space = P(" ")
-
-local utfbom_32_be = P('\000\000\254\255')
-local utfbom_32_le = P('\255\254\000\000')
-local utfbom_16_be = P('\255\254')
-local utfbom_16_le = P('\254\255')
-local utfbom_8 = P('\239\187\191')
-local utfbom = utfbom_32_be + utfbom_32_le
- + utfbom_16_be + utfbom_16_le
- + utfbom_8
-local utftype = utfbom_32_be / "utf-32-be" + utfbom_32_le / "utf-32-le"
- + utfbom_16_be / "utf-16-be" + utfbom_16_le / "utf-16-le"
- + utfbom_8 / "utf-8" + alwaysmatched / "unknown"
-
-local utf8next = R("\128\191")
-
-patterns.utf8one = R("\000\127")
-patterns.utf8two = R("\194\223") * utf8next
-patterns.utf8three = R("\224\239") * utf8next * utf8next
-patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
-patterns.utfbom = utfbom
-patterns.utftype = utftype
-
-local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
-local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
-
-patterns.utf8 = utf8char
-patterns.utf8char = utf8char
-patterns.validutf8 = validutf8char
-patterns.validutf8char = validutf8char
-
-patterns.digit = digit
-patterns.sign = sign
-patterns.cardinal = sign^0 * digit^1
-patterns.integer = sign^0 * digit^1
-patterns.float = sign^0 * digit^0 * P('.') * digit^1
-patterns.cfloat = sign^0 * digit^0 * P(',') * digit^1
-patterns.number = patterns.float + patterns.integer
-patterns.cnumber = patterns.cfloat + patterns.integer
-patterns.oct = P("0") * R("07")^1
-patterns.octal = patterns.oct
-patterns.HEX = P("0x") * R("09","AF")^1
-patterns.hex = P("0x") * R("09","af")^1
-patterns.hexadecimal = P("0x") * R("09","AF","af")^1
-patterns.lowercase = R("az")
-patterns.uppercase = R("AZ")
-patterns.letter = patterns.lowercase + patterns.uppercase
-patterns.space = space
-patterns.tab = P("\t")
-patterns.spaceortab = patterns.space + patterns.tab
-patterns.eol = S("\n\r")
-patterns.spacer = S(" \t\f\v") -- + char(0xc2, 0xa0) if we want utf (cf mail roberto)
-patterns.newline = newline
-patterns.emptyline = newline^1
-patterns.nonspacer = 1 - patterns.spacer
-patterns.whitespace = patterns.eol + patterns.spacer
-patterns.nonwhitespace = 1 - patterns.whitespace
-patterns.equal = P("=")
-patterns.comma = P(",")
-patterns.commaspacer = P(",") * patterns.spacer^0
-patterns.period = P(".")
-patterns.colon = P(":")
-patterns.semicolon = P(";")
-patterns.underscore = P("_")
-patterns.escaped = escaped
-patterns.squote = squote
-patterns.dquote = dquote
-patterns.nosquote = (escaped + (1-squote))^0
-patterns.nodquote = (escaped + (1-dquote))^0
-patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"")
-patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
-patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
-patterns.unspacer = ((patterns.spacer^1)/"")^0
-
-patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
-patterns.beginline = #(1-newline)
-
--- print(string.unquoted("test"))
--- print(string.unquoted([["t\"est"]]))
--- print(string.unquoted([["t\"est"x]]))
--- print(string.unquoted("\'test\'"))
--- print(string.unquoted('"test"'))
--- print(string.unquoted('"test"'))
-
-function lpeg.anywhere(pattern) --slightly adapted from website
- return P { P(pattern) + 1 * V(1) } -- why so complex?
-end
-
-function lpeg.splitter(pattern, action)
- return (((1-P(pattern))^1)/action+1)^0
-end
-
-function lpeg.tsplitter(pattern, action)
- return Ct((((1-P(pattern))^1)/action+1)^0)
-end
-
--- probleem: separator can be lpeg and that does not hash too well, but
--- it's quite okay as the key is then not garbage collected
-
-local splitters_s, splitters_m, splitters_t = { }, { }, { }
-
-local function splitat(separator,single)
- local splitter = (single and splitters_s[separator]) or splitters_m[separator]
- if not splitter then
- separator = P(separator)
- local other = C((1 - separator)^0)
- if single then
- local any = anything
- splitter = other * (separator * C(any^0) + "") -- ?
- splitters_s[separator] = splitter
- else
- splitter = other * (separator * other)^0
- splitters_m[separator] = splitter
- end
- end
- return splitter
-end
+-- original size: 1923, stripped down to: 1133
-local function tsplitat(separator)
- local splitter = splitters_t[separator]
- if not splitter then
- splitter = Ct(splitat(separator))
- splitters_t[separator] = splitter
+if not modules then modules={} end modules ['l-set']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+set=set or {}
+local nums={}
+local tabs={}
+local concat=table.concat
+local next,type=next,type
+set.create=table.tohash
+function set.tonumber(t)
+ if next(t) then
+ local s=""
+ for k,v in next,t do
+ if v then
+ s=s.." "..k
+ end
+ end
+ local n=nums[s]
+ if not n then
+ n=#tabs+1
+ tabs[n]=t
+ nums[s]=n
end
- return splitter
+ return n
+ else
+ return 0
+ end
end
-
-lpeg.splitat = splitat
-lpeg.tsplitat = tsplitat
-
-function string.splitup(str,separator)
- if not separator then
- separator = ","
- end
- return match(splitters_m[separator] or splitat(separator),str)
+function set.totable(n)
+ if n==0 then
+ return {}
+ else
+ return tabs[n] or {}
+ end
end
-
-
-local cache = { }
-
-function lpeg.split(separator,str)
- local c = cache[separator]
- if not c then
- c = tsplitat(separator)
- cache[separator] = c
+function set.tolist(n)
+ if n==0 or not tabs[n] then
+ return ""
+ else
+ local t,n={},0
+ for k,v in next,tabs[n] do
+ if v then
+ n=n+1
+ t[n]=k
+ end
end
- return match(c,str)
+ return concat(t," ")
+ end
end
-
-function string.split(str,separator)
- local c = cache[separator]
- if not c then
- c = tsplitat(separator)
- cache[separator] = c
- end
- return match(c,str)
+function set.contains(n,s)
+ if type(n)=="table" then
+ return n[s]
+ elseif n==0 then
+ return false
+ else
+ local t=tabs[n]
+ return t and t[s]
+ end
end
-local spacing = patterns.spacer^0 * newline -- sort of strip
-local empty = spacing * Cc("")
-local nonempty = Cs((1-spacing)^1) * spacing^-1
-local content = (empty + nonempty)^1
-patterns.textline = content
+end -- of closure
+do -- create closure to overcome 200 locals limit
-local linesplitter = tsplitat(newline)
+package.loaded["l-os"] = package.loaded["l-os"] or true
-patterns.linesplitter = linesplitter
+-- original size: 13692, stripped down to: 8406
-function string.splitlines(str)
- return match(linesplitter,str)
+if not modules then modules={} end modules ['l-os']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local os=os
+local date,time=os.date,os.time
+local find,format,gsub,upper,gmatch=string.find,string.format,string.gsub,string.upper,string.gmatch
+local concat=table.concat
+local random,ceil,randomseed=math.random,math.ceil,math.randomseed
+local rawget,rawset,type,getmetatable,setmetatable,tonumber,tostring=rawget,rawset,type,getmetatable,setmetatable,tonumber,tostring
+math.initialseed=tonumber(string.sub(string.reverse(tostring(ceil(socket and socket.gettime()*10000 or time()))),1,6))
+randomseed(math.initialseed)
+if not os.__getenv__ then
+ os.__getenv__=os.getenv
+ os.__setenv__=os.setenv
+ if os.env then
+ local osgetenv=os.getenv
+ local ossetenv=os.setenv
+ local osenv=os.env local _=osenv.PATH
+ function os.setenv(k,v)
+ if v==nil then
+ v=""
+ end
+ local K=upper(k)
+ osenv[K]=v
+ if type(v)=="table" then
+ v=concat(v,";")
+ end
+ ossetenv(K,v)
+ end
+ function os.getenv(k)
+ local K=upper(k)
+ local v=osenv[K] or osenv[k] or osgetenv(K) or osgetenv(k)
+ if v=="" then
+ return nil
+ else
+ return v
+ end
+ end
+ else
+ local ossetenv=os.setenv
+ local osgetenv=os.getenv
+ local osenv={}
+ function os.setenv(k,v)
+ if v==nil then
+ v=""
+ end
+ local K=upper(k)
+ osenv[K]=v
+ end
+ function os.getenv(k)
+ local K=upper(k)
+ local v=osenv[K] or osgetenv(K) or osgetenv(k)
+ if v=="" then
+ return nil
+ else
+ return v
+ end
+ end
+ local function __index(t,k)
+ return os.getenv(k)
+ end
+ local function __newindex(t,k,v)
+ os.setenv(k,v)
+ end
+ os.env={}
+ setmetatable(os.env,{ __index=__index,__newindex=__newindex } )
+ end
end
-
-local utflinesplitter = utfbom^-1 * tsplitat(newline)
-
-patterns.utflinesplitter = utflinesplitter
-
-function string.utfsplitlines(str)
- return match(utflinesplitter,str or "")
+local execute,spawn,exec,iopopen,ioflush=os.execute,os.spawn or os.execute,os.exec or os.execute,io.popen,io.flush
+function os.execute(...) ioflush() return execute(...) end
+function os.spawn (...) ioflush() return spawn (...) end
+function os.exec (...) ioflush() return exec (...) end
+function io.popen (...) ioflush() return iopopen(...) end
+function os.resultof(command)
+ local handle=io.popen(command,"r")
+ return handle and handle:read("*all") or ""
end
-
-
-local cache = { }
-
-function lpeg.checkedsplit(separator,str)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
+if not io.fileseparator then
+ if find(os.getenv("PATH"),";") then
+ io.fileseparator,io.pathseparator,os.type="\\",";",os.type or "mswin"
+ else
+ io.fileseparator,io.pathseparator,os.type="/",":",os.type or "unix"
+ end
+end
+os.type=os.type or (io.pathseparator==";" and "windows") or "unix"
+os.name=os.name or (os.type=="windows" and "mswin" ) or "linux"
+if os.type=="windows" then
+ os.libsuffix,os.binsuffix,os.binsuffixes='dll','exe',{ 'exe','cmd','bat' }
+else
+ os.libsuffix,os.binsuffix,os.binsuffixes='so','',{ '' }
+end
+local launchers={
+ windows="start %s",
+ macosx="open %s",
+ unix="$BROWSER %s &> /dev/null &",
+}
+function os.launch(str)
+ os.execute(format(launchers[os.name] or launchers.unix,str))
+end
+if not os.times then
+ function os.times()
+ return {
+ utime=os.gettimeofday(),
+ stime=0,
+ cutime=0,
+ cstime=0,
+ }
+ end
+end
+os.gettimeofday=os.gettimeofday or os.clock
+local startuptime=os.gettimeofday()
+function os.runtime()
+ return os.gettimeofday()-startuptime
+end
+os.resolvers=os.resolvers or {}
+local resolvers=os.resolvers
+setmetatable(os,{ __index=function(t,k)
+ local r=resolvers[k]
+ return r and r(t,k) or nil
+end })
+local name,platform=os.name or "linux",os.getenv("MTX_PLATFORM") or ""
+local function guess()
+ local architecture=os.resultof("uname -m") or ""
+ if architecture~="" then
+ return architecture
+ end
+ architecture=os.getenv("HOSTTYPE") or ""
+ if architecture~="" then
+ return architecture
+ end
+ return os.resultof("echo $HOSTTYPE") or ""
+end
+if platform~="" then
+ os.platform=platform
+elseif os.type=="windows" then
+ function os.resolvers.platform(t,k)
+ local platform,architecture="",os.getenv("PROCESSOR_ARCHITECTURE") or ""
+ if find(architecture,"AMD64") then
+ platform="mswin-64"
+ else
+ platform="mswin"
+ end
+ os.setenv("MTX_PLATFORM",platform)
+ os.platform=platform
+ return platform
+ end
+elseif name=="linux" then
+ function os.resolvers.platform(t,k)
+ local platform,architecture="",os.getenv("HOSTTYPE") or os.resultof("uname -m") or ""
+ if find(architecture,"x86_64") then
+ platform="linux-64"
+ elseif find(architecture,"ppc") then
+ platform="linux-ppc"
+ else
+ platform="linux"
+ end
+ os.setenv("MTX_PLATFORM",platform)
+ os.platform=platform
+ return platform
+ end
+elseif name=="macosx" then
+ function os.resolvers.platform(t,k)
+ local platform,architecture="",os.resultof("echo $HOSTTYPE") or ""
+ if architecture=="" then
+ platform="osx-intel"
+ elseif find(architecture,"i386") then
+ platform="osx-intel"
+ elseif find(architecture,"x86_64") then
+ platform="osx-64"
+ else
+ platform="osx-ppc"
+ end
+ os.setenv("MTX_PLATFORM",platform)
+ os.platform=platform
+ return platform
+ end
+elseif name=="sunos" then
+ function os.resolvers.platform(t,k)
+ local platform,architecture="",os.resultof("uname -m") or ""
+ if find(architecture,"sparc") then
+ platform="solaris-sparc"
+ else
+ platform="solaris-intel"
+ end
+ os.setenv("MTX_PLATFORM",platform)
+ os.platform=platform
+ return platform
+ end
+elseif name=="freebsd" then
+ function os.resolvers.platform(t,k)
+ local platform,architecture="",os.resultof("uname -m") or ""
+ if find(architecture,"amd64") then
+ platform="freebsd-amd64"
+ else
+ platform="freebsd"
+ end
+ os.setenv("MTX_PLATFORM",platform)
+ os.platform=platform
+ return platform
+ end
+elseif name=="kfreebsd" then
+ function os.resolvers.platform(t,k)
+ local platform,architecture="",os.getenv("HOSTTYPE") or os.resultof("uname -m") or ""
+ if find(architecture,"x86_64") then
+ platform="kfreebsd-amd64"
+ else
+ platform="kfreebsd-i386"
end
- return match(c,str)
+ os.setenv("MTX_PLATFORM",platform)
+ os.platform=platform
+ return platform
+ end
+else
+ function os.resolvers.platform(t,k)
+ local platform="linux"
+ os.setenv("MTX_PLATFORM",platform)
+ os.platform=platform
+ return platform
+ end
+end
+local t={ 8,9,"a","b" }
+function os.uuid()
+ return format("%04x%04x-4%03x-%s%03x-%04x-%04x%04x%04x",
+ random(0xFFFF),random(0xFFFF),
+ random(0x0FFF),
+ t[ceil(random(4))] or 8,random(0x0FFF),
+ random(0xFFFF),
+ random(0xFFFF),random(0xFFFF),random(0xFFFF)
+ )
end
-
-function string.checkedsplit(str,separator)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
+local d
+function os.timezone(delta)
+ d=d or tonumber(tonumber(date("%H")-date("!%H")))
+ if delta then
+ if d>0 then
+ return format("+%02i:00",d)
+ else
+ return format("-%02i:00",-d)
+ end
+ else
+ return 1
+ end
+end
+local timeformat=format("%%s%s",os.timezone(true))
+local dateformat="!%Y-%m-%d %H:%M:%S"
+function os.fulltime(t,default)
+ t=tonumber(t) or 0
+ if t>0 then
+ elseif default then
+ return default
+ else
+ t=nil
+ end
+ return format(timeformat,date(dateformat,t))
+end
+local dateformat="%Y-%m-%d %H:%M:%S"
+function os.localtime(t,default)
+ t=tonumber(t) or 0
+ if t>0 then
+ elseif default then
+ return default
+ else
+ t=nil
+ end
+ return date(dateformat,t)
+end
+function os.converttime(t,default)
+ local t=tonumber(t)
+ if t and t>0 then
+ return date(dateformat,t)
+ else
+ return default or "-"
+ end
+end
+local memory={}
+local function which(filename)
+ local fullname=memory[filename]
+ if fullname==nil then
+ local suffix=file.suffix(filename)
+ local suffixes=suffix=="" and os.binsuffixes or { suffix }
+ for directory in gmatch(os.getenv("PATH"),"[^"..io.pathseparator.."]+") do
+ local df=file.join(directory,filename)
+ for i=1,#suffixes do
+ local dfs=file.addsuffix(df,suffixes[i])
+ if io.exists(dfs) then
+ fullname=dfs
+ break
+ end
+ end
end
- return match(c,str)
+ if not fullname then
+ fullname=false
+ end
+ memory[filename]=fullname
+ end
+ return fullname
+end
+os.which=which
+os.where=which
+function os.today()
+ return date("!*t")
+end
+function os.now()
+ return date("!%Y-%m-%d %H:%M:%S")
+end
+if not os.sleep and socket then
+ os.sleep=socket.sleep
end
-local function f2(s) local c1, c2 = byte(s,1,2) return c1 * 64 + c2 - 12416 end
-local function f3(s) local c1, c2, c3 = byte(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
-local function f4(s) local c1, c2, c3, c4 = byte(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
-
-local utf8byte = patterns.utf8one/byte + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
-
-patterns.utf8byte = utf8byte
+end -- of closure
+do -- create closure to overcome 200 locals limit
+package.loaded["l-file"] = package.loaded["l-file"] or true
-local cache = { }
+-- original size: 16648, stripped down to: 9051
-function lpeg.stripper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs(((S(str)^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs(((str^1)/"" + 1)^0)
- end
+if not modules then modules={} end modules ['l-file']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+file=file or {}
+local file=file
+if not lfs then
+ lfs=optionalrequire("lfs")
+end
+if not lfs then
+ lfs={
+ getcurrentdir=function()
+ return "."
+ end,
+ attributes=function()
+ return nil
+ end,
+ isfile=function(name)
+ local f=io.open(name,'rb')
+ if f then
+ f:close()
+ return true
+ end
+ end,
+ isdir=function(name)
+ print("you need to load lfs")
+ return false
+ end
+ }
+elseif not lfs.isfile then
+ local attributes=lfs.attributes
+ function lfs.isdir(name)
+ return attributes(name,"mode")=="directory"
+ end
+ function lfs.isfile(name)
+ return attributes(name,"mode")=="file"
+ end
+end
+local insert,concat=table.insert,table.concat
+local match=string.match
+local lpegmatch=lpeg.match
+local getcurrentdir,attributes=lfs.currentdir,lfs.attributes
+local checkedsplit=string.checkedsplit
+local P,R,S,C,Cs,Cp,Cc,Ct=lpeg.P,lpeg.R,lpeg.S,lpeg.C,lpeg.Cs,lpeg.Cp,lpeg.Cc,lpeg.Ct
+local colon=P(":")
+local period=P(".")
+local periods=P("..")
+local fwslash=P("/")
+local bwslash=P("\\")
+local slashes=S("\\/")
+local noperiod=1-period
+local noslashes=1-slashes
+local name=noperiod^1
+local suffix=period/""*(1-period-slashes)^1*-1
+local pattern=C((1-(slashes^1*noslashes^1*-1))^1)*P(1)
+local function pathpart(name,default)
+ return name and lpegmatch(pattern,name) or default or ""
+end
+local pattern=(noslashes^0*slashes)^1*C(noslashes^1)*-1
+local function basename(name)
+ return name and lpegmatch(pattern,name) or name
end
-
-local cache = { }
-
-function lpeg.keeper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs((((1-S(str))^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
+local pattern=(noslashes^0*slashes^1)^0*Cs((1-suffix)^1)*suffix^0
+local function nameonly(name)
+ return name and lpegmatch(pattern,name) or name
+end
+local pattern=(noslashes^0*slashes)^0*(noperiod^1*period)^1*C(noperiod^1)*-1
+local function suffixonly(name)
+ return name and lpegmatch(pattern,name) or ""
+end
+file.pathpart=pathpart
+file.basename=basename
+file.nameonly=nameonly
+file.suffixonly=suffixonly
+file.suffix=suffixonly
+file.dirname=pathpart
+file.extname=suffixonly
+local drive=C(R("az","AZ"))*colon
+local path=C((noslashes^0*slashes)^0)
+local suffix=period*C(P(1-period)^0*P(-1))
+local base=C((1-suffix)^0)
+local rest=C(P(1)^0)
+drive=drive+Cc("")
+path=path+Cc("")
+base=base+Cc("")
+suffix=suffix+Cc("")
+local pattern_a=drive*path*base*suffix
+local pattern_b=path*base*suffix
+local pattern_c=C(drive*path)*C(base*suffix)
+local pattern_d=path*rest
+function file.splitname(str,splitdrive)
+ if not str then
+ elseif splitdrive then
+ return lpegmatch(pattern_a,str)
+ else
+ return lpegmatch(pattern_b,str)
+ end
+end
+function file.splitbase(str)
+ return str and lpegmatch(pattern_d,str)
+end
+function file.nametotable(str,splitdrive)
+ if str then
+ local path,drive,subpath,name,base,suffix=lpegmatch(pattern_c,str)
+ if splitdrive then
+ return {
+ path=path,
+ drive=drive,
+ subpath=subpath,
+ name=name,
+ base=base,
+ suffix=suffix,
+ }
else
- return Cs((((1-str)^1)/"" + 1)^0)
+ return {
+ path=path,
+ name=name,
+ base=base,
+ suffix=suffix,
+ }
+ end
+ end
+end
+local pattern=Cs(((period*(1-period-slashes)^1*-1)/""+1)^1)
+function file.removesuffix(name)
+ return name and lpegmatch(pattern,name)
+end
+local suffix=period/""*(1-period-slashes)^1*-1
+local pattern=Cs((noslashes^0*slashes^1)^0*((1-suffix)^1))*Cs(suffix)
+function file.addsuffix(filename,suffix,criterium)
+ if not filename or not suffix or suffix=="" then
+ return filename
+ elseif criterium==true then
+ return filename.."."..suffix
+ elseif not criterium then
+ local n,s=lpegmatch(pattern,filename)
+ if not s or s=="" then
+ return filename.."."..suffix
+ else
+ return filename
+ end
+ else
+ local n,s=lpegmatch(pattern,filename)
+ if s and s~="" then
+ local t=type(criterium)
+ if t=="table" then
+ for i=1,#criterium do
+ if s==criterium[i] then
+ return filename
+ end
+ end
+ elseif t=="string" then
+ if s==criterium then
+ return filename
+ end
+ end
end
+ return (n or filename).."."..suffix
+ end
end
-
-function lpeg.frontstripper(str) -- or pattern (yet undocumented)
- return (P(str) + P(true)) * Cs(P(1)^0)
+local suffix=period*(1-period-slashes)^1*-1
+local pattern=Cs((1-suffix)^0)
+function file.replacesuffix(name,suffix)
+ if name and suffix and suffix~="" then
+ return lpegmatch(pattern,name).."."..suffix
+ else
+ return name
+ end
end
-
-function lpeg.endstripper(str) -- or pattern (yet undocumented)
- return Cs((1 - P(str) * P(-1))^0)
+local reslasher=lpeg.replacer(P("\\"),"/")
+function file.reslash(str)
+ return str and lpegmatch(reslasher,str)
end
-
--- Just for fun I looked at the used bytecode and
--- p = (p and p + pp) or pp gets one more (testset).
-
-function lpeg.replacer(one,two)
- if type(one) == "table" then
- local no = #one
- if no > 0 then
- local p
- for i=1,no do
- local o = one[i]
- local pp = P(o[1]) / o[2]
- if p then
- p = p + pp
- else
- p = pp
- end
- end
- return Cs((p + 1)^0)
- end
- else
- two = two or ""
- return Cs((P(one)/two + 1)^0)
+function file.is_writable(name)
+ if not name then
+ elseif lfs.isdir(name) then
+ name=name.."/m_t_x_t_e_s_t.tmp"
+ local f=io.open(name,"wb")
+ if f then
+ f:close()
+ os.remove(name)
+ return true
end
-end
-
-local splitters_f, splitters_s = { }, { }
-
-function lpeg.firstofsplit(separator) -- always return value
- local splitter = splitters_f[separator]
- if not splitter then
- separator = P(separator)
- splitter = C((1 - separator)^0)
- splitters_f[separator] = splitter
+ elseif lfs.isfile(name) then
+ local f=io.open(name,"ab")
+ if f then
+ f:close()
+ return true
+ end
+ else
+ local f=io.open(name,"ab")
+ if f then
+ f:close()
+ os.remove(name)
+ return true
end
- return splitter
+ end
+ return false
end
-
-function lpeg.secondofsplit(separator) -- nil if not split
- local splitter = splitters_s[separator]
- if not splitter then
- separator = P(separator)
- splitter = (1 - separator)^0 * separator * C(anything^0)
- splitters_s[separator] = splitter
+local readable=P("r")*Cc(true)
+function file.is_readable(name)
+ if name then
+ local a=attributes(name)
+ return a and lpegmatch(readable,a.permissions) or false
+ else
+ return false
+ end
+end
+file.isreadable=file.is_readable
+file.iswritable=file.is_writable
+function file.size(name)
+ if name then
+ local a=attributes(name)
+ return a and a.size or 0
+ else
+ return 0
+ end
+end
+function file.splitpath(str,separator)
+ return str and checkedsplit(lpegmatch(reslasher,str),separator or io.pathseparator)
+end
+function file.joinpath(tab,separator)
+ return tab and concat(tab,separator or io.pathseparator)
+end
+local stripper=Cs(P(fwslash)^0/""*reslasher)
+local isnetwork=fwslash*fwslash*(1-fwslash)+(1-fwslash-colon)^1*colon
+local isroot=fwslash^1*-1
+local hasroot=fwslash^1
+local deslasher=lpeg.replacer(S("\\/")^1,"/")
+function file.join(...)
+ local lst={... }
+ local one=lst[1]
+ if lpegmatch(isnetwork,one) then
+ local two=lpegmatch(deslasher,concat(lst,"/",2))
+ return one.."/"..two
+ elseif lpegmatch(isroot,one) then
+ local two=lpegmatch(deslasher,concat(lst,"/",2))
+ if lpegmatch(hasroot,two) then
+ return two
+ else
+ return "/"..two
+ end
+ elseif one=="" then
+ return lpegmatch(stripper,concat(lst,"/",2))
+ else
+ return lpegmatch(deslasher,concat(lst,"/"))
+ end
+end
+local drivespec=R("az","AZ")^1*colon
+local anchors=fwslash+drivespec
+local untouched=periods+(1-period)^1*P(-1)
+local splitstarter=(Cs(drivespec*(bwslash/"/"+fwslash)^0)+Cc(false))*Ct(lpeg.splitat(S("/\\")^1))
+local absolute=fwslash
+function file.collapsepath(str,anchor)
+ if not str then
+ return
+ end
+ if anchor and not lpegmatch(anchors,str) then
+ str=getcurrentdir().."/"..str
+ end
+ if str=="" or str=="." then
+ return "."
+ elseif lpegmatch(untouched,str) then
+ return lpegmatch(reslasher,str)
+ end
+ local starter,oldelements=lpegmatch(splitstarter,str)
+ local newelements={}
+ local i=#oldelements
+ while i>0 do
+ local element=oldelements[i]
+ if element=='.' then
+ elseif element=='..' then
+ local n=i-1
+ while n>0 do
+ local element=oldelements[n]
+ if element~='..' and element~='.' then
+ oldelements[n]='.'
+ break
+ else
+ n=n-1
+ end
+ end
+ if n<1 then
+ insert(newelements,1,'..')
+ end
+ elseif element~="" then
+ insert(newelements,1,element)
+ end
+ i=i-1
+ end
+ if #newelements==0 then
+ return starter or "."
+ elseif starter then
+ return starter..concat(newelements,'/')
+ elseif lpegmatch(absolute,str) then
+ return "/"..concat(newelements,'/')
+ else
+ return concat(newelements,'/')
+ end
+end
+local validchars=R("az","09","AZ","--","..")
+local pattern_a=lpeg.replacer(1-validchars)
+local pattern_a=Cs((validchars+P(1)/"-")^1)
+local whatever=P("-")^0/""
+local pattern_b=Cs(whatever*(1-whatever*-1)^1)
+function file.robustname(str,strict)
+ if str then
+ str=lpegmatch(pattern_a,str) or str
+ if strict then
+ return lpegmatch(pattern_b,str) or str
+ else
+ return str
end
- return splitter
+ end
end
-
-function lpeg.balancer(left,right)
- left, right = P(left), P(right)
- return P { left * ((1 - left - right) + V(1))^0 * right }
+file.readdata=io.loaddata
+file.savedata=io.savedata
+function file.copy(oldname,newname)
+ if oldname and newname then
+ local data=io.loaddata(oldname)
+ if data and data~="" then
+ file.savedata(newname,data)
+ end
+ end
+end
+local letter=R("az","AZ")+S("_-+")
+local separator=P("://")
+local qualified=period^0*fwslash+letter*colon+letter^1*separator+letter^1*fwslash
+local rootbased=fwslash+letter*colon
+lpeg.patterns.qualified=qualified
+lpeg.patterns.rootbased=rootbased
+function file.is_qualified_path(filename)
+ return filename and lpegmatch(qualified,filename)~=nil
+end
+function file.is_rootbased_path(filename)
+ return filename and lpegmatch(rootbased,filename)~=nil
+end
+function file.strip(name,dir)
+ if name then
+ local b,a=match(name,"^(.-)"..dir.."(.*)$")
+ return a~="" and a or name
+ end
end
+end -- of closure
-local nany = utf8char/""
+do -- create closure to overcome 200 locals limit
-function lpeg.counter(pattern)
- pattern = Cs((P(pattern)/" " + nany)^0)
- return function(str)
- return #match(pattern,str)
- end
-end
+package.loaded["l-md5"] = package.loaded["l-md5"] or true
-if utfgmatch then
+-- original size: 3760, stripped down to: 2088
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local n = 0
- for _ in utfgmatch(str,what) do
- n = n + 1
- end
- return n
- else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
- end
+if not modules then modules={} end modules ['l-md5']={
+ version=1.001,
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+if not md5 then
+ md5=optionalrequire("md5")
+end
+if not md5 then
+ md5={
+ sum=function(str) print("error: md5 is not loaded (sum ignored)") return str end,
+ sumhexa=function(str) print("error: md5 is not loaded (sumhexa ignored)") return str end,
+ }
+end
+local md5,file=md5,file
+local gsub,format,byte=string.gsub,string.format,string.byte
+local md5sum=md5.sum
+local function convert(str,fmt)
+ return (gsub(md5sum(str),".",function(chr) return format(fmt,byte(chr)) end))
+end
+if not md5.HEX then function md5.HEX(str) return convert(str,"%02X") end end
+if not md5.hex then function md5.hex(str) return convert(str,"%02x") end end
+if not md5.dec then function md5.dec(str) return convert(str,"%03i") end end
+function file.needsupdating(oldname,newname,threshold)
+ local oldtime=lfs.attributes(oldname,"modification")
+ if oldtime then
+ local newtime=lfs.attributes(newname,"modification")
+ if not newtime then
+ return true
+ elseif newtime>=oldtime then
+ return false
+ elseif oldtime-newtime<(threshold or 1) then
+ return false
+ else
+ return true
+ end
+ else
+ return false
+ end
+end
+file.needs_updating=file.needsupdating
+function file.syncmtimes(oldname,newname)
+ local oldtime=lfs.attributes(oldname,"modification")
+ if oldtime and lfs.isfile(newname) then
+ lfs.touch(newname,oldtime,oldtime)
+ end
+end
+function file.checksum(name)
+ if md5 then
+ local data=io.loaddata(name)
+ if data then
+ return md5.HEX(data)
end
+ end
+ return nil
+end
+function file.loadchecksum(name)
+ if md5 then
+ local data=io.loaddata(name..".md5")
+ return data and (gsub(data,"%s",""))
+ end
+ return nil
+end
+function file.savechecksum(name,checksum)
+ if not checksum then checksum=file.checksum(name) end
+ if checksum then
+ io.savedata(name..".md5",checksum)
+ return checksum
+ end
+ return nil
+end
-else
- local cache = { }
+end -- of closure
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local p = cache[what]
- if not p then
- p = Cs((P(what)/" " + nany)^0)
- cache[p] = p
- end
- return #match(p,str)
- else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
- end
- end
+do -- create closure to overcome 200 locals limit
-end
+package.loaded["l-url"] = package.loaded["l-url"] or true
-local patterns_escapes = { -- also defines in l-string
- ["%"] = "%%",
- ["."] = "%.",
- ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
- ["["] = "%[", ["]"] = "%]",
- ["("] = "%)", [")"] = "%)",
- -- ["{"] = "%{", ["}"] = "%}"
- -- ["^"] = "%^", ["$"] = "%$",
-}
+-- original size: 11806, stripped down to: 5417
-local simple_escapes = { -- also defines in l-string
- ["-"] = "%-",
- ["."] = "%.",
- ["?"] = ".",
- ["*"] = ".*",
+if not modules then modules={} end modules ['l-url']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
}
-
-local p = Cs((S("-.+*%()[]") / patterns_escapes + anything)^0)
-local s = Cs((S("-.+*%()[]") / simple_escapes + anything)^0)
-
-function string.escapedpattern(str,simple)
- return match(simple and s or p,str)
+local char,format,byte=string.char,string.format,string.byte
+local concat=table.concat
+local tonumber,type=tonumber,type
+local P,C,R,S,Cs,Cc,Ct,Cf,Cg,V=lpeg.P,lpeg.C,lpeg.R,lpeg.S,lpeg.Cs,lpeg.Cc,lpeg.Ct,lpeg.Cf,lpeg.Cg,lpeg.V
+local lpegmatch,lpegpatterns,replacer=lpeg.match,lpeg.patterns,lpeg.replacer
+url=url or {}
+local url=url
+local tochar=function(s) return char(tonumber(s,16)) end
+local colon=P(":")
+local qmark=P("?")
+local hash=P("#")
+local slash=P("/")
+local percent=P("%")
+local endofstring=P(-1)
+local hexdigit=R("09","AF","af")
+local plus=P("+")
+local nothing=Cc("")
+local escapedchar=(percent*C(hexdigit*hexdigit))/tochar
+local escaped=(plus/" ")+escapedchar
+local noslash=P("/")/""
+local schemestr=Cs((escaped+(1-colon-slash-qmark-hash))^2)
+local authoritystr=Cs((escaped+(1- slash-qmark-hash))^0)
+local pathstr=Cs((escaped+(1- qmark-hash))^0)
+local querystr=Cs(((1- hash))^0)
+local fragmentstr=Cs((escaped+(1- endofstring))^0)
+local scheme=schemestr*colon+nothing
+local authority=slash*slash*authoritystr+nothing
+local path=slash*pathstr+nothing
+local query=qmark*querystr+nothing
+local fragment=hash*fragmentstr+nothing
+local validurl=scheme*authority*path*query*fragment
+local parser=Ct(validurl)
+lpegpatterns.url=validurl
+lpegpatterns.urlsplitter=parser
+local escapes={}
+setmetatable(escapes,{ __index=function(t,k)
+ local v=format("%%%02X",byte(k))
+ t[k]=v
+ return v
+end })
+local escaper=Cs((R("09","AZ","az")^1+P(" ")/"%%20"+S("-./_")^1+P(1)/escapes)^0)
+local unescaper=Cs((escapedchar+1)^0)
+lpegpatterns.urlunescaped=escapedchar
+lpegpatterns.urlescaper=escaper
+lpegpatterns.urlunescaper=unescaper
+local function split(str)
+ return (type(str)=="string" and lpegmatch(parser,str)) or str
+end
+local isscheme=schemestr*colon*slash*slash
+local function hasscheme(str)
+ if str then
+ local scheme=lpegmatch(isscheme,str)
+ return scheme~="" and scheme or false
+ else
+ return false
+ end
+end
+local rootletter=R("az","AZ")+S("_-+")
+local separator=P("://")
+local qualified=P(".")^0*P("/")+rootletter*P(":")+rootletter^1*separator+rootletter^1*P("/")
+local rootbased=P("/")+rootletter*P(":")
+local barswapper=replacer("|",":")
+local backslashswapper=replacer("\\","/")
+local equal=P("=")
+local amp=P("&")
+local key=Cs(((escapedchar+1)-equal )^0)
+local value=Cs(((escapedchar+1)-amp -endofstring)^0)
+local splitquery=Cf (Ct("")*P { "sequence",
+ sequence=V("pair")*(amp*V("pair"))^0,
+ pair=Cg(key*equal*value),
+},rawset)
+local function hashed(str)
+ if str=="" then
+ return {
+ scheme="invalid",
+ original=str,
+ }
+ end
+ local s=split(str)
+ local rawscheme=s[1]
+ local rawquery=s[4]
+ local somescheme=rawscheme~=""
+ local somequery=rawquery~=""
+ if not somescheme and not somequery then
+ s={
+ scheme="file",
+ authority="",
+ path=str,
+ query="",
+ fragment="",
+ original=str,
+ noscheme=true,
+ filename=str,
+ }
+ else
+ local authority,path,filename=s[2],s[3]
+ if authority=="" then
+ filename=path
+ elseif path=="" then
+ filename=""
+ else
+ filename=authority.."/"..path
+ end
+ s={
+ scheme=rawscheme,
+ authority=authority,
+ path=path,
+ query=lpegmatch(unescaper,rawquery),
+ queries=lpegmatch(splitquery,rawquery),
+ fragment=s[5],
+ original=str,
+ noscheme=false,
+ filename=filename,
+ }
+ end
+ return s
+end
+url.split=split
+url.hasscheme=hasscheme
+url.hashed=hashed
+function url.addscheme(str,scheme)
+ if hasscheme(str) then
+ return str
+ elseif not scheme then
+ return "file:///"..str
+ else
+ return scheme..":///"..str
+ end
+end
+function url.construct(hash)
+ local fullurl,f={},0
+ local scheme,authority,path,query,fragment=hash.scheme,hash.authority,hash.path,hash.query,hash.fragment
+ if scheme and scheme~="" then
+ f=f+1;fullurl[f]=scheme.."://"
+ end
+ if authority and authority~="" then
+ f=f+1;fullurl[f]=authority
+ end
+ if path and path~="" then
+ f=f+1;fullurl[f]="/"..path
+ end
+ if query and query~="" then
+ f=f+1;fullurl[f]="?"..query
+ end
+ if fragment and fragment~="" then
+ f=f+1;fullurl[f]="#"..fragment
+ end
+ return lpegmatch(escaper,concat(fullurl))
+end
+local pattern=Cs(noslash*R("az","AZ")*(S(":|")/":")*noslash*P(1)^0)
+function url.filename(filename)
+ local spec=hashed(filename)
+ local path=spec.path
+ return (spec.scheme=="file" and path and lpegmatch(pattern,path)) or filename
+end
+local function escapestring(str)
+ return lpegmatch(escaper,str)
+end
+url.escape=escapestring
+function url.query(str)
+ if type(str)=="string" then
+ return lpegmatch(splitquery,str) or ""
+ else
+ return str
+ end
+end
+function url.toquery(data)
+ local td=type(data)
+ if td=="string" then
+ return #str and escape(data) or nil
+ elseif td=="table" then
+ if next(data) then
+ local t={}
+ for k,v in next,data do
+ t[#t+1]=format("%s=%s",k,escapestring(v))
+ end
+ return concat(t,"&")
+ end
+ else
+ end
+end
+local pattern=Cs(noslash^0*(1-noslash*P(-1))^0)
+function url.barepath(path)
+ if not path or path=="" then
+ return ""
+ else
+ return lpegmatch(pattern,path)
+ end
end
--- utf extensies
-
-lpeg.UP = lpeg.P
-if utfcharacters then
+end -- of closure
- function lpeg.US(str)
- local p
- for uc in utfcharacters(str) do
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- return p
- end
+do -- create closure to overcome 200 locals limit
+package.loaded["l-dir"] = package.loaded["l-dir"] or true
-elseif utfgmatch then
+-- original size: 13139, stripped down to: 8196
- function lpeg.US(str)
- local p
- for uc in utfgmatch(str,".") do
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
+if not modules then modules={} end modules ['l-dir']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local type,select=type,select
+local find,gmatch,match,gsub=string.find,string.gmatch,string.match,string.gsub
+local concat,insert,remove=table.concat,table.insert,table.remove
+local lpegmatch=lpeg.match
+local P,S,R,C,Cc,Cs,Ct,Cv,V=lpeg.P,lpeg.S,lpeg.R,lpeg.C,lpeg.Cc,lpeg.Cs,lpeg.Ct,lpeg.Cv,lpeg.V
+dir=dir or {}
+local dir=dir
+local lfs=lfs
+local attributes=lfs.attributes
+local walkdir=lfs.dir
+local isdir=lfs.isdir
+local isfile=lfs.isfile
+local currentdir=lfs.currentdir
+local chdir=lfs.chdir
+if not isdir then
+ function isdir(name)
+ local a=attributes(name)
+ return a and a.mode=="directory"
+ end
+ lfs.isdir=isdir
+end
+if not isfile then
+ function isfile(name)
+ local a=attributes(name)
+ return a and a.mode=="file"
+ end
+ lfs.isfile=isfile
+end
+function dir.current()
+ return (gsub(currentdir(),"\\","/"))
+end
+local lfsisdir=isdir
+local function isdir(path)
+ path=gsub(path,"[/\\]+$","")
+ return lfsisdir(path)
+end
+lfs.isdir=isdir
+local function globpattern(path,patt,recurse,action)
+ if path=="/" then
+ path=path.."."
+ elseif not find(path,"/$") then
+ path=path..'/'
+ end
+ if isdir(path) then
+ for name in walkdir(path) do
+ local full=path..name
+ local mode=attributes(full,'mode')
+ if mode=='file' then
+ if find(full,patt) then
+ action(full)
+ end
+ elseif recurse and (mode=="directory") and (name~='.') and (name~="..") then
+ globpattern(full,patt,recurse,action)
+ end
+ end
+ end
+end
+dir.globpattern=globpattern
+local function collectpattern(path,patt,recurse,result)
+ local ok,scanner
+ result=result or {}
+ if path=="/" then
+ ok,scanner,first=xpcall(function() return walkdir(path..".") end,function() end)
+ else
+ ok,scanner,first=xpcall(function() return walkdir(path) end,function() end)
+ end
+ if ok and type(scanner)=="function" then
+ if not find(path,"/$") then path=path..'/' end
+ for name in scanner,first do
+ local full=path..name
+ local attr=attributes(full)
+ local mode=attr.mode
+ if mode=='file' then
+ if find(full,patt) then
+ result[name]=attr
+ end
+ elseif recurse and (mode=="directory") and (name~='.') and (name~="..") then
+ attr.list=collectpattern(full,patt,recurse)
+ result[name]=attr
+ end
+ end
+ end
+ return result
+end
+dir.collectpattern=collectpattern
+local pattern=Ct {
+ [1]=(C(P(".")+P("/")^1)+C(R("az","AZ")*P(":")*P("/")^0)+Cc("./"))*V(2)*V(3),
+ [2]=C(((1-S("*?/"))^0*P("/"))^0),
+ [3]=C(P(1)^0)
+}
+local filter=Cs ((
+ P("**")/".*"+P("*")/"[^/]*"+P("?")/"[^/]"+P(".")/"%%."+P("+")/"%%+"+P("-")/"%%-"+P(1)
+)^0 )
+local function glob(str,t)
+ if type(t)=="function" then
+ if type(str)=="table" then
+ for s=1,#str do
+ glob(str[s],t)
+ end
+ elseif isfile(str) then
+ t(str)
+ else
+ local split=lpegmatch(pattern,str)
+ if split then
+ local root,path,base=split[1],split[2],split[3]
+ local recurse=find(base,"%*%*")
+ local start=root..path
+ local result=lpegmatch(filter,start..base)
+ globpattern(start,result,recurse,t)
+ end
+ end
+ else
+ if type(str)=="table" then
+ local t=t or {}
+ for s=1,#str do
+ glob(str[s],t)
+ end
+ return t
+ elseif isfile(str) then
+ if t then
+ t[#t+1]=str
+ return t
+ else
+ return { str }
+ end
+ else
+ local split=lpegmatch(pattern,str)
+ if split then
+ local t=t or {}
+ local action=action or function(name) t[#t+1]=name end
+ local root,path,base=split[1],split[2],split[3]
+ local recurse=find(base,"%*%*")
+ local start=root..path
+ local result=lpegmatch(filter,start..base)
+ globpattern(start,result,recurse,action)
+ return t
+ else
+ return {}
+ end
+ end
+ end
+end
+dir.glob=glob
+local function globfiles(path,recurse,func,files)
+ if type(func)=="string" then
+ local s=func
+ func=function(name) return find(name,s) end
+ end
+ files=files or {}
+ local noffiles=#files
+ for name in walkdir(path) do
+ if find(name,"^%.") then
+ else
+ local mode=attributes(name,'mode')
+ if mode=="directory" then
+ if recurse then
+ globfiles(path.."/"..name,recurse,func,files)
end
- return p
- end
-
-else
-
- function lpeg.US(str)
- local p
- local f = function(uc)
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
+ elseif mode=="file" then
+ if not func or func(name) then
+ noffiles=noffiles+1
+ files[noffiles]=path.."/"..name
end
- match((utf8char/f)^0,str)
- return p
+ end
end
-
+ end
+ return files
end
-
-local range = Cs(utf8byte) * (Cs(utf8byte) + Cc(false))
-
-local utfchar = unicode and unicode.utf8 and unicode.utf8.char
-
-function lpeg.UR(str,more)
- local first, last
- if type(str) == "number" then
- first = str
- last = more or first
+dir.globfiles=globfiles
+function dir.ls(pattern)
+ return concat(glob(pattern),"\n")
+end
+local make_indeed=true
+local onwindows=os.type=="windows" or find(os.getenv("PATH"),";")
+if onwindows then
+ function dir.mkdirs(...)
+ local str,pth="",""
+ for i=1,select("#",...) do
+ local s=select(i,...)
+ if s=="" then
+ elseif str=="" then
+ str=s
+ else
+ str=str.."/"..s
+ end
+ end
+ local first,middle,last
+ local drive=false
+ first,middle,last=match(str,"^(//)(//*)(.*)$")
+ if first then
else
- first, last = match(range,str)
- if not last then
- return P(str)
+ first,last=match(str,"^(//)/*(.-)$")
+ if first then
+ middle,last=match(str,"([^/]+)/+(.-)$")
+ if middle then
+ pth="//"..middle
+ else
+ pth="//"..last
+ last=""
+ end
+ else
+ first,middle,last=match(str,"^([a-zA-Z]:)(/*)(.-)$")
+ if first then
+ pth,drive=first..middle,true
+ else
+ middle,last=match(str,"^(/*)(.-)$")
+ if not middle then
+ last=str
+ end
+ end
+ end
+ end
+ for s in gmatch(last,"[^/]+") do
+ if pth=="" then
+ pth=s
+ elseif drive then
+ pth,drive=pth..s,false
+ else
+ pth=pth.."/"..s
+ end
+ if make_indeed and not isdir(pth) then
+ lfs.mkdir(pth)
+ end
+ end
+ return pth,(isdir(pth)==true)
+ end
+else
+ function dir.mkdirs(...)
+ local str,pth="",""
+ for i=1,select("#",...) do
+ local s=select(i,...)
+ if s and s~="" then
+ if str~="" then
+ str=str.."/"..s
+ else
+ str=s
end
+ end
end
- if first == last then
- return P(str)
- elseif utfchar and last - first < 8 then -- a somewhat arbitrary criterium
- local p
- for i=first,last do
- if p then
- p = p + P(utfchar(i))
- else
- p = P(utfchar(i))
- end
+ str=gsub(str,"/+","/")
+ if find(str,"^/") then
+ pth="/"
+ for s in gmatch(str,"[^/]+") do
+ local first=(pth=="/")
+ if first then
+ pth=pth..s
+ else
+ pth=pth.."/"..s
end
- return p -- nil when invalid range
+ if make_indeed and not first and not isdir(pth) then
+ lfs.mkdir(pth)
+ end
+ end
else
- local f = function(b)
- return b >= first and b <= last
+ pth="."
+ for s in gmatch(str,"[^/]+") do
+ pth=pth.."/"..s
+ if make_indeed and not isdir(pth) then
+ lfs.mkdir(pth)
end
- return utf8byte / f -- nil when invalid range
+ end
end
+ return pth,(isdir(pth)==true)
+ end
end
-
-
-
-function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
- if type(list) ~= "table" then
- list = { list, ... }
+dir.makedirs=dir.mkdirs
+if onwindows then
+ function dir.expandname(str)
+ local first,nothing,last=match(str,"^(//)(//*)(.*)$")
+ if first then
+ first=dir.current().."/"
+ end
+ if not first then
+ first,last=match(str,"^(//)/*(.*)$")
+ end
+ if not first then
+ first,last=match(str,"^([a-zA-Z]:)(.*)$")
+ if first and not find(last,"^/") then
+ local d=currentdir()
+ if chdir(first) then
+ first=dir.current()
+ end
+ chdir(d)
+ end
+ end
+ if not first then
+ first,last=dir.current(),str
+ end
+ last=gsub(last,"//","/")
+ last=gsub(last,"/%./","/")
+ last=gsub(last,"^/*","")
+ first=gsub(first,"/*$","")
+ if last=="" or last=="." then
+ return first
+ else
+ return first.."/"..last
end
- -- sort(list) -- longest match first
- local p = P(list[1])
- for l=2,#list do
- p = p + P(list[l])
+ end
+else
+ function dir.expandname(str)
+ if not find(str,"^/") then
+ str=currentdir().."/"..str
end
- return p
+ str=gsub(str,"//","/")
+ str=gsub(str,"/%./","/")
+ str=gsub(str,"(.)/%.$","%1")
+ return str
+ end
end
-
-function lpeg.is_lpeg(p)
- return p and lpegtype(p) == "pattern"
+file.expandname=dir.expandname
+local stack={}
+function dir.push(newdir)
+ insert(stack,currentdir())
+ if newdir and newdir~="" then
+ chdir(newdir)
+ end
+end
+function dir.pop()
+ local d=remove(stack)
+ if d then
+ chdir(d)
+ end
+ return d
end
--- For the moment here, but it might move to utilities. Beware, we need to
--- have the longest keyword first, so 'aaa' comes beforte 'aa' which is why we
--- loop back from the end cq. prepend.
-
-local sort, fastcopy, sortedkeys = table.sort, table.fastcopy, table.sortedkeys -- dependency!
-function lpeg.append(list,pp,delayed,checked)
- local p = pp
- if #list > 0 then
- local keys = fastcopy(list)
- sort(keys)
- for i=#keys,1,-1 do
- local k = keys[i]
- if p then
- p = P(k) + p
- else
- p = P(k)
- end
- end
- elseif delayed then -- hm, it looks like the lpeg parser resolves anyway
- local keys = sortedkeys(list)
- if p then
- for i=1,#keys,1 do
- local k = keys[i]
- local v = list[k]
- p = P(k)/list + p
- end
- else
- for i=1,#keys do
- local k = keys[i]
- local v = list[k]
- if p then
- p = P(k) + p
- else
- p = P(k)
- end
- end
- if p then
- p = p / list
- end
- end
- elseif checked then
- -- problem: substitution gives a capture
- local keys = sortedkeys(list)
- for i=1,#keys do
- local k = keys[i]
- local v = list[k]
- if p then
- if k == v then
- p = P(k) + p
- else
- p = P(k)/v + p
- end
- else
- if k == v then
- p = P(k)
- else
- p = P(k)/v
- end
- end
- end
- else
- local keys = sortedkeys(list)
- for i=1,#keys do
- local k = keys[i]
- local v = list[k]
- if p then
- p = P(k)/v + p
- else
- p = P(k)/v
- end
- end
- end
- return p
-end
+end -- of closure
--- inspect(lpeg.append({ a = "1", aa = "1", aaa = "1" } ,nil,true))
--- inspect(lpeg.append({ ["degree celsius"] = "1", celsius = "1", degree = "1" } ,nil,true))
+do -- create closure to overcome 200 locals limit
--- function lpeg.exact_match(words,case_insensitive)
--- local pattern = concat(words)
--- if case_insensitive then
--- local pattern = S(upper(characters)) + S(lower(characters))
--- local list = { }
--- for i=1,#words do
--- list[lower(words[i])] = true
--- end
--- return Cmt(pattern^1, function(_,i,s)
--- return list[lower(s)] and i
--- end)
--- else
--- local pattern = S(concat(words))
--- local list = { }
--- for i=1,#words do
--- list[words[i]] = true
--- end
--- return Cmt(pattern^1, function(_,i,s)
--- return list[s] and i
--- end)
--- end
--- end
+package.loaded["l-boolean"] = package.loaded["l-boolean"] or true
--- experiment:
+-- original size: 1781, stripped down to: 1503
-local function make(t)
- local p
--- for k, v in next, t do
- for k, v in table.sortedhash(t) do
- if not p then
- if next(v) then
- p = P(k) * make(v)
- else
- p = P(k)
- end
- else
- if next(v) then
- p = p + P(k) * make(v)
- else
- p = p + P(k)
- end
- end
- end
- return p
+if not modules then modules={} end modules ['l-boolean']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local type,tonumber=type,tonumber
+boolean=boolean or {}
+local boolean=boolean
+function boolean.tonumber(b)
+ if b then return 1 else return 0 end
end
-
-function lpeg.utfchartabletopattern(list)
- local tree = { }
- for i=1,#list do
- local t = tree
- for c in gmatch(list[i],".") do
- if not t[c] then
- t[c] = { }
- end
- t = t[c]
- end
+function toboolean(str,tolerant)
+ if str==nil then
+ return false
+ elseif str==false then
+ return false
+ elseif str==true then
+ return true
+ elseif str=="true" then
+ return true
+ elseif str=="false" then
+ return false
+ elseif not tolerant then
+ return false
+ elseif str==0 then
+ return false
+ elseif (tonumber(str) or 0)>0 then
+ return true
+ else
+ return str=="yes" or str=="on" or str=="t"
+ end
+end
+string.toboolean=toboolean
+function string.booleanstring(str)
+ if str=="0" then
+ return false
+ elseif str=="1" then
+ return true
+ elseif str=="" then
+ return false
+ elseif str=="false" then
+ return false
+ elseif str=="true" then
+ return true
+ elseif (tonumber(str) or 0)>0 then
+ return true
+ else
+ return str=="yes" or str=="on" or str=="t"
+ end
+end
+function string.is_boolean(str,default)
+ if type(str)=="string" then
+ if str=="true" or str=="yes" or str=="on" or str=="t" then
+ return true
+ elseif str=="false" or str=="no" or str=="off" or str=="f" then
+ return false
end
- return make(tree)
+ end
+ return default
end
--- inspect ( lpeg.utfchartabletopattern {
--- utfchar(0x00A0), -- nbsp
--- utfchar(0x2000), -- enquad
--- utfchar(0x2001), -- emquad
--- utfchar(0x2002), -- enspace
--- utfchar(0x2003), -- emspace
--- utfchar(0x2004), -- threeperemspace
--- utfchar(0x2005), -- fourperemspace
--- utfchar(0x2006), -- sixperemspace
--- utfchar(0x2007), -- figurespace
--- utfchar(0x2008), -- punctuationspace
--- utfchar(0x2009), -- breakablethinspace
--- utfchar(0x200A), -- hairspace
--- utfchar(0x200B), -- zerowidthspace
--- utfchar(0x202F), -- narrownobreakspace
--- utfchar(0x205F), -- math thinspace
--- } )
-
end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-io'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local io = io
-local byte, find, gsub, format = string.byte, string.find, string.gsub, string.format
-local concat = table.concat
-local type = type
+package.loaded["l-unicode"] = package.loaded["l-unicode"] or true
-if string.find(os.getenv("PATH"),";") then
- io.fileseparator, io.pathseparator = "\\", ";"
-else
- io.fileseparator, io.pathseparator = "/" , ":"
-end
+-- original size: 26810, stripped down to: 11943
-function io.loaddata(filename,textmode)
- local f = io.open(filename,(textmode and 'r') or 'rb')
- if f then
- local data = f:read('*all')
- f:close()
- return data
+if not modules then modules={} end modules ['l-unicode']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+utf=utf or (unicode and unicode.utf8) or {}
+utf.characters=utf.characters or string.utfcharacters
+utf.values=utf.values or string.utfvalues
+local type=type
+local char,byte,format,sub=string.char,string.byte,string.format,string.sub
+local concat=table.concat
+local P,C,R,Cs,Ct,Cmt,Cc,Carg,Cp=lpeg.P,lpeg.C,lpeg.R,lpeg.Cs,lpeg.Ct,lpeg.Cmt,lpeg.Cc,lpeg.Carg,lpeg.Cp
+local lpegmatch,patterns=lpeg.match,lpeg.patterns
+local bytepairs=string.bytepairs
+local finder=lpeg.finder
+local replacer=lpeg.replacer
+local utfvalues=utf.values
+local utfgmatch=utf.gmatch
+local p_utftype=patterns.utftype
+local p_utfoffset=patterns.utfoffset
+local p_utf8char=patterns.utf8char
+local p_utf8byte=patterns.utf8byte
+local p_utfbom=patterns.utfbom
+local p_newline=patterns.newline
+local p_whitespace=patterns.whitespace
+if not unicode then
+ unicode={ utf=utf }
+end
+if not utf.char then
+ local floor,char=math.floor,string.char
+ function utf.char(n)
+ if n<0x80 then
+ return char(n)
+ elseif n<0x800 then
+ return char(
+ 0xC0+floor(n/0x40),
+ 0x80+(n%0x40)
+ )
+ elseif n<0x10000 then
+ return char(
+ 0xE0+floor(n/0x1000),
+ 0x80+(floor(n/0x40)%0x40),
+ 0x80+(n%0x40)
+ )
+ elseif n<0x200000 then
+ return char(
+ 0xF0+floor(n/0x40000),
+ 0x80+(floor(n/0x1000)%0x40),
+ 0x80+(floor(n/0x40)%0x40),
+ 0x80+(n%0x40)
+ )
else
- return nil
+ return ""
+ end
+ end
+end
+if not utf.byte then
+ local utf8byte=patterns.utf8byte
+ function utf.byte(c)
+ return lpegmatch(utf8byte,c)
+ end
+end
+local utfchar,utfbyte=utf.char,utf.byte
+function utf.filetype(data)
+ return data and lpegmatch(p_utftype,data) or "unknown"
+end
+local toentities=Cs (
+ (
+ patterns.utf8one+(
+ patterns.utf8two+patterns.utf8three+patterns.utf8four
+ )/function(s) local b=utfbyte(s) if b<127 then return s else return format("%X;",b) end end
+ )^0
+)
+patterns.toentities=toentities
+function utf.toentities(str)
+ return lpegmatch(toentities,str)
+end
+local one=P(1)
+local two=C(1)*C(1)
+local four=C(R(utfchar(0xD8),utfchar(0xFF)))*C(1)*C(1)*C(1)
+local pattern=P("\254\255")*Cs((
+ four/function(a,b,c,d)
+ local ab=0xFF*byte(a)+byte(b)
+ local cd=0xFF*byte(c)+byte(d)
+ return utfchar((ab-0xD800)*0x400+(cd-0xDC00)+0x10000)
+ end+two/function(a,b)
+ return utfchar(byte(a)*256+byte(b))
+ end+one
+ )^1 )+P("\255\254")*Cs((
+ four/function(b,a,d,c)
+ local ab=0xFF*byte(a)+byte(b)
+ local cd=0xFF*byte(c)+byte(d)
+ return utfchar((ab-0xD800)*0x400+(cd-0xDC00)+0x10000)
+ end+two/function(b,a)
+ return utfchar(byte(a)*256+byte(b))
+ end+one
+ )^1 )
+function string.toutf(s)
+ return lpegmatch(pattern,s) or s
+end
+local validatedutf=Cs (
+ (
+ patterns.utf8one+patterns.utf8two+patterns.utf8three+patterns.utf8four+P(1)/"�"
+ )^0
+)
+patterns.validatedutf=validatedutf
+function utf.is_valid(str)
+ return type(str)=="string" and lpegmatch(validatedutf,str) or false
+end
+if not utf.len then
+ local n,f=0,1
+ local utfcharcounter=patterns.utfbom^-1*Cmt (
+ Cc(1)*patterns.utf8one^1+Cc(2)*patterns.utf8two^1+Cc(3)*patterns.utf8three^1+Cc(4)*patterns.utf8four^1,
+ function(_,t,d)
+ n=n+(t-f)/d
+ f=t
+ return true
+ end
+ )^0
+ function utf.len(str)
+ n,f=0,1
+ lpegmatch(utfcharcounter,str or "")
+ return n
+ end
+end
+utf.length=utf.len
+if not utf.sub then
+ local utflength=utf.length
+ local b,e,n,first,last=0,0,0,0,0
+ local function slide_zero(s,p)
+ n=n+1
+ if n>=last then
+ e=p-1
+ else
+ return p
end
-end
-
-function io.savedata(filename,data,joiner)
- local f = io.open(filename,"wb")
- if f then
- if type(data) == "table" then
- f:write(concat(data,joiner or ""))
- elseif type(data) == "function" then
- data(f)
+ end
+ local function slide_one(s,p)
+ n=n+1
+ if n==first then
+ b=p
+ end
+ if n>=last then
+ e=p-1
+ else
+ return p
+ end
+ end
+ local function slide_two(s,p)
+ n=n+1
+ if n==first then
+ b=p
+ else
+ return true
+ end
+ end
+ local pattern_zero=Cmt(p_utf8char,slide_zero)^0
+ local pattern_one=Cmt(p_utf8char,slide_one )^0
+ local pattern_two=Cmt(p_utf8char,slide_two )^0
+ function utf.sub(str,start,stop)
+ if not start then
+ return str
+ end
+ if start==0 then
+ start=1
+ end
+ if not stop then
+ if start<0 then
+ local l=utflength(str)
+ start=l+start
+ else
+ start=start-1
+ end
+ b,n,first=0,0,start
+ lpegmatch(pattern_two,str)
+ if n>=first then
+ return sub(str,b)
+ else
+ return ""
+ end
+ end
+ if start<0 or stop<0 then
+ local l=utf.length(str)
+ if start<0 then
+ start=l+start
+ if start<=0 then
+ start=1
else
- f:write(data or "")
+ start=start+1
end
- f:close()
- io.flush()
- return true
+ end
+ if stop<0 then
+ stop=l+stop
+ if stop==0 then
+ stop=1
+ else
+ stop=stop+1
+ end
+ end
+ end
+ if start>stop then
+ return ""
+ elseif start>1 then
+ b,e,n,first,last=0,0,0,start-1,stop
+ lpegmatch(pattern_one,str)
+ if n>=first and e==0 then
+ e=#str
+ end
+ return sub(str,b,e)
else
- return false
- end
-end
-
-function io.exists(filename)
- local f = io.open(filename)
- if f == nil then
- return false
+ b,e,n,last=1,0,0,stop
+ lpegmatch(pattern_zero,str)
+ if e==0 then
+ e=#str
+ end
+ return sub(str,b,e)
+ end
+ end
+end
+function utf.remapper(mapping)
+ local pattern=Cs((p_utf8char/mapping)^0)
+ return function(str)
+ if not str or str=="" then
+ return ""
else
- assert(f:close())
- return true
- end
-end
-
-function io.size(filename)
- local f = io.open(filename)
- if f == nil then
- return 0
+ return lpegmatch(pattern,str)
+ end
+ end,pattern
+end
+function utf.replacer(t)
+ local r=replacer(t,false,false,true)
+ return function(str)
+ return lpegmatch(r,str)
+ end
+end
+function utf.subtituter(t)
+ local f=finder (t)
+ local r=replacer(t,false,false,true)
+ return function(str)
+ local i=lpegmatch(f,str)
+ if not i then
+ return str
+ elseif i>#str then
+ return str
else
- local s = f:seek("end")
- assert(f:close())
- return s
- end
+ return lpegmatch(r,str)
+ end
+ end
+end
+local utflinesplitter=p_utfbom^-1*lpeg.tsplitat(p_newline)
+local utfcharsplitter_ows=p_utfbom^-1*Ct(C(p_utf8char)^0)
+local utfcharsplitter_iws=p_utfbom^-1*Ct((p_whitespace^1+C(p_utf8char))^0)
+local utfcharsplitter_raw=Ct(C(p_utf8char)^0)
+patterns.utflinesplitter=utflinesplitter
+function utf.splitlines(str)
+ return lpegmatch(utflinesplitter,str or "")
+end
+function utf.split(str,ignorewhitespace)
+ if ignorewhitespace then
+ return lpegmatch(utfcharsplitter_iws,str or "")
+ else
+ return lpegmatch(utfcharsplitter_ows,str or "")
+ end
+end
+function utf.totable(str)
+ return lpegmatch(utfcharsplitter_raw,str)
+end
+function utf.magic(f)
+ local str=f:read(4) or ""
+ local off=lpegmatch(p_utfoffset,str)
+ if off<4 then
+ f:seek('set',off)
+ end
+ return lpegmatch(p_utftype,str)
end
-
-function io.noflines(f)
- if type(f) == "string" then
- local f = io.open(filename)
- local n = f and io.noflines(f) or 0
- assert(f:close())
- return n
- else
- local n = 0
- for _ in f:lines() do
- n = n + 1
+local function utf16_to_utf8_be(t)
+ if type(t)=="string" then
+ t=lpegmatch(utflinesplitter,t)
+ end
+ local result={}
+ for i=1,#t do
+ local r,more=0,0
+ for left,right in bytepairs(t[i]) do
+ if right then
+ local now=256*left+right
+ if more>0 then
+ now=(more-0xD800)*0x400+(now-0xDC00)+0x10000
+ more=0
+ r=r+1
+ result[r]=utfchar(now)
+ elseif now>=0xD800 and now<=0xDBFF then
+ more=now
+ else
+ r=r+1
+ result[r]=utfchar(now)
end
- f:seek('set',0)
- return n
+ end
end
+ t[i]=concat(result,"",1,r)
+ end
+ return t
end
-
-local nextchar = {
- [ 4] = function(f)
- return f:read(1,1,1,1)
- end,
- [ 2] = function(f)
- return f:read(1,1)
- end,
- [ 1] = function(f)
- return f:read(1)
- end,
- [-2] = function(f)
- local a, b = f:read(1,1)
- return b, a
- end,
- [-4] = function(f)
- local a, b, c, d = f:read(1,1,1,1)
- return d, c, b, a
- end
-}
-
-function io.characters(f,n)
- if f then
- return nextchar[n or 1], f
+local function utf16_to_utf8_le(t)
+ if type(t)=="string" then
+ t=lpegmatch(utflinesplitter,t)
+ end
+ local result={}
+ for i=1,#t do
+ local r,more=0,0
+ for left,right in bytepairs(t[i]) do
+ if right then
+ local now=256*right+left
+ if more>0 then
+ now=(more-0xD800)*0x400+(now-0xDC00)+0x10000
+ more=0
+ r=r+1
+ result[r]=utfchar(now)
+ elseif now>=0xD800 and now<=0xDBFF then
+ more=now
+ else
+ r=r+1
+ result[r]=utfchar(now)
+ end
+ end
end
+ t[i]=concat(result,"",1,r)
+ end
+ return t
end
-
-local nextbyte = {
- [4] = function(f)
- local a, b, c, d = f:read(1,1,1,1)
- if d then
- return byte(a), byte(b), byte(c), byte(d)
- end
- end,
- [3] = function(f)
- local a, b, c = f:read(1,1,1)
- if b then
- return byte(a), byte(b), byte(c)
- end
- end,
- [2] = function(f)
- local a, b = f:read(1,1)
- if b then
- return byte(a), byte(b)
- end
- end,
- [1] = function (f)
- local a = f:read(1)
- if a then
- return byte(a)
- end
- end,
- [-2] = function (f)
- local a, b = f:read(1,1)
- if b then
- return byte(b), byte(a)
- end
- end,
- [-3] = function(f)
- local a, b, c = f:read(1,1,1)
- if b then
- return byte(c), byte(b), byte(a)
- end
- end,
- [-4] = function(f)
- local a, b, c, d = f:read(1,1,1,1)
- if d then
- return byte(d), byte(c), byte(b), byte(a)
+local function utf32_to_utf8_be(t)
+ if type(t)=="string" then
+ t=lpegmatch(utflinesplitter,t)
+ end
+ local result={}
+ for i=1,#t do
+ local r,more=0,-1
+ for a,b in bytepairs(t[i]) do
+ if a and b then
+ if more<0 then
+ more=256*256*256*a+256*256*b
+ else
+ r=r+1
+ result[t]=utfchar(more+256*a+b)
+ more=-1
end
+ else
+ break
+ end
end
-}
-
-function io.bytes(f,n)
- if f then
- return nextbyte[n or 1], f
- else
- return nil, nil
- end
+ t[i]=concat(result,"",1,r)
+ end
+ return t
end
-
-function io.ask(question,default,options)
- while true do
- io.write(question)
- if options then
- io.write(format(" [%s]",concat(options,"|")))
- end
- if default then
- io.write(format(" [%s]",default))
- end
- io.write(format(" "))
- io.flush()
- local answer = io.read()
- answer = gsub(answer,"^%s*(.*)%s*$","%1")
- if answer == "" and default then
- return default
- elseif not options then
- return answer
+local function utf32_to_utf8_le(t)
+ if type(t)=="string" then
+ t=lpegmatch(utflinesplitter,t)
+ end
+ local result={}
+ for i=1,#t do
+ local r,more=0,-1
+ for a,b in bytepairs(t[i]) do
+ if a and b then
+ if more<0 then
+ more=256*b+a
else
- for k=1,#options do
- if options[k] == answer then
- return answer
- end
- end
- local pattern = "^" .. answer
- for k=1,#options do
- local v = options[k]
- if find(v,pattern) then
- return v
- end
- end
+ r=r+1
+ result[t]=utfchar(more+256*256*256*b+256*256*a)
+ more=-1
end
+ else
+ break
+ end
end
+ t[i]=concat(result,"",1,r)
+ end
+ return t
end
-
-local function readnumber(f,n,m)
- if m then
- f:seek("set",n)
- n = m
- end
- if n == 1 then
- return byte(f:read(1))
- elseif n == 2 then
- local a, b = byte(f:read(2),1,2)
- return 256 * a + b
- elseif n == 3 then
- local a, b, c = byte(f:read(3),1,3)
- return 256*256 * a + 256 * b + c
- elseif n == 4 then
- local a, b, c, d = byte(f:read(4),1,4)
- return 256*256*256 * a + 256*256 * b + 256 * c + d
- elseif n == 8 then
- local a, b = readnumber(f,4), readnumber(f,4)
- return 256 * a + b
- elseif n == 12 then
- local a, b, c = readnumber(f,4), readnumber(f,4), readnumber(f,4)
- return 256*256 * a + 256 * b + c
- elseif n == -2 then
- local b, a = byte(f:read(2),1,2)
- return 256*a + b
- elseif n == -3 then
- local c, b, a = byte(f:read(3),1,3)
- return 256*256 * a + 256 * b + c
- elseif n == -4 then
- local d, c, b, a = byte(f:read(4),1,4)
- return 256*256*256 * a + 256*256 * b + 256*c + d
- elseif n == -8 then
- local h, g, f, e, d, c, b, a = byte(f:read(8),1,8)
- return 256*256*256*256*256*256*256 * a +
- 256*256*256*256*256*256 * b +
- 256*256*256*256*256 * c +
- 256*256*256*256 * d +
- 256*256*256 * e +
- 256*256 * f +
- 256 * g +
- h
+utf.utf32_to_utf8_be=utf32_to_utf8_be
+utf.utf32_to_utf8_le=utf32_to_utf8_le
+utf.utf16_to_utf8_be=utf16_to_utf8_be
+utf.utf16_to_utf8_le=utf16_to_utf8_le
+function utf.utf8_to_utf8(t)
+ return type(t)=="string" and lpegmatch(utflinesplitter,t) or t
+end
+function utf.utf16_to_utf8(t,endian)
+ return endian and utf16_to_utf8_be(t) or utf16_to_utf8_le(t) or t
+end
+function utf.utf32_to_utf8(t,endian)
+ return endian and utf32_to_utf8_be(t) or utf32_to_utf8_le(t) or t
+end
+local function little(c)
+ local b=byte(c)
+ if b<0x10000 then
+ return char(b%256,b/256)
+ else
+ b=b-0x10000
+ local b1,b2=b/1024+0xD800,b%1024+0xDC00
+ return char(b1%256,b1/256,b2%256,b2/256)
+ end
+end
+local function big(c)
+ local b=byte(c)
+ if b<0x10000 then
+ return char(b/256,b%256)
+ else
+ b=b-0x10000
+ local b1,b2=b/1024+0xD800,b%1024+0xDC00
+ return char(b1/256,b1%256,b2/256,b2%256)
+ end
+end
+local _,l_remap=utf.remapper(little)
+local _,b_remap=utf.remapper(big)
+function utf.utf8_to_utf16(str,littleendian)
+ if littleendian then
+ return char(255,254)..lpegmatch(l_remap,str)
+ else
+ return char(254,255)..lpegmatch(b_remap,str)
+ end
+end
+local pattern=Cs (
+ (p_utf8byte/function(unicode ) return format("0x%04X",unicode) end)*(p_utf8byte*Carg(1)/function(unicode,separator) return format("%s0x%04X",separator,unicode) end)^0
+)
+function utf.tocodes(str,separator)
+ return lpegmatch(pattern,str,1,separator or " ")
+end
+function utf.ustring(s)
+ return format("U+%05X",type(s)=="number" and s or utfbyte(s))
+end
+function utf.xstring(s)
+ return format("0x%05X",type(s)=="number" and s or utfbyte(s))
+end
+local p_nany=p_utf8char/""
+if utfgmatch then
+ function utf.count(str,what)
+ if type(what)=="string" then
+ local n=0
+ for _ in utfgmatch(str,what) do
+ n=n+1
+ end
+ return n
+ else
+ return #lpegmatch(Cs((P(what)/" "+p_nany)^0),str)
+ end
+ end
+else
+ local cache={}
+ function utf.count(str,what)
+ if type(what)=="string" then
+ local p=cache[what]
+ if not p then
+ p=Cs((P(what)/" "+p_nany)^0)
+ cache[p]=p
+ end
+ return #lpegmatch(p,str)
+ else
+ return #lpegmatch(Cs((P(what)/" "+p_nany)^0),str)
+ end
+ end
+end
+if not utf.characters then
+ function utf.characters(str)
+ return gmatch(str,".[\128-\191]*")
+ end
+ string.utfcharacters=utf.characters
+end
+if not utf.values then
+ local find=string.find
+ local dummy=function()
+ end
+ function utf.values(str)
+ local n=#str
+ if n==0 then
+ return dummy
+ elseif n==1 then
+ return function() return utfbyte(str) end
else
- return 0
+ local p=1
+ return function()
+ local b,e=find(str,".[\128-\191]*",p)
+ if b then
+ p=e+1
+ return utfbyte(sub(str,b,e))
+ end
+ end
end
+ end
+ string.utfvalues=utf.values
end
-io.readnumber = readnumber
-function io.readstring(f,n,m)
- if m then
- f:seek("set",n)
- n = m
- end
- local str = gsub(f:read(n),"%z","")
- return str
-end
+end -- of closure
---
+do -- create closure to overcome 200 locals limit
+
+package.loaded["l-math"] = package.loaded["l-math"] or true
-if not io.i_limiter then function io.i_limiter() end end -- dummy so we can test safely
-if not io.o_limiter then function io.o_limiter() end end -- dummy so we can test safely
+-- original size: 915, stripped down to: 836
+
+if not modules then modules={} end modules ['l-math']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local floor,sin,cos,tan=math.floor,math.sin,math.cos,math.tan
+if not math.round then
+ function math.round(x) return floor(x+0.5) end
+end
+if not math.div then
+ function math.div(n,m) return floor(n/m) end
+end
+if not math.mod then
+ function math.mod(n,m) return n%m end
+end
+local pipi=2*math.pi/360
+if not math.sind then
+ function math.sind(d) return sin(d*pipi) end
+ function math.cosd(d) return cos(d*pipi) end
+ function math.tand(d) return tan(d*pipi) end
+end
+if not math.odd then
+ function math.odd (n) return n%2~=0 end
+ function math.even(n) return n%2==0 end
+end
end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-number'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
+package.loaded["util-str"] = package.loaded["util-str"] or true
--- this module will be replaced when we have the bit library
+-- original size: 22834, stripped down to: 12570
+if not modules then modules={} end modules ['util-str']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+utilities=utilities or {}
+utilities.strings=utilities.strings or {}
+local strings=utilities.strings
+local format,gsub,rep,sub=string.format,string.gsub,string.rep,string.sub
+local load,dump=load,string.dump
+local tonumber,type,tostring=tonumber,type,tostring
+local unpack,concat=table.unpack,table.concat
+local P,V,C,S,R,Ct,Cs,Cp,Carg,Cc=lpeg.P,lpeg.V,lpeg.C,lpeg.S,lpeg.R,lpeg.Ct,lpeg.Cs,lpeg.Cp,lpeg.Carg,lpeg.Cc
+local patterns,lpegmatch=lpeg.patterns,lpeg.match
+local utfchar,utfbyte=utf.char,utf.byte
+local loadstripped=_LUAVERSION<5.2 and load or function(str)
+ return load(dump(load(str),true))
+end
+if not number then number={} end
+local stripper=patterns.stripzeros
+local function points(n)
+ return (not n or n==0) and "0pt" or lpegmatch(stripper,format("%.5fpt",n/65536))
+end
+local function basepoints(n)
+ return (not n or n==0) and "0bp" or lpegmatch(stripper,format("%.5fbp",n*(7200/7227)/65536))
+end
+number.points=points
+number.basepoints=basepoints
+local rubish=patterns.spaceortab^0*patterns.newline
+local anyrubish=patterns.spaceortab+patterns.newline
+local anything=patterns.anything
+local stripped=(patterns.spaceortab^1/"")*patterns.newline
+local leading=rubish^0/""
+local trailing=(anyrubish^1*patterns.endofstring)/""
+local redundant=rubish^3/"\n"
+local pattern=Cs(leading*(trailing+redundant+stripped+anything)^0)
+function strings.collapsecrlf(str)
+ return lpegmatch(pattern,str)
+end
+local repeaters={}
+function strings.newrepeater(str,offset)
+ offset=offset or 0
+ local s=repeaters[str]
+ if not s then
+ s={}
+ repeaters[str]=s
+ end
+ local t=s[offset]
+ if t then
+ return t
+ end
+ t={}
+ setmetatable(t,{ __index=function(t,k)
+ if not k then
+ return ""
+ end
+ local n=k+offset
+ local s=n>0 and rep(str,n) or ""
+ t[k]=s
+ return s
+ end })
+ s[offset]=t
+ return t
+end
+local extra,tab,start=0,0,4,0
+local nspaces=strings.newrepeater(" ")
+string.nspaces=nspaces
+local pattern=Carg(1)/function(t)
+ extra,tab,start=0,t or 7,1
+ end*Cs((
+ Cp()*patterns.tab/function(position)
+ local current=(position-start+1)+extra
+ local spaces=tab-(current-1)%tab
+ if spaces>0 then
+ extra=extra+spaces-1
+ return nspaces[spaces]
+ else
+ return ""
+ end
+ end+patterns.newline*Cp()/function(position)
+ extra,start=0,position
+ end+patterns.anything
+ )^1)
+function strings.tabtospace(str,tab)
+ return lpegmatch(pattern,str,1,tab or 7)
+end
+function strings.striplong(str)
+ str=gsub(str,"^%s*","")
+ str=gsub(str,"[\n\r]+ *","\n")
+ return str
+end
+function strings.nice(str)
+ str=gsub(str,"[:%-+_]+"," ")
+ return str
+end
+local n=0
+local sequenced=table.sequenced
+function string.autodouble(s,sep)
+ if s==nil then
+ return '""'
+ end
+ local t=type(s)
+ if t=="number" then
+ return tostring(s)
+ end
+ if t=="table" then
+ return ('"'..sequenced(s,sep or ",")..'"')
+ end
+ return ('"'..tostring(s)..'"')
+end
+function string.autosingle(s,sep)
+ if s==nil then
+ return "''"
+ end
+ local t=type(s)
+ if t=="number" then
+ return tostring(s)
+ end
+ if t=="table" then
+ return ("'"..sequenced(s,sep or ",").."'")
+ end
+ return ("'"..tostring(s).."'")
+end
+local tracedchars={}
+string.tracedchars=tracedchars
+strings.tracers=tracedchars
+function string.tracedchar(b)
+ if type(b)=="number" then
+ return tracedchars[b] or (utfchar(b).." (U+"..format('%05X',b)..")")
+ else
+ local c=utfbyte(b)
+ return tracedchars[c] or (b.." (U+"..format('%05X',c)..")")
+ end
+end
+function number.signed(i)
+ if i>0 then
+ return "+",i
+ else
+ return "-",-i
+ end
+end
+local preamble=[[
+local type = type
local tostring = tostring
-local format, floor, match, rep = string.format, math.floor, string.match, string.rep
-local concat, insert = table.concat, table.insert
+local tonumber = tonumber
+local format = string.format
+local concat = table.concat
+local signed = number.signed
+local points = number.points
+local basepoints = number.basepoints
+local utfchar = utf.char
+local utfbyte = utf.byte
local lpegmatch = lpeg.match
-
-number = number or { }
-local number = number
-
--- a,b,c,d,e,f = number.toset(100101)
-
-function number.toset(n)
- return match(tostring(n),"(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.?)")
-end
-
-function number.toevenhex(n)
- local s = format("%X",n)
- if #s % 2 == 0 then
- return s
+local nspaces = string.nspaces
+local tracedchar = string.tracedchar
+local autosingle = string.autosingle
+local autodouble = string.autodouble
+local sequenced = table.sequenced
+]]
+local template=[[
+%s
+%s
+return function(%s) return %s end
+]]
+local arguments={ "a1" }
+setmetatable(arguments,{ __index=function(t,k)
+ local v=t[k-1]..",a"..k
+ t[k]=v
+ return v
+ end
+})
+local prefix_any=C((S("+- .")+R("09"))^0)
+local prefix_tab=C((1-R("az","AZ","09","%%"))^0)
+local format_s=function(f)
+ n=n+1
+ if f and f~="" then
+ return format("format('%%%ss',a%s)",f,n)
+ else
+ return format("(a%s or '')",n)
+ end
+end
+local format_S=function(f)
+ n=n+1
+ if f and f~="" then
+ return format("format('%%%ss',tostring(a%s))",f,n)
+ else
+ return format("tostring(a%s)",n)
+ end
+end
+local format_q=function()
+ n=n+1
+ return format("(a%s and format('%%q',a%s) or '')",n,n)
+end
+local format_Q=function()
+ n=n+1
+ return format("format('%%q',tostring(a%s))",n)
+end
+local format_i=function(f)
+ n=n+1
+ if f and f~="" then
+ return format("format('%%%si',a%s)",f,n)
+ else
+ return format("a%s",n)
+ end
+end
+local format_d=format_i
+local format_I=function(f)
+ n=n+1
+ return format("format('%%s%%%si',signed(a%s))",f,n)
+end
+local format_f=function(f)
+ n=n+1
+ return format("format('%%%sf',a%s)",f,n)
+end
+local format_g=function(f)
+ n=n+1
+ return format("format('%%%sg',a%s)",f,n)
+end
+local format_G=function(f)
+ n=n+1
+ return format("format('%%%sG',a%s)",f,n)
+end
+local format_e=function(f)
+ n=n+1
+ return format("format('%%%se',a%s)",f,n)
+end
+local format_E=function(f)
+ n=n+1
+ return format("format('%%%sE',a%s)",f,n)
+end
+local format_x=function(f)
+ n=n+1
+ return format("format('%%%sx',a%s)",f,n)
+end
+local format_X=function(f)
+ n=n+1
+ return format("format('%%%sX',a%s)",f,n)
+end
+local format_o=function(f)
+ n=n+1
+ return format("format('%%%so',a%s)",f,n)
+end
+local format_c=function()
+ n=n+1
+ return format("utfchar(a%s)",n)
+end
+local format_C=function()
+ n=n+1
+ return format("tracedchar(a%s)",n)
+end
+local format_r=function(f)
+ n=n+1
+ return format("format('%%%s.0f',a%s)",f,n)
+end
+local format_h=function(f)
+ n=n+1
+ if f=="-" then
+ f=sub(f,2)
+ return format("format('%%%sx',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n)
+ else
+ return format("format('0x%%%sx',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n)
+ end
+end
+local format_H=function(f)
+ n=n+1
+ if f=="-" then
+ f=sub(f,2)
+ return format("format('%%%sX',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n)
+ else
+ return format("format('0x%%%sX',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n)
+ end
+end
+local format_u=function(f)
+ n=n+1
+ if f=="-" then
+ f=sub(f,2)
+ return format("format('%%%sx',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n)
+ else
+ return format("format('u+%%%sx',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n)
+ end
+end
+local format_U=function(f)
+ n=n+1
+ if f=="-" then
+ f=sub(f,2)
+ return format("format('%%%sX',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n)
+ else
+ return format("format('U+%%%sX',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n)
+ end
+end
+local format_p=function()
+ n=n+1
+ return format("points(a%s)",n)
+end
+local format_b=function()
+ n=n+1
+ return format("basepoints(a%s)",n)
+end
+local format_t=function(f)
+ n=n+1
+ if f and f~="" then
+ return format("concat(a%s,%q)",n,f)
+ else
+ return format("concat(a%s)",n)
+ end
+end
+local format_T=function(f)
+ n=n+1
+ if f and f~="" then
+ return format("sequenced(a%s,%q)",n,f)
+ else
+ return format("sequenced(a%s)",n)
+ end
+end
+local format_l=function()
+ n=n+1
+ return format("(a%s and 'true' or 'false')",n)
+end
+local format_L=function()
+ n=n+1
+ return format("(a%s and 'TRUE' or 'FALSE')",n)
+end
+local format_N=function()
+ n=n+1
+ return format("tostring(tonumber(a%s) or a%s)",n,n)
+end
+local format_a=function(f)
+ n=n+1
+ if f and f~="" then
+ return format("autosingle(a%s,%q)",n,f)
+ else
+ return format("autosingle(a%s)",n)
+ end
+end
+local format_A=function(f)
+ n=n+1
+ if f and f~="" then
+ return format("autodouble(a%s,%q)",n,f)
+ else
+ return format("autodouble(a%s)",n)
+ end
+end
+local format_w=function(f)
+ n=n+1
+ f=tonumber(f)
+ if f then
+ return format("nspaces[%s+a%s]",f,n)
+ else
+ return format("nspaces[a%s]",n)
+ end
+end
+local format_W=function(f)
+ return format("nspaces[%s]",tonumber(f) or 0)
+end
+local format_rest=function(s)
+ return format("%q",s)
+end
+local format_extension=function(extensions,f,name)
+ local extension=extensions[name] or "tostring(%s)"
+ local f=tonumber(f) or 1
+ if f==0 then
+ return extension
+ elseif f==1 then
+ n=n+1
+ local a="a"..n
+ return format(extension,a,a)
+ elseif f<0 then
+ local a="a"..(n+f+1)
+ return format(extension,a,a)
+ else
+ local t={}
+ for i=1,f do
+ n=n+1
+ t[#t+1]="a"..n
+ end
+ return format(extension,unpack(t))
+ end
+end
+local builder=Cs { "start",
+ start=(
+ (
+ P("%")/""*(
+ V("!")
++V("s")+V("q")+V("i")+V("d")+V("f")+V("g")+V("G")+V("e")+V("E")+V("x")+V("X")+V("o")
++V("c")+V("C")+V("S")
++V("Q")
++V("N")
++V("r")+V("h")+V("H")+V("u")+V("U")+V("p")+V("b")+V("t")+V("T")+V("l")+V("L")+V("I")+V("h")
++V("w")
++V("W")
++V("a")
++V("A")
++V("*")
+ )+V("*")
+ )*(P(-1)+Carg(1))
+ )^0,
+ ["s"]=(prefix_any*P("s"))/format_s,
+ ["q"]=(prefix_any*P("q"))/format_q,
+ ["i"]=(prefix_any*P("i"))/format_i,
+ ["d"]=(prefix_any*P("d"))/format_d,
+ ["f"]=(prefix_any*P("f"))/format_f,
+ ["g"]=(prefix_any*P("g"))/format_g,
+ ["G"]=(prefix_any*P("G"))/format_G,
+ ["e"]=(prefix_any*P("e"))/format_e,
+ ["E"]=(prefix_any*P("E"))/format_E,
+ ["x"]=(prefix_any*P("x"))/format_x,
+ ["X"]=(prefix_any*P("X"))/format_X,
+ ["o"]=(prefix_any*P("o"))/format_o,
+ ["S"]=(prefix_any*P("S"))/format_S,
+ ["Q"]=(prefix_any*P("Q"))/format_S,
+ ["N"]=(prefix_any*P("N"))/format_N,
+ ["c"]=(prefix_any*P("c"))/format_c,
+ ["C"]=(prefix_any*P("C"))/format_C,
+ ["r"]=(prefix_any*P("r"))/format_r,
+ ["h"]=(prefix_any*P("h"))/format_h,
+ ["H"]=(prefix_any*P("H"))/format_H,
+ ["u"]=(prefix_any*P("u"))/format_u,
+ ["U"]=(prefix_any*P("U"))/format_U,
+ ["p"]=(prefix_any*P("p"))/format_p,
+ ["b"]=(prefix_any*P("b"))/format_b,
+ ["t"]=(prefix_tab*P("t"))/format_t,
+ ["T"]=(prefix_tab*P("T"))/format_T,
+ ["l"]=(prefix_tab*P("l"))/format_l,
+ ["L"]=(prefix_tab*P("L"))/format_L,
+ ["I"]=(prefix_any*P("I"))/format_I,
+ ["w"]=(prefix_any*P("w"))/format_w,
+ ["W"]=(prefix_any*P("W"))/format_W,
+ ["a"]=(prefix_any*P("a"))/format_a,
+ ["A"]=(prefix_any*P("A"))/format_A,
+ ["*"]=Cs(((1-P("%"))^1+P("%%")/"%%%%")^1)/format_rest,
+ ["!"]=Carg(2)*prefix_any*P("!")*C((1-P("!"))^1)*P("!")/format_extension,
+}
+local direct=Cs (
+ P("%")/""*Cc([[local format = string.format return function(str) return format("%]])*(S("+- .")+R("09"))^0*S("sqidfgGeExXo")*Cc([[",str) end]])*P(-1)
+ )
+local function make(t,str)
+ local f
+ local p
+ local p=lpegmatch(direct,str)
+ if p then
+ f=loadstripped(p)()
+ else
+ n=0
+ p=lpegmatch(builder,str,1,"..",t._extensions_)
+ if n>0 then
+ p=format(template,preamble,t._preamble_,arguments[n],p)
+ f=loadstripped(p)()
else
- return "0" .. s
+ f=function() return str end
end
+ end
+ t[str]=f
+ return f
end
-
--- the lpeg way is slower on 8 digits, but faster on 4 digits, some 7.5%
--- on
---
--- for i=1,1000000 do
--- local a,b,c,d,e,f,g,h = number.toset(12345678)
--- local a,b,c,d = number.toset(1234)
--- local a,b,c = number.toset(123)
--- end
---
--- of course dedicated "(.)(.)(.)(.)" matches are even faster
-
-local one = lpeg.C(1-lpeg.S(''))^1
-
-function number.toset(n)
- return lpegmatch(one,tostring(n))
+local function use(t,fmt,...)
+ return t[fmt](...)
end
-
-function number.bits(n,zero)
- local t, i = { }, (zero and 0) or 1
- while n > 0 do
- local m = n % 2
- if m > 0 then
- insert(t,1,i)
- end
- n = floor(n/2)
- i = i + 1
+strings.formatters={}
+function strings.formatters.new()
+ local t={ _extensions_={},_preamble_="",_type_="formatter" }
+ setmetatable(t,{ __index=make,__call=use })
+ return t
+end
+local formatters=strings.formatters.new()
+string.formatters=formatters
+string.formatter=function(str,...) return formatters[str](...) end
+local function add(t,name,template,preamble)
+ if type(t)=="table" and t._type_=="formatter" then
+ t._extensions_[name]=template or "%s"
+ if preamble then
+ t._preamble_=preamble.."\n"..t._preamble_
end
- return t
+ end
end
+strings.formatters.add=add
+lpeg.patterns.xmlescape=Cs((P("<")/"<"+P(">")/">"+P("&")/"&"+P('"')/"""+P(1))^0)
+lpeg.patterns.texescape=Cs((C(S("#$%\\{}"))/"\\%1"+P(1))^0)
+add(formatters,"xml",[[lpegmatch(xmlescape,%s)]],[[local xmlescape = lpeg.patterns.xmlescape]])
+add(formatters,"tex",[[lpegmatch(texescape,%s)]],[[local texescape = lpeg.patterns.texescape]])
-function number.bit(p)
- return 2 ^ (p - 1) -- 1-based indexing
-end
-
-function number.hasbit(x, p) -- typical call: if hasbit(x, bit(3)) then ...
- return x % (p + p) >= p
-end
+end -- of closure
-function number.setbit(x, p)
- return hasbit(x, p) and x or x + p
-end
+do -- create closure to overcome 200 locals limit
-function number.clearbit(x, p)
- return hasbit(x, p) and x - p or x
-end
+package.loaded["util-tab"] = package.loaded["util-tab"] or true
+-- original size: 14491, stripped down to: 8512
-function number.tobitstring(n,m)
- if n == 0 then
- if m then
- rep("00000000",m)
+if not modules then modules={} end modules ['util-tab']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+utilities=utilities or {}
+utilities.tables=utilities.tables or {}
+local tables=utilities.tables
+local format,gmatch,gsub=string.format,string.gmatch,string.gsub
+local concat,insert,remove=table.concat,table.insert,table.remove
+local setmetatable,getmetatable,tonumber,tostring=setmetatable,getmetatable,tonumber,tostring
+local type,next,rawset,tonumber,tostring,load,select=type,next,rawset,tonumber,tostring,load,select
+local lpegmatch,P,Cs,Cc=lpeg.match,lpeg.P,lpeg.Cs,lpeg.Cc
+local serialize,sortedkeys,sortedpairs=table.serialize,table.sortedkeys,table.sortedpairs
+local formatters=string.formatters
+local splitter=lpeg.tsplitat(".")
+function tables.definetable(target,nofirst,nolast)
+ local composed,shortcut,t=nil,nil,{}
+ local snippets=lpegmatch(splitter,target)
+ for i=1,#snippets-(nolast and 1 or 0) do
+ local name=snippets[i]
+ if composed then
+ composed=shortcut.."."..name
+ shortcut=shortcut.."_"..name
+ t[#t+1]=formatters["local %s = %s if not %s then %s = { } %s = %s end"](shortcut,composed,shortcut,shortcut,composed,shortcut)
+ else
+ composed=name
+ shortcut=name
+ if not nofirst then
+ t[#t+1]=formatters["%s = %s or { }"](composed,composed)
+ end
+ end
+ end
+ if nolast then
+ composed=shortcut.."."..snippets[#snippets]
+ end
+ return concat(t,"\n"),composed
+end
+function tables.definedtable(...)
+ local t=_G
+ for i=1,select("#",...) do
+ local li=select(i,...)
+ local tl=t[li]
+ if not tl then
+ tl={}
+ t[li]=tl
+ end
+ t=tl
+ end
+ return t
+end
+function tables.accesstable(target,root)
+ local t=root or _G
+ for name in gmatch(target,"([^%.]+)") do
+ t=t[name]
+ if not t then
+ return
+ end
+ end
+ return t
+end
+function tables.migratetable(target,v,root)
+ local t=root or _G
+ local names=string.split(target,".")
+ for i=1,#names-1 do
+ local name=names[i]
+ t[name]=t[name] or {}
+ t=t[name]
+ if not t then
+ return
+ end
+ end
+ t[names[#names]]=v
+end
+function tables.removevalue(t,value)
+ if value then
+ for i=1,#t do
+ if t[i]==value then
+ remove(t,i)
+ end
+ end
+ end
+end
+function tables.insertbeforevalue(t,value,extra)
+ for i=1,#t do
+ if t[i]==extra then
+ remove(t,i)
+ end
+ end
+ for i=1,#t do
+ if t[i]==value then
+ insert(t,i,extra)
+ return
+ end
+ end
+ insert(t,1,extra)
+end
+function tables.insertaftervalue(t,value,extra)
+ for i=1,#t do
+ if t[i]==extra then
+ remove(t,i)
+ end
+ end
+ for i=1,#t do
+ if t[i]==value then
+ insert(t,i+1,extra)
+ return
+ end
+ end
+ insert(t,#t+1,extra)
+end
+local escape=Cs(Cc('"')*((P('"')/'""'+P(1))^0)*Cc('"'))
+function table.tocsv(t,specification)
+ if t and #t>0 then
+ local result={}
+ local r={}
+ specification=specification or {}
+ local fields=specification.fields
+ if type(fields)~="string" then
+ fields=sortedkeys(t[1])
+ end
+ local separator=specification.separator or ","
+ if specification.preamble==true then
+ for f=1,#fields do
+ r[f]=lpegmatch(escape,tostring(fields[f]))
+ end
+ result[1]=concat(r,separator)
+ end
+ for i=1,#t do
+ local ti=t[i]
+ for f=1,#fields do
+ local field=ti[fields[f]]
+ if type(field)=="string" then
+ r[f]=lpegmatch(escape,field)
else
- return "00000000"
+ r[f]=tostring(field)
end
+ end
+ result[#result+1]=concat(r,separator)
+ end
+ return concat(result,"\n")
+ else
+ return ""
+ end
+end
+local nspaces=utilities.strings.newrepeater(" ")
+local function toxml(t,d,result,step)
+ for k,v in sortedpairs(t) do
+ local s=nspaces[d]
+ local tk=type(k)
+ local tv=type(v)
+ if tv=="table" then
+ if tk=="number" then
+ result[#result+1]=formatters["%s"](s,k)
+ toxml(v,d+step,result,step)
+ result[#result+1]=formatters["%s "](s,k)
+ else
+ result[#result+1]=formatters["%s<%s>"](s,k)
+ toxml(v,d+step,result,step)
+ result[#result+1]=formatters["%s%s>"](s,k)
+ end
+ elseif tv=="string" then
+ if tk=="number" then
+ result[#result+1]=formatters["%s%!xml! "](s,k,v,k)
+ else
+ result[#result+1]=formatters["%s<%s>%!xml!%s>"](s,k,v,k)
+ end
+ elseif tk=="number" then
+ result[#result+1]=formatters["%s%S "](s,k,v,k)
else
- local t = { }
- while n > 0 do
- insert(t,1,n % 2 > 0 and 1 or 0)
- n = floor(n/2)
- end
- local nn = 8 - #t % 8
- if nn > 0 and nn < 8 then
- for i=1,nn do
- insert(t,1,0)
- end
- end
- if m then
- m = m * 8 - #t
- if m > 0 then
- insert(t,1,rep("0",m))
- end
- end
- return concat(t)
+ result[#result+1]=formatters["%s<%s>%S%s>"](s,k,v,k)
+ end
+ end
+end
+function table.toxml(t,specification)
+ specification=specification or {}
+ local name=specification.name
+ local noroot=name==false
+ local result=(specification.nobanner or noroot) and {} or { "" }
+ local indent=specification.indent or 0
+ local spaces=specification.spaces or 1
+ if noroot then
+ toxml(t,indent,result,spaces)
+ else
+ toxml({ [name or "data"]=t },indent,result,spaces)
+ end
+ return concat(result,"\n")
+end
+function tables.encapsulate(core,capsule,protect)
+ if type(capsule)~="table" then
+ protect=true
+ capsule={}
+ end
+ for key,value in next,core do
+ if capsule[key] then
+ print(formatters["\ninvalid %s %a in %a"]("inheritance",key,core))
+ os.exit()
+ else
+ capsule[key]=value
+ end
+ end
+ if protect then
+ for key,value in next,core do
+ core[key]=nil
end
+ setmetatable(core,{
+ __index=capsule,
+ __newindex=function(t,key,value)
+ if capsule[key] then
+ print(formatters["\ninvalid %s %a' in %a"]("overload",key,core))
+ os.exit()
+ else
+ rawset(t,key,value)
+ end
+ end
+ } )
+ end
+end
+local function fastserialize(t,r,outer)
+ r[#r+1]="{"
+ local n=#t
+ if n>0 then
+ for i=1,n do
+ local v=t[i]
+ local tv=type(v)
+ if tv=="string" then
+ r[#r+1]=formatters["%q,"](v)
+ elseif tv=="number" then
+ r[#r+1]=formatters["%s,"](v)
+ elseif tv=="table" then
+ fastserialize(v,r)
+ elseif tv=="boolean" then
+ r[#r+1]=formatters["%S,"](v)
+ end
+ end
+ else
+ for k,v in next,t do
+ local tv=type(v)
+ if tv=="string" then
+ r[#r+1]=formatters["[%q]=%q,"](k,v)
+ elseif tv=="number" then
+ r[#r+1]=formatters["[%q]=%s,"](k,v)
+ elseif tv=="table" then
+ r[#r+1]=formatters["[%q]="](k)
+ fastserialize(v,r)
+ elseif tv=="boolean" then
+ r[#r+1]=formatters["[%q]=%S,"](k,v)
+ end
+ end
+ end
+ if outer then
+ r[#r+1]="}"
+ else
+ r[#r+1]="},"
+ end
+ return r
+end
+function table.fastserialize(t,prefix)
+ return concat(fastserialize(t,{ prefix or "return" },true))
+end
+function table.deserialize(str)
+ if not str or str=="" then
+ return
+ end
+ local code=load(str)
+ if not code then
+ return
+ end
+ code=code()
+ if not code then
+ return
+ end
+ return code
+end
+function table.load(filename)
+ if filename then
+ local t=io.loaddata(filename)
+ if t and t~="" then
+ t=load(t)
+ if type(t)=="function" then
+ t=t()
+ if type(t)=="table" then
+ return t
+ end
+ end
+ end
+ end
+end
+function table.save(filename,t,n,...)
+ io.savedata(filename,serialize(t,n==nil and true or n,...))
+end
+local function slowdrop(t)
+ local r={}
+ local l={}
+ for i=1,#t do
+ local ti=t[i]
+ local j=0
+ for k,v in next,ti do
+ j=j+1
+ l[j]=formatters["%s=%q"](k,v)
+ end
+ r[i]=formatters[" {%t},\n"](l)
+ end
+ return formatters["return {\n%st}"](r)
+end
+local function fastdrop(t)
+ local r={ "return {\n" }
+ for i=1,#t do
+ local ti=t[i]
+ r[#r+1]=" {"
+ for k,v in next,ti do
+ r[#r+1]=formatters["%s=%q"](k,v)
+ end
+ r[#r+1]="},\n"
+ end
+ r[#r+1]="}"
+ return concat(r)
+end
+function table.drop(t,slow)
+ if #t==0 then
+ return "return { }"
+ elseif slow==true then
+ return slowdrop(t)
+ else
+ return fastdrop(t)
+ end
+end
+function table.autokey(t,k)
+ local v={}
+ t[k]=v
+ return v
+end
+local selfmapper={ __index=function(t,k) t[k]=k return k end }
+function table.twowaymapper(t)
+ if not t then
+ t={}
+ else
+ for i=0,#t do
+ local ti=t[i]
+ if ti then
+ local i=tostring(i)
+ t[i]=ti
+ t[ti]=i
+ end
+ end
+ t[""]=t[0] or ""
+ end
+ setmetatable(t,selfmapper)
+ return t
end
-
end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-set'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- This will become obsolete when we have the bitset library embedded.
-
-set = set or { }
-
-local nums = { }
-local tabs = { }
-local concat = table.concat
-local next, type = next, type
+package.loaded["util-sto"] = package.loaded["util-sto"] or true
-set.create = table.tohash
+-- original size: 4432, stripped down to: 3123
-function set.tonumber(t)
- if next(t) then
- local s = ""
- -- we could save mem by sorting, but it slows down
- for k, v in next, t do
- if v then
- -- why bother about the leading space
- s = s .. " " .. k
- end
- end
- local n = nums[s]
- if not n then
- n = #tabs + 1
- tabs[n] = t
- nums[s] = n
- end
- return n
- else
- return 0
- end
+if not modules then modules={} end modules ['util-sto']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local setmetatable,getmetatable,type=setmetatable,getmetatable,type
+utilities=utilities or {}
+utilities.storage=utilities.storage or {}
+local storage=utilities.storage
+function storage.mark(t)
+ if not t then
+ print("\nfatal error: storage cannot be marked\n")
+ os.exit()
+ return
+ end
+ local m=getmetatable(t)
+ if not m then
+ m={}
+ setmetatable(t,m)
+ end
+ m.__storage__=true
+ return t
end
-
-function set.totable(n)
- if n == 0 then
- return { }
+function storage.allocate(t)
+ t=t or {}
+ local m=getmetatable(t)
+ if not m then
+ m={}
+ setmetatable(t,m)
+ end
+ m.__storage__=true
+ return t
+end
+function storage.marked(t)
+ local m=getmetatable(t)
+ return m and m.__storage__
+end
+function storage.checked(t)
+ if not t then
+ report("\nfatal error: storage has not been allocated\n")
+ os.exit()
+ return
+ end
+ return t
+end
+function storage.setinitializer(data,initialize)
+ local m=getmetatable(data) or {}
+ m.__index=function(data,k)
+ m.__index=nil
+ initialize()
+ return data[k]
+ end
+ setmetatable(data,m)
+end
+local keyisvalue={ __index=function(t,k)
+ t[k]=k
+ return k
+end }
+function storage.sparse(t)
+ t=t or {}
+ setmetatable(t,keyisvalue)
+ return t
+end
+local function f_empty () return "" end
+local function f_self (t,k) t[k]=k return k end
+local function f_table (t,k) local v={} t[k]=v return v end
+local function f_ignore() end
+local t_empty={ __index=f_empty }
+local t_self={ __index=f_self }
+local t_table={ __index=f_table }
+local t_ignore={ __newindex=f_ignore }
+function table.setmetatableindex(t,f)
+ if type(t)~="table" then
+ f,t=t,{}
+ end
+ local m=getmetatable(t)
+ if m then
+ if f=="empty" then
+ m.__index=f_empty
+ elseif f=="key" then
+ m.__index=f_self
+ elseif f=="table" then
+ m.__index=f_table
else
- return tabs[n] or { }
+ m.__index=f
+ end
+ else
+ if f=="empty" then
+ setmetatable(t,t_empty)
+ elseif f=="key" then
+ setmetatable(t,t_self)
+ elseif f=="table" then
+ setmetatable(t,t_table)
+ else
+ setmetatable(t,{ __index=f })
end
+ end
+ return t
end
-
-function set.tolist(n)
- if n == 0 or not tabs[n] then
- return ""
+function table.setmetatablenewindex(t,f)
+ if type(t)~="table" then
+ f,t=t,{}
+ end
+ local m=getmetatable(t)
+ if m then
+ if f=="ignore" then
+ m.__newindex=f_ignore
else
- local t, n = { }, 0
- for k, v in next, tabs[n] do
- if v then
- n = n + 1
- t[n] = k
- end
- end
- return concat(t," ")
+ m.__newindex=f
end
-end
-
-function set.contains(n,s)
- if type(n) == "table" then
- return n[s]
- elseif n == 0 then
- return false
+ else
+ if f=="ignore" then
+ setmetatable(t,t_ignore)
else
- local t = tabs[n]
- return t and t[s]
+ setmetatable(t,{ __newindex=f })
end
+ end
+ return t
+end
+function table.setmetatablecall(t,f)
+ if type(t)~="table" then
+ f,t=t,{}
+ end
+ local m=getmetatable(t)
+ if m then
+ m.__call=f
+ else
+ setmetatable(t,{ __call=f })
+ end
+ return t
+end
+function table.setmetatablekey(t,key,value)
+ local m=getmetatable(t)
+ if not m then
+ m={}
+ setmetatable(t,m)
+ end
+ m[key]=value
+ return t
+end
+function table.getmetatablekey(t,key,value)
+ local m=getmetatable(t)
+ return m and m[key]
end
-
-
end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-os'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- This file deals with some operating system issues. Please don't bother me
--- with the pros and cons of operating systems as they all have their flaws
--- and benefits. Bashing one of them won't help solving problems and fixing
--- bugs faster and is a waste of time and energy.
---
--- path separators: / or \ ... we can use / everywhere
--- suffixes : dll so exe ... no big deal
--- quotes : we can use "" in most cases
--- expansion : unless "" are used * might give side effects
--- piping/threads : somewhat different for each os
--- locations : specific user file locations and settings can change over time
---
--- os.type : windows | unix (new, we already guessed os.platform)
--- os.name : windows | msdos | linux | macosx | solaris | .. | generic (new)
--- os.platform : extended os.name with architecture
-
--- maybe build io.flush in os.execute
-
-local os = os
-local find, format, gsub, upper, gmatch = string.find, string.format, string.gsub, string.upper, string.gmatch
-local concat = table.concat
-local random, ceil = math.random, math.ceil
-local rawget, rawset, type, getmetatable, setmetatable, tonumber = rawget, rawset, type, getmetatable, setmetatable, tonumber
-
--- The following code permits traversing the environment table, at least
--- in luatex. Internally all environment names are uppercase.
-
-if not os.__getenv__ then
-
- os.__getenv__ = os.getenv
- os.__setenv__ = os.setenv
+package.loaded["util-prs"] = package.loaded["util-prs"] or true
- if os.env then
-
- local osgetenv = os.getenv
- local ossetenv = os.setenv
- local osenv = os.env local _ = osenv.PATH -- initialize the table
-
- function os.setenv(k,v)
- if v == nil then
- v = ""
- end
- local K = upper(k)
- osenv[K] = v
- if type(v) == "table" then
- v = concat(v,";") -- path
- end
- ossetenv(K,v)
- end
-
- function os.getenv(k)
- local K = upper(k)
- local v = osenv[K] or osenv[k] or osgetenv(K) or osgetenv(k)
- if v == "" then
- return nil
- else
- return v
- end
- end
+-- original size: 16976, stripped down to: 12143
+if not modules then modules={} end modules ['util-prs']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local lpeg,table,string=lpeg,table,string
+local P,R,V,S,C,Ct,Cs,Carg,Cc,Cg,Cf,Cp=lpeg.P,lpeg.R,lpeg.V,lpeg.S,lpeg.C,lpeg.Ct,lpeg.Cs,lpeg.Carg,lpeg.Cc,lpeg.Cg,lpeg.Cf,lpeg.Cp
+local lpegmatch,lpegpatterns=lpeg.match,lpeg.patterns
+local concat,format,gmatch,find=table.concat,string.format,string.gmatch,string.find
+local tostring,type,next,rawset=tostring,type,next,rawset
+utilities=utilities or {}
+local parsers=utilities.parsers or {}
+utilities.parsers=parsers
+local patterns=parsers.patterns or {}
+parsers.patterns=patterns
+local setmetatableindex=table.setmetatableindex
+local sortedhash=table.sortedhash
+local digit=R("09")
+local space=P(' ')
+local equal=P("=")
+local comma=P(",")
+local lbrace=P("{")
+local rbrace=P("}")
+local lparent=P("(")
+local rparent=P(")")
+local period=S(".")
+local punctuation=S(".,:;")
+local spacer=lpegpatterns.spacer
+local whitespace=lpegpatterns.whitespace
+local newline=lpegpatterns.newline
+local anything=lpegpatterns.anything
+local endofstring=lpegpatterns.endofstring
+local nobrace=1-(lbrace+rbrace )
+local noparent=1-(lparent+rparent)
+local escape,left,right=P("\\"),P('{'),P('}')
+lpegpatterns.balanced=P {
+ [1]=((escape*(left+right))+(1-(left+right))+V(2))^0,
+ [2]=left*V(1)*right
+}
+local nestedbraces=P { lbrace*(nobrace+V(1))^0*rbrace }
+local nestedparents=P { lparent*(noparent+V(1))^0*rparent }
+local spaces=space^0
+local argument=Cs((lbrace/"")*((nobrace+nestedbraces)^0)*(rbrace/""))
+local content=(1-endofstring)^0
+lpegpatterns.nestedbraces=nestedbraces
+lpegpatterns.nestedparents=nestedparents
+lpegpatterns.nested=nestedbraces
+lpegpatterns.argument=argument
+lpegpatterns.content=content
+local value=P(lbrace*C((nobrace+nestedbraces)^0)*rbrace)+C((nestedbraces+(1-comma))^0)
+local key=C((1-equal-comma)^1)
+local pattern_a=(space+comma)^0*(key*equal*value+key*C(""))
+local pattern_c=(space+comma)^0*(key*equal*value)
+local key=C((1-space-equal-comma)^1)
+local pattern_b=spaces*comma^0*spaces*(key*((spaces*equal*spaces*value)+C("")))
+local hash={}
+local function set(key,value)
+ hash[key]=value
+end
+local pattern_a_s=(pattern_a/set)^1
+local pattern_b_s=(pattern_b/set)^1
+local pattern_c_s=(pattern_c/set)^1
+patterns.settings_to_hash_a=pattern_a_s
+patterns.settings_to_hash_b=pattern_b_s
+patterns.settings_to_hash_c=pattern_c_s
+function parsers.make_settings_to_hash_pattern(set,how)
+ if how=="strict" then
+ return (pattern_c/set)^1
+ elseif how=="tolerant" then
+ return (pattern_b/set)^1
+ else
+ return (pattern_a/set)^1
+ end
+end
+function parsers.settings_to_hash(str,existing)
+ if str and str~="" then
+ hash=existing or {}
+ lpegmatch(pattern_a_s,str)
+ return hash
+ else
+ return {}
+ end
+end
+function parsers.settings_to_hash_tolerant(str,existing)
+ if str and str~="" then
+ hash=existing or {}
+ lpegmatch(pattern_b_s,str)
+ return hash
+ else
+ return {}
+ end
+end
+function parsers.settings_to_hash_strict(str,existing)
+ if str and str~="" then
+ hash=existing or {}
+ lpegmatch(pattern_c_s,str)
+ return next(hash) and hash
+ else
+ return nil
+ end
+end
+local separator=comma*space^0
+local value=P(lbrace*C((nobrace+nestedbraces)^0)*rbrace)+C((nestedbraces+(1-comma))^0)
+local pattern=spaces*Ct(value*(separator*value)^0)
+patterns.settings_to_array=pattern
+function parsers.settings_to_array(str,strict)
+ if not str or str=="" then
+ return {}
+ elseif strict then
+ if find(str,"{") then
+ return lpegmatch(pattern,str)
else
-
- local ossetenv = os.setenv
- local osgetenv = os.getenv
- local osenv = { }
-
- function os.setenv(k,v)
- if v == nil then
- v = ""
- end
- local K = upper(k)
- osenv[K] = v
- end
-
- function os.getenv(k)
- local K = upper(k)
- local v = osenv[K] or osgetenv(K) or osgetenv(k)
- if v == "" then
- return nil
- else
- return v
- end
- end
-
- local function __index(t,k)
- return os.getenv(k)
- end
- local function __newindex(t,k,v)
- os.setenv(k,v)
+ return { str }
+ end
+ else
+ return lpegmatch(pattern,str)
+ end
+end
+local function set(t,v)
+ t[#t+1]=v
+end
+local value=P(Carg(1)*value)/set
+local pattern=value*(separator*value)^0*Carg(1)
+function parsers.add_settings_to_array(t,str)
+ return lpegmatch(pattern,str,nil,t)
+end
+function parsers.hash_to_string(h,separator,yes,no,strict,omit)
+ if h then
+ local t,tn,s={},0,table.sortedkeys(h)
+ omit=omit and table.tohash(omit)
+ for i=1,#s do
+ local key=s[i]
+ if not omit or not omit[key] then
+ local value=h[key]
+ if type(value)=="boolean" then
+ if yes and no then
+ if value then
+ tn=tn+1
+ t[tn]=key..'='..yes
+ elseif not strict then
+ tn=tn+1
+ t[tn]=key..'='..no
+ end
+ elseif value or not strict then
+ tn=tn+1
+ t[tn]=key..'='..tostring(value)
+ end
+ else
+ tn=tn+1
+ t[tn]=key..'='..value
end
-
- os.env = { }
-
- setmetatable(os.env, { __index = __index, __newindex = __newindex } )
-
+ end
end
-
+ return concat(t,separator or ",")
+ else
+ return ""
+ end
end
-
--- end of environment hack
-
-local execute, spawn, exec, iopopen, ioflush = os.execute, os.spawn or os.execute, os.exec or os.execute, io.popen, io.flush
-
-function os.execute(...) ioflush() return execute(...) end
-function os.spawn (...) ioflush() return spawn (...) end
-function os.exec (...) ioflush() return exec (...) end
-function io.popen (...) ioflush() return iopopen(...) end
-
-function os.resultof(command)
- local handle = io.popen(command,"r")
- return handle and handle:read("*all") or ""
+function parsers.array_to_string(a,separator)
+ if a then
+ return concat(a,separator or ",")
+ else
+ return ""
+ end
+end
+function parsers.settings_to_set(str,t)
+ t=t or {}
+ for s in gmatch(str,"[^, ]+") do
+ t[s]=true
+ end
+ return t
+end
+function parsers.simple_hash_to_string(h,separator)
+ local t,tn={},0
+ for k,v in sortedhash(h) do
+ if v then
+ tn=tn+1
+ t[tn]=k
+ end
+ end
+ return concat(t,separator or ",")
end
-
-if not io.fileseparator then
- if find(os.getenv("PATH"),";") then
- io.fileseparator, io.pathseparator, os.type = "\\", ";", os.type or "mswin"
+local value=P(lbrace*C((nobrace+nestedbraces)^0)*rbrace)+C(digit^1*lparent*(noparent+nestedparents)^1*rparent)+C((nestedbraces+(1-comma))^1)
+local pattern_a=spaces*Ct(value*(separator*value)^0)
+local function repeater(n,str)
+ if not n then
+ return str
+ else
+ local s=lpegmatch(pattern_a,str)
+ if n==1 then
+ return unpack(s)
else
- io.fileseparator, io.pathseparator, os.type = "/" , ":", os.type or "unix"
- end
+ local t,tn={},0
+ for i=1,n do
+ for j=1,#s do
+ tn=tn+1
+ t[tn]=s[j]
+ end
+ end
+ return unpack(t)
+ end
+ end
+end
+local value=P(lbrace*C((nobrace+nestedbraces)^0)*rbrace)+(C(digit^1)/tonumber*lparent*Cs((noparent+nestedparents)^1)*rparent)/repeater+C((nestedbraces+(1-comma))^1)
+local pattern_b=spaces*Ct(value*(separator*value)^0)
+function parsers.settings_to_array_with_repeat(str,expand)
+ if expand then
+ return lpegmatch(pattern_b,str) or {}
+ else
+ return lpegmatch(pattern_a,str) or {}
+ end
+end
+local value=lbrace*C((nobrace+nestedbraces)^0)*rbrace
+local pattern=Ct((space+value)^0)
+function parsers.arguments_to_table(str)
+ return lpegmatch(pattern,str)
end
-
-os.type = os.type or (io.pathseparator == ";" and "windows") or "unix"
-os.name = os.name or (os.type == "windows" and "mswin" ) or "linux"
-
-if os.type == "windows" then
- os.libsuffix, os.binsuffix, os.binsuffixes = 'dll', 'exe', { 'exe', 'cmd', 'bat' }
-else
- os.libsuffix, os.binsuffix, os.binsuffixes = 'so', '', { '' }
+function parsers.getparameters(self,class,parentclass,settings)
+ local sc=self[class]
+ if not sc then
+ sc={}
+ self[class]=sc
+ if parentclass then
+ local sp=self[parentclass]
+ if not sp then
+ sp={}
+ self[parentclass]=sp
+ end
+ setmetatableindex(sc,sp)
+ end
+ end
+ parsers.settings_to_hash(settings,sc)
end
-
-function os.launch(str)
- if os.type == "windows" then
- os.execute("start " .. str) -- os.spawn ?
+function parsers.listitem(str)
+ return gmatch(str,"[^, ]+")
+end
+local pattern=Cs { "start",
+ start=V("one")+V("two")+V("three"),
+ rest=(Cc(",")*V("thousand"))^0*(P(".")+endofstring)*anything^0,
+ thousand=digit*digit*digit,
+ one=digit*V("rest"),
+ two=digit*digit*V("rest"),
+ three=V("thousand")*V("rest"),
+}
+lpegpatterns.splitthousands=pattern
+function parsers.splitthousands(str)
+ return lpegmatch(pattern,str) or str
+end
+local optionalwhitespace=whitespace^0
+lpegpatterns.words=Ct((Cs((1-punctuation-whitespace)^1)+anything)^1)
+lpegpatterns.sentences=Ct((optionalwhitespace*Cs((1-period)^0*period))^1)
+lpegpatterns.paragraphs=Ct((optionalwhitespace*Cs((whitespace^1*endofstring/""+1-(spacer^0*newline*newline))^1))^1)
+local dquote=P('"')
+local equal=P('=')
+local escape=P('\\')
+local separator=S(' ,')
+local key=C((1-equal)^1)
+local value=dquote*C((1-dquote-escape*dquote)^0)*dquote
+local pattern=Cf(Ct("")*Cg(key*equal*value)*separator^0,rawset)^0*P(-1)
+patterns.keq_to_hash_c=pattern
+function parsers.keq_to_hash(str)
+ if str and str~="" then
+ return lpegmatch(pattern,str)
+ else
+ return {}
+ end
+end
+local defaultspecification={ separator=",",quote='"' }
+function parsers.csvsplitter(specification)
+ specification=specification and table.setmetatableindex(specification,defaultspecification) or defaultspecification
+ local separator=specification.separator
+ local quotechar=specification.quote
+ local separator=S(separator~="" and separator or ",")
+ local whatever=C((1-separator-newline)^0)
+ if quotechar and quotechar~="" then
+ local quotedata=nil
+ for chr in gmatch(quotechar,".") do
+ local quotechar=P(chr)
+ local quoteword=quotechar*C((1-quotechar)^0)*quotechar
+ if quotedata then
+ quotedata=quotedata+quoteword
+ else
+ quotedata=quoteword
+ end
+ end
+ whatever=quotedata+whatever
+ end
+ local parser=Ct((Ct(whatever*(separator*whatever)^0)*S("\n\r"))^0 )
+ return function(data)
+ return lpegmatch(parser,data)
+ end
+end
+function parsers.rfc4180splitter(specification)
+ specification=specification and table.setmetatableindex(specification,defaultspecification) or defaultspecification
+ local separator=specification.separator
+ local quotechar=P(specification.quote)
+ local dquotechar=quotechar*quotechar
+/specification.quote
+ local separator=S(separator~="" and separator or ",")
+ local escaped=quotechar*Cs((dquotechar+(1-quotechar))^0)*quotechar
+ local non_escaped=C((1-quotechar-newline-separator)^1)
+ local field=escaped+non_escaped
+ local record=Ct((field*separator^-1)^1)
+ local headerline=record*Cp()
+ local wholeblob=Ct((newline^-1*record)^0)
+ return function(data,getheader)
+ if getheader then
+ local header,position=lpegmatch(headerline,data)
+ local data=lpegmatch(wholeblob,data,position)
+ return data,header
else
- os.execute(str .. " &") -- os.spawn ?
+ return lpegmatch(wholeblob,data)
+ end
+ end
+end
+local function ranger(first,last,n,action)
+ if not first then
+ elseif last==true then
+ for i=first,n or first do
+ action(i)
+ end
+ elseif last then
+ for i=first,last do
+ action(i)
+ end
+ else
+ action(first)
+ end
+end
+local cardinal=lpegpatterns.cardinal/tonumber
+local spacers=lpegpatterns.spacer^0
+local endofstring=lpegpatterns.endofstring
+local stepper=spacers*(C(cardinal)*(spacers*S(":-")*spacers*(C(cardinal)+Cc(true) )+Cc(false) )*Carg(1)*Carg(2)/ranger*S(", ")^0 )^1
+local stepper=spacers*(C(cardinal)*(spacers*S(":-")*spacers*(C(cardinal)+(P("*")+endofstring)*Cc(true) )+Cc(false) )*Carg(1)*Carg(2)/ranger*S(", ")^0 )^1*endofstring
+function parsers.stepper(str,n,action)
+ if type(n)=="function" then
+ lpegmatch(stepper,str,1,false,n or print)
+ else
+ lpegmatch(stepper,str,1,n,action or print)
+ end
+end
+local pattern_math=Cs((P("%")/"\\percent "+P("^")*Cc("{")*lpegpatterns.integer*Cc("}")+P(1))^0)
+local pattern_text=Cs((P("%")/"\\percent "+(P("^")/"\\high")*Cc("{")*lpegpatterns.integer*Cc("}")+P(1))^0)
+patterns.unittotex=pattern
+function parsers.unittotex(str,textmode)
+ return lpegmatch(textmode and pattern_text or pattern_math,str)
+end
+local pattern=Cs((P("^")/""*lpegpatterns.integer*Cc(" ")+P(1))^0)
+function parsers.unittoxml(str)
+ return lpegmatch(pattern,str)
+end
+local cache={}
+local spaces=lpeg.patterns.space^0
+local dummy=function() end
+table.setmetatableindex(cache,function(t,k)
+ local separator=P(k)
+ local value=(1-separator)^0
+ local pattern=spaces*C(value)*separator^0*Cp()
+ t[k]=pattern
+ return pattern
+end)
+local commalistiterator=cache[","]
+function utilities.parsers.iterator(str,separator)
+ local n=#str
+ if n==0 then
+ return dummy
+ else
+ local pattern=separator and cache[separator] or commalistiterator
+ local p=1
+ return function()
+ if p<=n then
+ local s,e=lpegmatch(pattern,str,p)
+ if e then
+ p=e
+ return s
+ end
+ end
end
+ end
end
-
-if not os.times then
- -- utime = user time
- -- stime = system time
- -- cutime = children user time
- -- cstime = children system time
- function os.times()
- return {
- utime = os.gettimeofday(), -- user
- stime = 0, -- system
- cutime = 0, -- children user
- cstime = 0, -- children system
- }
+local function initialize(t,name)
+ local source=t[name]
+ if source then
+ local result={}
+ for k,v in next,t[name] do
+ result[k]=v
end
+ return result
+ else
+ return {}
+ end
end
-
-os.gettimeofday = os.gettimeofday or os.clock
-
-local startuptime = os.gettimeofday()
-
-function os.runtime()
- return os.gettimeofday() - startuptime
+local function fetch(t,name)
+ return t[name] or {}
end
-
-
--- no need for function anymore as we have more clever code and helpers now
--- this metatable trickery might as well disappear
-
-os.resolvers = os.resolvers or { } -- will become private
-
-local resolvers = os.resolvers
-
-local osmt = getmetatable(os) or { __index = function(t,k) t[k] = "unset" return "unset" end } -- maybe nil
-local osix = osmt.__index
-
-osmt.__index = function(t,k)
- return (resolvers[k] or osix)(t,k)
+function process(result,more)
+ for k,v in next,more do
+ result[k]=v
+ end
+ return result
end
-
-setmetatable(os,osmt)
-
--- we can use HOSTTYPE on some platforms
-
-local name, platform = os.name or "linux", os.getenv("MTX_PLATFORM") or ""
-
-local function guess()
- local architecture = os.resultof("uname -m") or ""
- if architecture ~= "" then
- return architecture
- end
- architecture = os.getenv("HOSTTYPE") or ""
- if architecture ~= "" then
- return architecture
- end
- return os.resultof("echo $HOSTTYPE") or ""
+local name=C((1-S(", "))^1)
+local parser=(Carg(1)*name/initialize)*(S(", ")^1*(Carg(1)*name/fetch))^0
+local merge=Cf(parser,process)
+function utilities.parsers.mergehashes(hash,list)
+ return lpegmatch(merge,list,1,hash)
end
-if platform ~= "" then
-
- os.platform = platform
-elseif os.type == "windows" then
+end -- of closure
- -- we could set the variable directly, no function needed here
+do -- create closure to overcome 200 locals limit
- function os.resolvers.platform(t,k)
- local platform, architecture = "", os.getenv("PROCESSOR_ARCHITECTURE") or ""
- if find(architecture,"AMD64") then
- platform = "mswin-64"
- else
- platform = "mswin"
- end
- os.setenv("MTX_PLATFORM",platform)
- os.platform = platform
- return platform
- end
+package.loaded["util-fmt"] = package.loaded["util-fmt"] or true
-elseif name == "linux" then
+-- original size: 2274, stripped down to: 1781
- function os.resolvers.platform(t,k)
- -- we sometimes have HOSTTYPE set so let's check that first
- local platform, architecture = "", os.getenv("HOSTTYPE") or os.resultof("uname -m") or ""
- if find(architecture,"x86_64") then
- platform = "linux-64"
- elseif find(architecture,"ppc") then
- platform = "linux-ppc"
- else
- platform = "linux"
- end
- os.setenv("MTX_PLATFORM",platform)
- os.platform = platform
- return platform
- end
-
-elseif name == "macosx" then
-
- --[[
- Identifying the architecture of OSX is quite a mess and this
- is the best we can come up with. For some reason $HOSTTYPE is
- a kind of pseudo environment variable, not known to the current
- environment. And yes, uname cannot be trusted either, so there
- is a change that you end up with a 32 bit run on a 64 bit system.
- Also, some proper 64 bit intel macs are too cheap (low-end) and
- therefore not permitted to run the 64 bit kernel.
- ]]--
-
- function os.resolvers.platform(t,k)
- -- local platform, architecture = "", os.getenv("HOSTTYPE") or ""
- -- if architecture == "" then
- -- architecture = os.resultof("echo $HOSTTYPE") or ""
- -- end
- local platform, architecture = "", os.resultof("echo $HOSTTYPE") or ""
- if architecture == "" then
- -- print("\nI have no clue what kind of OSX you're running so let's assume an 32 bit intel.\n")
- platform = "osx-intel"
- elseif find(architecture,"i386") then
- platform = "osx-intel"
- elseif find(architecture,"x86_64") then
- platform = "osx-64"
+if not modules then modules={} end modules ['util-fmt']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+utilities=utilities or {}
+utilities.formatters=utilities.formatters or {}
+local formatters=utilities.formatters
+local concat,format=table.concat,string.format
+local tostring,type=tostring,type
+local strip=string.strip
+local lpegmatch=lpeg.match
+local stripper=lpeg.patterns.stripzeros
+function formatters.stripzeros(str)
+ return lpegmatch(stripper,str)
+end
+function formatters.formatcolumns(result,between)
+ if result and #result>0 then
+ between=between or " "
+ local widths,numbers={},{}
+ local first=result[1]
+ local n=#first
+ for i=1,n do
+ widths[i]=0
+ end
+ for i=1,#result do
+ local r=result[i]
+ for j=1,n do
+ local rj=r[j]
+ local tj=type(rj)
+ if tj=="number" then
+ numbers[j]=true
+ end
+ if tj~="string" then
+ rj=tostring(rj)
+ r[j]=rj
+ end
+ local w=#rj
+ if w>widths[j] then
+ widths[j]=w
+ end
+ end
+ end
+ for i=1,n do
+ local w=widths[i]
+ if numbers[i] then
+ if w>80 then
+ widths[i]="%s"..between
+ else
+ widths[i]="%0"..w.."i"..between
+ end
+ else
+ if w>80 then
+ widths[i]="%s"..between
+ elseif w>0 then
+ widths[i]="%-"..w.."s"..between
else
- platform = "osx-ppc"
+ widths[i]="%s"
end
- os.setenv("MTX_PLATFORM",platform)
- os.platform = platform
- return platform
+ end
+ end
+ local template=strip(concat(widths))
+ for i=1,#result do
+ local str=format(template,unpack(result[i]))
+ result[i]=strip(str)
end
+ end
+ return result
+end
-elseif name == "sunos" then
- function os.resolvers.platform(t,k)
- local platform, architecture = "", os.resultof("uname -m") or ""
- if find(architecture,"sparc") then
- platform = "solaris-sparc"
- else -- if architecture == 'i86pc'
- platform = "solaris-intel"
- end
- os.setenv("MTX_PLATFORM",platform)
- os.platform = platform
- return platform
- end
+end -- of closure
-elseif name == "freebsd" then
+do -- create closure to overcome 200 locals limit
- function os.resolvers.platform(t,k)
- local platform, architecture = "", os.resultof("uname -m") or ""
- if find(architecture,"amd64") then
- platform = "freebsd-amd64"
- else
- platform = "freebsd"
- end
- os.setenv("MTX_PLATFORM",platform)
- os.platform = platform
- return platform
- end
+package.loaded["trac-set"] = package.loaded["trac-set"] or true
-elseif name == "kfreebsd" then
+-- original size: 12365, stripped down to: 8799
- function os.resolvers.platform(t,k)
- -- we sometimes have HOSTTYPE set so let's check that first
- local platform, architecture = "", os.getenv("HOSTTYPE") or os.resultof("uname -m") or ""
- if find(architecture,"x86_64") then
- platform = "kfreebsd-amd64"
+if not modules then modules={} end modules ['trac-set']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local type,next,tostring=type,next,tostring
+local concat=table.concat
+local format,find,lower,gsub,topattern=string.format,string.find,string.lower,string.gsub,string.topattern
+local is_boolean=string.is_boolean
+local settings_to_hash=utilities.parsers.settings_to_hash
+local allocate=utilities.storage.allocate
+utilities=utilities or {}
+local utilities=utilities
+local setters=utilities.setters or {}
+utilities.setters=setters
+local data={}
+local trace_initialize=false
+function setters.initialize(filename,name,values)
+ local setter=data[name]
+ if setter then
+ frozen=true
+ local data=setter.data
+ if data then
+ for key,newvalue in next,values do
+ local newvalue=is_boolean(newvalue,newvalue)
+ local functions=data[key]
+ if functions then
+ local oldvalue=functions.value
+ if functions.frozen then
+ if trace_initialize then
+ setter.report("%s: %a is %s to %a",filename,key,"frozen",oldvalue)
+ end
+ elseif #functions>0 and not oldvalue then
+ if trace_initialize then
+ setter.report("%s: %a is %s to %a",filename,key,"set",newvalue)
+ end
+ for i=1,#functions do
+ functions[i](newvalue)
+ end
+ functions.value=newvalue
+ functions.frozen=functions.frozen or frozen
+ else
+ if trace_initialize then
+ setter.report("%s: %a is %s as %a",filename,key,"kept",oldvalue)
+ end
+ end
else
- platform = "kfreebsd-i386"
+ functions={ default=newvalue,frozen=frozen }
+ data[key]=functions
+ if trace_initialize then
+ setter.report("%s: %a is %s to %a",filename,key,"defaulted",newvalue)
+ end
end
- os.setenv("MTX_PLATFORM",platform)
- os.platform = platform
- return platform
+ end
+ return true
end
-
-else
-
- -- platform = "linux"
- -- os.setenv("MTX_PLATFORM",platform)
- -- os.platform = platform
-
- function os.resolvers.platform(t,k)
- local platform = "linux"
- os.setenv("MTX_PLATFORM",platform)
- os.platform = platform
- return platform
- end
-
+ end
end
-
--- beware, we set the randomseed
-
--- from wikipedia: Version 4 UUIDs use a scheme relying only on random numbers. This algorithm sets the
--- version number as well as two reserved bits. All other bits are set using a random or pseudorandom
--- data source. Version 4 UUIDs have the form xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx with hexadecimal
--- digits x and hexadecimal digits 8, 9, A, or B for y. e.g. f47ac10b-58cc-4372-a567-0e02b2c3d479.
---
--- as we don't call this function too often there is not so much risk on repetition
-
-local t = { 8, 9, "a", "b" }
-
-function os.uuid()
- return format("%04x%04x-4%03x-%s%03x-%04x-%04x%04x%04x",
- random(0xFFFF),random(0xFFFF),
- random(0x0FFF),
- t[ceil(random(4))] or 8,random(0x0FFF),
- random(0xFFFF),
- random(0xFFFF),random(0xFFFF),random(0xFFFF)
- )
+local function set(t,what,newvalue)
+ local data=t.data
+ if not data.frozen then
+ local done=t.done
+ if type(what)=="string" then
+ what=settings_to_hash(what)
+ end
+ if type(what)~="table" then
+ return
+ end
+ if not done then
+ done={}
+ t.done=done
+ end
+ for w,value in next,what do
+ if value=="" then
+ value=newvalue
+ elseif not value then
+ value=false
+ else
+ value=is_boolean(value,value)
+ end
+ w=topattern(w,true,true)
+ for name,functions in next,data do
+ if done[name] then
+ elseif find(name,w) then
+ done[name]=true
+ for i=1,#functions do
+ functions[i](value)
+ end
+ functions.value=value
+ end
+ end
+ end
+ end
end
-
-local d
-
-function os.timezone(delta)
- d = d or tonumber(tonumber(os.date("%H")-os.date("!%H")))
- if delta then
- if d > 0 then
- return format("+%02i:00",d)
- else
- return format("-%02i:00",-d)
- end
+local function reset(t)
+ local data=t.data
+ if not data.frozen then
+ for name,functions in next,data do
+ for i=1,#functions do
+ functions[i](false)
+ end
+ functions.value=false
+ end
+ end
+end
+local function enable(t,what)
+ set(t,what,true)
+end
+local function disable(t,what)
+ local data=t.data
+ if not what or what=="" then
+ t.done={}
+ reset(t)
+ else
+ set(t,what,false)
+ end
+end
+function setters.register(t,what,...)
+ local data=t.data
+ what=lower(what)
+ local functions=data[what]
+ if not functions then
+ functions={}
+ data[what]=functions
+ if trace_initialize then
+ t.report("defining %a",what)
+ end
+ end
+ local default=functions.default
+ for i=1,select("#",...) do
+ local fnc=select(i,...)
+ local typ=type(fnc)
+ if typ=="string" then
+ if trace_initialize then
+ t.report("coupling %a to %a",what,fnc)
+ end
+ local s=fnc
+ fnc=function(value) set(t,s,value) end
+ elseif typ~="function" then
+ fnc=nil
+ end
+ if fnc then
+ functions[#functions+1]=fnc
+ local value=functions.value or default
+ if value~=nil then
+ fnc(value)
+ functions.value=value
+ end
+ end
+ end
+ return false
+end
+function setters.enable(t,what)
+ local e=t.enable
+ t.enable,t.done=enable,{}
+ enable(t,what)
+ t.enable,t.done=e,{}
+end
+function setters.disable(t,what)
+ local e=t.disable
+ t.disable,t.done=disable,{}
+ disable(t,what)
+ t.disable,t.done=e,{}
+end
+function setters.reset(t)
+ t.done={}
+ reset(t)
+end
+function setters.list(t)
+ local list=table.sortedkeys(t.data)
+ local user,system={},{}
+ for l=1,#list do
+ local what=list[l]
+ if find(what,"^%*") then
+ system[#system+1]=what
else
- return 1
+ user[#user+1]=what
end
+ end
+ return user,system
end
-
-local memory = { }
-
-local function which(filename)
- local fullname = memory[filename]
- if fullname == nil then
- local suffix = file.suffix(filename)
- local suffixes = suffix == "" and os.binsuffixes or { suffix }
- for directory in gmatch(os.getenv("PATH"),"[^" .. io.pathseparator .."]+") do
- local df = file.join(directory,filename)
- for i=1,#suffixes do
- local dfs = file.addsuffix(df,suffixes[i])
- if io.exists(dfs) then
- fullname = dfs
- break
- end
- end
- end
- if not fullname then
- fullname = false
- end
- memory[filename] = fullname
+function setters.show(t)
+ local category=t.name
+ local list=setters.list(t)
+ t.report()
+ for k=1,#list do
+ local name=list[k]
+ local functions=t.data[name]
+ if functions then
+ local value,default,modules=functions.value,functions.default,#functions
+ value=value==nil and "unset" or tostring(value)
+ default=default==nil and "unset" or tostring(default)
+ t.report("%-50s modules: %2i default: %-12s value: %-12s",name,modules,default,value)
+ end
+ end
+ t.report()
+end
+local enable,disable,register,list,show=setters.enable,setters.disable,setters.register,setters.list,setters.show
+function setters.report(setter,...)
+ print(format("%-15s : %s\n",setter.name,format(...)))
+end
+local function default(setter,name)
+ local d=setter.data[name]
+ return d and d.default
+end
+local function value(setter,name)
+ local d=setter.data[name]
+ return d and (d.value or d.default)
+end
+function setters.new(name)
+ local setter
+ setter={
+ data=allocate(),
+ name=name,
+ report=function(...) setters.report (setter,...) end,
+ enable=function(...) enable (setter,...) end,
+ disable=function(...) disable (setter,...) end,
+ register=function(...) register(setter,...) end,
+ list=function(...) list (setter,...) end,
+ show=function(...) show (setter,...) end,
+ default=function(...) return default (setter,...) end,
+ value=function(...) return value (setter,...) end,
+ }
+ data[name]=setter
+ return setter
+end
+trackers=setters.new("trackers")
+directives=setters.new("directives")
+experiments=setters.new("experiments")
+local t_enable,t_disable=trackers .enable,trackers .disable
+local d_enable,d_disable=directives .enable,directives .disable
+local e_enable,e_disable=experiments.enable,experiments.disable
+local trace_directives=false local trace_directives=false trackers.register("system.directives",function(v) trace_directives=v end)
+local trace_experiments=false local trace_experiments=false trackers.register("system.experiments",function(v) trace_experiments=v end)
+function directives.enable(...)
+ if trace_directives then
+ directives.report("enabling: % t",{...})
+ end
+ d_enable(...)
+end
+function directives.disable(...)
+ if trace_directives then
+ directives.report("disabling: % t",{...})
+ end
+ d_disable(...)
+end
+function experiments.enable(...)
+ if trace_experiments then
+ experiments.report("enabling: % t",{...})
+ end
+ e_enable(...)
+end
+function experiments.disable(...)
+ if trace_experiments then
+ experiments.report("disabling: % t",{...})
+ end
+ e_disable(...)
+end
+directives.register("system.nostatistics",function(v)
+ if statistics then
+ statistics.enable=not v
+ else
+ end
+end)
+directives.register("system.nolibraries",function(v)
+ if libraries then
+ libraries=nil
+ else
+ end
+end)
+if environment then
+ local engineflags=environment.engineflags
+ if engineflags then
+ local list=engineflags["c:trackers"] or engineflags["trackers"]
+ if type(list)=="string" then
+ setters.initialize("commandline flags","trackers",settings_to_hash(list))
end
- return fullname
+ local list=engineflags["c:directives"] or engineflags["directives"]
+ if type(list)=="string" then
+ setters.initialize("commandline flags","directives",settings_to_hash(list))
+ end
+ end
+end
+if texconfig then
+ local function set(k,v)
+ v=tonumber(v)
+ if v then
+ texconfig[k]=v
+ end
+ end
+ directives.register("luatex.expanddepth",function(v) set("expand_depth",v) end)
+ directives.register("luatex.hashextra",function(v) set("hash_extra",v) end)
+ directives.register("luatex.nestsize",function(v) set("nest_size",v) end)
+ directives.register("luatex.maxinopen",function(v) set("max_in_open",v) end)
+ directives.register("luatex.maxprintline",function(v) set("max_print_line",v) end)
+ directives.register("luatex.maxstrings",function(v) set("max_strings",v) end)
+ directives.register("luatex.paramsize",function(v) set("param_size",v) end)
+ directives.register("luatex.savesize",function(v) set("save_size",v) end)
+ directives.register("luatex.stacksize",function(v) set("stack_size",v) end)
end
-
-os.which = which
-os.where = which
-
--- print(os.which("inkscape.exe"))
--- print(os.which("inkscape"))
--- print(os.which("gs.exe"))
--- print(os.which("ps2pdf"))
end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-file'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- needs a cleanup
-
-file = file or { }
-local file = file
-
-local insert, concat = table.insert, table.concat
-local find, gmatch, match, gsub, sub, char, lower = string.find, string.gmatch, string.match, string.gsub, string.sub, string.char, string.lower
-local lpegmatch = lpeg.match
-local getcurrentdir, attributes = lfs.currentdir, lfs.attributes
+package.loaded["trac-log"] = package.loaded["trac-log"] or true
-local P, R, S, C, Cs, Cp, Cc = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Cs, lpeg.Cp, lpeg.Cc
+-- original size: 21795, stripped down to: 14194
-local function dirname(name,default)
- return match(name,"^(.+)[/\\].-$") or (default or "")
+if not modules then modules={} end modules ['trac-log']={
+ version=1.001,
+ comment="companion to trac-log.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local write_nl,write=texio and texio.write_nl or print,texio and texio.write or io.write
+local format,gmatch,find=string.format,string.gmatch,string.find
+local concat,insert,remove=table.concat,table.insert,table.remove
+local topattern=string.topattern
+local texcount=tex and tex.count
+local next,type,select=next,type,select
+local utfchar=utf.char
+local setmetatableindex=table.setmetatableindex
+local formatters=string.formatters
+logs=logs or {}
+local logs=logs
+local moreinfo=[[
+More information about ConTeXt and the tools that come with it can be found at:
+]].."\n"..[[
+maillist : ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+webpage : http://www.pragma-ade.nl / http://tex.aanhet.net
+wiki : http://contextgarden.net
+]]
+utilities.strings.formatters.add (
+ formatters,"unichr",
+ [["U+" .. format("%%05X",%s) .. " (" .. utfchar(%s) .. ")"]]
+)
+utilities.strings.formatters.add (
+ formatters,"chruni",
+ [[utfchar(%s) .. " (U+" .. format("%%05X",%s) .. ")"]]
+)
+local function ignore() end
+setmetatableindex(logs,function(t,k) t[k]=ignore;return ignore end)
+local report,subreport,status,settarget,setformats,settranslations
+local direct,subdirect,writer,pushtarget,poptarget
+if tex and (tex.jobname or tex.formatname) then
+ local valueiskey={ __index=function(t,k) t[k]=k return k end }
+ local target="term and log"
+ logs.flush=io.flush
+ local formats={} setmetatable(formats,valueiskey)
+ local translations={} setmetatable(translations,valueiskey)
+ writer=function(...)
+ write_nl(target,...)
+ end
+ newline=function()
+ write_nl(target,"\n")
+ end
+ local f_one=formatters["%-15s > %s\n"]
+ local f_two=formatters["%-15s >\n"]
+ report=function(a,b,c,...)
+ if c then
+ write_nl(target,f_one(translations[a],formatters[formats[b]](c,...)))
+ elseif b then
+ write_nl(target,f_one(translations[a],formats[b]))
+ elseif a then
+ write_nl(target,f_two(translations[a]))
+ else
+ write_nl(target,"\n")
+ end
+ end
+ local f_one=formatters["%-15s > %s"]
+ local f_two=formatters["%-15s >"]
+ direct=function(a,b,c,...)
+ if c then
+ return f_one(translations[a],formatters[formats[b]](c,...))
+ elseif b then
+ return f_one(translations[a],formats[b])
+ elseif a then
+ return f_two(translations[a])
+ else
+ return ""
+ end
+ end
+ local f_one=formatters["%-15s > %s > %s\n"]
+ local f_two=formatters["%-15s > %s >\n"]
+ subreport=function(a,s,b,c,...)
+ if c then
+ write_nl(target,f_one(translations[a],translations[s],formatters[formats[b]](c,...)))
+ elseif b then
+ write_nl(target,f_one(translations[a],translations[s],formats[b]))
+ elseif a then
+ write_nl(target,f_two(translations[a],translations[s]))
+ else
+ write_nl(target,"\n")
+ end
+ end
+ local f_one=formatters["%-15s > %s > %s"]
+ local f_two=formatters["%-15s > %s >"]
+ subdirect=function(a,s,b,c,...)
+ if c then
+ return f_one(translations[a],translations[s],formatters[formats[b]](c,...))
+ elseif b then
+ return f_one(translations[a],translations[s],formats[b])
+ elseif a then
+ return f_two(translations[a],translations[s])
+ else
+ return ""
+ end
+ end
+ local f_one=formatters["%-15s : %s\n"]
+ local f_two=formatters["%-15s :\n"]
+ status=function(a,b,c,...)
+ if c then
+ write_nl(target,f_one(translations[a],formatters[formats[b]](c,...)))
+ elseif b then
+ write_nl(target,f_one(translations[a],formats[b]))
+ elseif a then
+ write_nl(target,f_two(translations[a]))
+ else
+ write_nl(target,"\n")
+ end
+ end
+ local targets={
+ logfile="log",
+ log="log",
+ file="log",
+ console="term",
+ terminal="term",
+ both="term and log",
+ }
+ settarget=function(whereto)
+ target=targets[whereto or "both"] or targets.both
+ if target=="term" or target=="term and log" then
+ logs.flush=io.flush
+ else
+ logs.flush=ignore
+ end
+ end
+ local stack={}
+ pushtarget=function(newtarget)
+ insert(stack,target)
+ settarget(newtarget)
+ end
+ poptarget=function()
+ if #stack>0 then
+ settarget(remove(stack))
+ end
+ end
+ setformats=function(f)
+ formats=f
+ end
+ settranslations=function(t)
+ translations=t
+ end
+else
+ logs.flush=ignore
+ writer=write_nl
+ newline=function()
+ write_nl("\n")
+ end
+ local f_one=formatters["%-15s | %s"]
+ local f_two=formatters["%-15s |"]
+ report=function(a,b,c,...)
+ if c then
+ write_nl(f_one(a,formatters[b](c,...)))
+ elseif b then
+ write_nl(f_one(a,b))
+ elseif a then
+ write_nl(f_two(a))
+ else
+ write_nl("")
+ end
+ end
+ local f_one=formatters["%-15s | %s | %s"]
+ local f_two=formatters["%-15s | %s |"]
+ subreport=function(a,sub,b,c,...)
+ if c then
+ write_nl(f_one(a,sub,formatters[b](c,...)))
+ elseif b then
+ write_nl(f_one(a,sub,b))
+ elseif a then
+ write_nl(f_two(a,sub))
+ else
+ write_nl("")
+ end
+ end
+ local f_one=formatters["%-15s : %s\n"]
+ local f_two=formatters["%-15s :\n"]
+ status=function(a,b,c,...)
+ if c then
+ write_nl(f_one(a,formatters[b](c,...)))
+ elseif b then
+ write_nl(f_one(a,b))
+ elseif a then
+ write_nl(f_two(a))
+ else
+ write_nl("\n")
+ end
+ end
+ direct=ignore
+ subdirect=ignore
+ settarget=ignore
+ pushtarget=ignore
+ poptarget=ignore
+ setformats=ignore
+ settranslations=ignore
+end
+logs.report=report
+logs.subreport=subreport
+logs.status=status
+logs.settarget=settarget
+logs.pushtarget=pushtarget
+logs.poptarget=poptarget
+logs.setformats=setformats
+logs.settranslations=settranslations
+logs.direct=direct
+logs.subdirect=subdirect
+logs.writer=writer
+logs.newline=newline
+local data,states={},nil
+function logs.reporter(category,subcategory)
+ local logger=data[category]
+ if not logger then
+ local state=false
+ if states==true then
+ state=true
+ elseif type(states)=="table" then
+ for c,_ in next,states do
+ if find(category,c) then
+ state=true
+ break
+ end
+ end
+ end
+ logger={
+ reporters={},
+ state=state,
+ }
+ data[category]=logger
+ end
+ local reporter=logger.reporters[subcategory or "default"]
+ if not reporter then
+ if subcategory then
+ reporter=function(...)
+ if not logger.state then
+ subreport(category,subcategory,...)
+ end
+ end
+ logger.reporters[subcategory]=reporter
+ else
+ local tag=category
+ reporter=function(...)
+ if not logger.state then
+ report(category,...)
+ end
+ end
+ logger.reporters.default=reporter
+ end
+ end
+ return reporter
end
-
-local function basename(name)
- return match(name,"^.+[/\\](.-)$") or name
+logs.new=logs.reporter
+local ctxreport=logs.writer
+function logs.setmessenger(m)
+ ctxreport=m
end
-
--- local function nameonly(name)
--- return (gsub(match(name,"^.+[/\\](.-)$") or name,"%..*$",""))
--- end
-
-local function nameonly(name)
- return (gsub(match(name,"^.+[/\\](.-)$") or name,"%.[%a%d]+$",""))
+function logs.messenger(category,subcategory)
+ if subcategory then
+ return function(...)
+ ctxreport(subdirect(category,subcategory,...))
+ end
+ else
+ return function(...)
+ ctxreport(direct(category,...))
+ end
+ end
end
-
-local function extname(name,default)
- return match(name,"^.+%.([^/\\]-)$") or default or ""
+local function setblocked(category,value)
+ if category==true then
+ category,value="*",true
+ elseif category==false then
+ category,value="*",false
+ elseif value==nil then
+ value=true
+ end
+ if category=="*" then
+ states=value
+ for k,v in next,data do
+ v.state=value
+ end
+ else
+ states=utilities.parsers.settings_to_hash(category)
+ for c,_ in next,states do
+ if data[c] then
+ v.state=value
+ else
+ c=topattern(c,true,true)
+ for k,v in next,data do
+ if find(k,c) then
+ v.state=value
+ end
+ end
+ end
+ end
+ end
end
-
-local function splitname(name)
- local n, s = match(name,"^(.+)%.([^/\\]-)$")
- return n or name, s or ""
+function logs.disable(category,value)
+ setblocked(category,value==nil and true or value)
end
-
-file.basename = basename
-file.dirname = dirname
-file.nameonly = nameonly
-file.extname = extname
-file.suffix = extname
-
-function file.removesuffix(filename)
- return (gsub(filename,"%.[%a%d]+$",""))
+function logs.enable(category)
+ setblocked(category,false)
end
-
-function file.addsuffix(filename, suffix, criterium)
- if not suffix or suffix == "" then
- return filename
- elseif criterium == true then
- return filename .. "." .. suffix
- elseif not criterium then
- local n, s = splitname(filename)
- if not s or s == "" then
- return filename .. "." .. suffix
- else
- return filename
- end
+function logs.categories()
+ return table.sortedkeys(data)
+end
+function logs.show()
+ local n,c,s,max=0,0,0,0
+ for category,v in table.sortedpairs(data) do
+ n=n+1
+ local state=v.state
+ local reporters=v.reporters
+ local nc=#category
+ if nc>c then
+ c=nc
+ end
+ for subcategory,_ in next,reporters do
+ local ns=#subcategory
+ if ns>c then
+ s=ns
+ end
+ local m=nc+ns
+ if m>max then
+ max=m
+ end
+ end
+ local subcategories=concat(table.sortedkeys(reporters),", ")
+ if state==true then
+ state="disabled"
+ elseif state==false then
+ state="enabled"
else
- local n, s = splitname(filename)
- if s and s ~= "" then
- local t = type(criterium)
- if t == "table" then
- -- keep if in criterium
- for i=1,#criterium do
- if s == criterium[i] then
- return filename
- end
- end
- elseif t == "string" then
- -- keep if criterium
- if s == criterium then
- return filename
- end
- end
- end
- return n .. "." .. suffix
+ state="unknown"
end
+ report("logging","category %a, subcategories %a, state %a",category,subcategories,state)
+ end
+ report("logging","categories: %s, max category: %s, max subcategory: %s, max combined: %s",n,c,s,max)
end
-
-
-function file.replacesuffix(filename, suffix)
- return (gsub(filename,"%.[%a%d]+$","")) .. "." .. suffix
+local delayed_reporters={}
+setmetatableindex(delayed_reporters,function(t,k)
+ local v=logs.reporter(k.name)
+ t[k]=v
+ return v
+end)
+function utilities.setters.report(setter,...)
+ delayed_reporters[setter](...)
end
-
-
-local trick_1 = char(1)
-local trick_2 = "^" .. trick_1 .. "/+"
-
-function file.join(...) -- rather dirty
- local lst = { ... }
- local a, b = lst[1], lst[2]
- if not a or a == "" then -- not a added
- lst[1] = trick_1
- elseif b and find(a,"^/+$") and find(b,"^/") then
- lst[1] = ""
- lst[2] = gsub(b,"^/+","")
- end
- local pth = concat(lst,"/")
- pth = gsub(pth,"\\","/")
- local a, b = match(pth,"^(.*://)(.*)$")
- if a and b then
- return a .. gsub(b,"//+","/")
+directives.register("logs.blocked",function(v)
+ setblocked(v,true)
+end)
+directives.register("logs.target",function(v)
+ settarget(v)
+end)
+local report_pages=logs.reporter("pages")
+local real,user,sub
+function logs.start_page_number()
+ real,user,sub=texcount.realpageno,texcount.userpageno,texcount.subpageno
+end
+local timing=false
+local starttime=nil
+local lasttime=nil
+trackers.register("pages.timing",function(v)
+ starttime=os.clock()
+ timing=true
+end)
+function logs.stop_page_number()
+ if timing then
+ local elapsed,average
+ local stoptime=os.clock()
+ if not lasttime or real<2 then
+ elapsed=stoptime
+ average=stoptime
+ starttime=stoptime
+ else
+ elapsed=stoptime-lasttime
+ average=(stoptime-starttime)/(real-1)
+ end
+ lasttime=stoptime
+ if real<=0 then
+ report_pages("flushing page, time %0.04f / %0.04f",elapsed,average)
+ elseif user<=0 then
+ report_pages("flushing realpage %s, time %0.04f / %0.04f",real,elapsed,average)
+ elseif sub<=0 then
+ report_pages("flushing realpage %s, userpage %s, time %0.04f / %0.04f",real,user,elapsed,average)
+ else
+ report_pages("flushing realpage %s, userpage %s, subpage %s, time %0.04f / %0.04f",real,user,sub,elapsed,average)
+ end
+ else
+ if real<=0 then
+ report_pages("flushing page")
+ elseif user<=0 then
+ report_pages("flushing realpage %s",real)
+ elseif sub<=0 then
+ report_pages("flushing realpage %s, userpage %s",real,user)
+ else
+ report_pages("flushing realpage %s, userpage %s, subpage %s",real,user,sub)
end
- a, b = match(pth,"^(//)(.*)$")
- if a and b then
- return a .. gsub(b,"//+","/")
+ end
+ logs.flush()
+end
+local report_files=logs.reporter("files")
+local nesting=0
+local verbose=false
+local hasscheme=url.hasscheme
+function logs.show_open(name)
+end
+function logs.show_close(name)
+end
+function logs.show_load(name)
+end
+local simple=logs.reporter("comment")
+logs.simple=simple
+logs.simpleline=simple
+function logs.setprogram () end
+function logs.extendbanner() end
+function logs.reportlines () end
+function logs.reportbanner() end
+function logs.reportline () end
+function logs.simplelines () end
+function logs.help () end
+local Carg,C,lpegmatch=lpeg.Carg,lpeg.C,lpeg.match
+local p_newline=lpeg.patterns.newline
+local linewise=(
+ Carg(1)*C((1-p_newline)^1)/function(t,s) t.report(s) end+Carg(1)*p_newline^2/function(t) t.report() end+p_newline
+)^1
+local function reportlines(t,str)
+ if str then
+ lpegmatch(linewise,str,1,t)
+ end
+end
+local function reportbanner(t)
+ local banner=t.banner
+ if banner then
+ t.report(banner)
+ t.report()
+ end
+end
+local function reportversion(t)
+ local banner=t.banner
+ if banner then
+ t.report(banner)
+ end
+end
+local function reporthelp(t,...)
+ local helpinfo=t.helpinfo
+ if type(helpinfo)=="string" then
+ reportlines(t,helpinfo)
+ elseif type(helpinfo)=="table" then
+ for i=1,select("#",...) do
+ reportlines(t,t.helpinfo[select(i,...)])
+ if i %s => %s => %s\r"](os.date("%d/%m/%y %H:%m:%S"),process,jobname,category,format(...))
+ for i=1,10 do
+ local f=io.open(whereto,"a")
+ if f then
+ f:write(message)
+ f:close()
+ break
else
- local f = io.open(name,"ab")
- if f then
- f:close()
- os.remove(name)
- return true
- end
+ sleep(0.1)
end
- return false
+ end
end
-
-function file.is_readable(name)
- local a = attributes(name)
- return a and sub(a.permissions,1,1) == "r"
+local report_system=logs.reporter("system","logs")
+function logs.obsolete(old,new)
+ local o=loadstring("return "..new)()
+ if type(o)=="function" then
+ return function(...)
+ report_system("function %a is obsolete, use %a",old,new)
+ loadstring(old.."="..new.." return "..old)()(...)
+ end
+ elseif type(o)=="table" then
+ local t,m={},{}
+ m.__index=function(t,k)
+ report_system("table %a is obsolete, use %a",old,new)
+ m.__index,m.__newindex=o,o
+ return o[k]
+ end
+ m.__newindex=function(t,k,v)
+ report_system("table %a is obsolete, use %a",old,new)
+ m.__index,m.__newindex=o,o
+ o[k]=v
+ end
+ if libraries then
+ libraries.obsolete[old]=t
+ end
+ setmetatable(t,m)
+ return t
+ end
end
-
-file.isreadable = file.is_readable -- depricated
-file.iswritable = file.is_writable -- depricated
-
--- todo: lpeg \\ / .. does not save much
-
-local checkedsplit = string.checkedsplit
-
-function file.splitpath(str,separator) -- string
- str = gsub(str,"\\","/")
- return checkedsplit(str,separator or io.pathseparator)
+if utilities then
+ utilities.report=report_system
end
-
-function file.joinpath(tab,separator) -- table
- return concat(tab,separator or io.pathseparator) -- can have trailing //
+if tex and tex.error then
+ function logs.texerrormessage(...)
+ tex.error(format(...),{})
+ end
+else
+ function logs.texerrormessage(...)
+ print(format(...))
+ end
end
+io.stdout:setvbuf('no')
+io.stderr:setvbuf('no')
--- we can hash them weakly
+end -- of closure
-function file.collapsepath(str,anchor)
- if anchor and not find(str,"^/") and not find(str,"^%a:") then
- str = getcurrentdir() .. "/" .. str
- end
- if str == "" or str =="." then
- return "."
- elseif find(str,"^%.%.") then
- str = gsub(str,"\\","/")
- return str
- elseif not find(str,"%.") then
- str = gsub(str,"\\","/")
- return str
- end
- str = gsub(str,"\\","/")
- local starter, rest = match(str,"^(%a+:/*)(.-)$")
- if starter then
- str = rest
- end
- local oldelements = checkedsplit(str,"/")
- local newelements = { }
- local i = #oldelements
- while i > 0 do
- local element = oldelements[i]
- if element == '.' then
- -- do nothing
- elseif element == '..' then
- local n = i - 1
- while n > 0 do
- local element = oldelements[n]
- if element ~= '..' and element ~= '.' then
- oldelements[n] = '.'
- break
- else
- n = n - 1
- end
- end
- if n < 1 then
- insert(newelements,1,'..')
- end
- elseif element ~= "" then
- insert(newelements,1,element)
- end
- i = i - 1
- end
- if #newelements == 0 then
- return starter or "."
- elseif starter then
- return starter .. concat(newelements, '/')
- elseif find(str,"^/") then
- return "/" .. concat(newelements,'/')
- else
- return concat(newelements, '/')
- end
-end
+do -- create closure to overcome 200 locals limit
+package.loaded["trac-inf"] = package.loaded["trac-inf"] or true
-function file.robustname(str,strict)
- str = gsub(str,"[^%a%d%/%-%.\\]+","-")
- if strict then
- return lower(gsub(str,"^%-*(.-)%-*$","%1"))
- else
- return str
+-- original size: 5791, stripped down to: 4540
+
+if not modules then modules={} end modules ['trac-inf']={
+ version=1.001,
+ comment="companion to trac-inf.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local type,tonumber=type,tonumber
+local format,lower=string.format,string.lower
+local concat=table.concat
+local clock=os.gettimeofday or os.clock
+statistics=statistics or {}
+local statistics=statistics
+statistics.enable=true
+statistics.threshold=0.01
+local statusinfo,n,registered,timers={},0,{},{}
+table.setmetatableindex(timers,function(t,k)
+ local v={ timing=0,loadtime=0 }
+ t[k]=v
+ return v
+end)
+local function hastiming(instance)
+ return instance and timers[instance]
+end
+local function resettiming(instance)
+ timers[instance or "notimer"]={ timing=0,loadtime=0 }
+end
+local function starttiming(instance)
+ local timer=timers[instance or "notimer"]
+ local it=timer.timing or 0
+ if it==0 then
+ timer.starttime=clock()
+ if not timer.loadtime then
+ timer.loadtime=0
+ end
+ end
+ timer.timing=it+1
+end
+local function stoptiming(instance,report)
+ local timer=timers[instance or "notimer"]
+ local it=timer.timing
+ if it>1 then
+ timer.timing=it-1
+ else
+ local starttime=timer.starttime
+ if starttime then
+ local stoptime=clock()
+ local loadtime=stoptime-starttime
+ timer.stoptime=stoptime
+ timer.loadtime=timer.loadtime+loadtime
+ if report then
+ statistics.report("load time %0.3f",loadtime)
+ end
+ timer.timing=0
+ return loadtime
+ end
+ end
+ return 0
+end
+local function elapsed(instance)
+ if type(instance)=="number" then
+ return instance or 0
+ else
+ local timer=timers[instance or "notimer"]
+ return timer and timer.loadtime or 0
+ end
+end
+local function elapsedtime(instance)
+ return format("%0.3f",elapsed(instance))
+end
+local function elapsedindeed(instance)
+ return elapsed(instance)>statistics.threshold
+end
+local function elapsedseconds(instance,rest)
+ if elapsedindeed(instance) then
+ return format("%0.3f seconds %s",elapsed(instance),rest or "")
+ end
+end
+statistics.hastiming=hastiming
+statistics.resettiming=resettiming
+statistics.starttiming=starttiming
+statistics.stoptiming=stoptiming
+statistics.elapsed=elapsed
+statistics.elapsedtime=elapsedtime
+statistics.elapsedindeed=elapsedindeed
+statistics.elapsedseconds=elapsedseconds
+function statistics.register(tag,fnc)
+ if statistics.enable and type(fnc)=="function" then
+ local rt=registered[tag] or (#statusinfo+1)
+ statusinfo[rt]={ tag,fnc }
+ registered[tag]=rt
+ if #tag>n then n=#tag end
+ end
+end
+local report=logs.reporter("mkiv lua stats")
+function statistics.show()
+ if statistics.enable then
+ local register=statistics.register
+ register("luatex banner",function()
+ return lower(status.banner)
+ end)
+ register("control sequences",function()
+ return format("%s of %s + %s",status.cs_count,status.hash_size,status.hash_extra)
+ end)
+ register("callbacks",function()
+ local total,indirect=status.callbacks or 0,status.indirect_callbacks or 0
+ return format("%s direct, %s indirect, %s total",total-indirect,indirect,total)
+ end)
+ if jit then
+ local status={ jit.status() }
+ if status[1] then
+ register("luajit status",function()
+ return concat(status," ",2)
+ end)
+ end
+ end
+ register("current memory usage",statistics.memused)
+ register("runtime",statistics.runtime)
+ logs.newline()
+ for i=1,#statusinfo do
+ local s=statusinfo[i]
+ local r=s[2]()
+ if r then
+ report("%s: %s",s[1],r)
+ end
end
+ statistics.enable=false
+ end
end
-
-file.readdata = io.loaddata
-file.savedata = io.savedata
-
-function file.copy(oldname,newname)
- file.savedata(newname,io.loaddata(oldname))
+function statistics.memused()
+ local round=math.round or math.floor
+ return format("%s MB (ctx: %s MB)",round(collectgarbage("count")/1000),round(status.luastate_bytes/1000000))
+end
+starttiming(statistics)
+function statistics.formatruntime(runtime)
+ return format("%s seconds",runtime)
+end
+function statistics.runtime()
+ stoptiming(statistics)
+ return statistics.formatruntime(elapsedtime(statistics))
+end
+local report=logs.reporter("system")
+function statistics.timed(action)
+ starttiming("run")
+ action()
+ stoptiming("run")
+ report("total runtime: %s",elapsedtime("run"))
+end
+commands=commands or {}
+function commands.resettimer(name)
+ resettiming(name or "whatever")
+ starttiming(name or "whatever")
+end
+function commands.elapsedtime(name)
+ stoptiming(name or "whatever")
+ context(elapsedtime(name or "whatever"))
end
-
--- lpeg variants, slightly faster, not always
+end -- of closure
+do -- create closure to overcome 200 locals limit
+package.loaded["trac-pro"] = package.loaded["trac-pro"] or true
+-- original size: 5773, stripped down to: 3453
+if not modules then modules={} end modules ['trac-pro']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local getmetatable,setmetatable,rawset,type=getmetatable,setmetatable,rawset,type
+local trace_namespaces=false trackers.register("system.namespaces",function(v) trace_namespaces=v end)
+local report_system=logs.reporter("system","protection")
+namespaces=namespaces or {}
+local namespaces=namespaces
+local registered={}
+local function report_index(k,name)
+ if trace_namespaces then
+ report_system("reference to %a in protected namespace %a: %s",k,name,debug.traceback())
+ else
+ report_system("reference to %a in protected namespace %a",k,name)
+ end
+end
+local function report_newindex(k,name)
+ if trace_namespaces then
+ report_system("assignment to %a in protected namespace %a: %s",k,name,debug.traceback())
+ else
+ report_system("assignment to %a in protected namespace %a",k,name)
+ end
+end
+local function register(name)
+ local data=name=="global" and _G or _G[name]
+ if not data then
+ return
+ end
+ registered[name]=data
+ local m=getmetatable(data)
+ if not m then
+ m={}
+ setmetatable(data,m)
+ end
+ local index,newindex={},{}
+ m.__saved__index=m.__index
+ m.__no__index=function(t,k)
+ if not index[k] then
+ index[k]=true
+ report_index(k,name)
+ end
+ return nil
+ end
+ m.__saved__newindex=m.__newindex
+ m.__no__newindex=function(t,k,v)
+ if not newindex[k] then
+ newindex[k]=true
+ report_newindex(k,name)
+ end
+ rawset(t,k,v)
+ end
+ m.__protection__depth=0
+end
+local function private(name)
+ local data=registered[name]
+ if not data then
+ data=_G[name]
+ if not data then
+ data={}
+ _G[name]=data
+ end
+ register(name)
+ end
+ return data
+end
+local function protect(name)
+ local data=registered[name]
+ if not data then
+ return
+ end
+ local m=getmetatable(data)
+ local pd=m.__protection__depth
+ if pd>0 then
+ m.__protection__depth=pd+1
+ else
+ m.__save_d_index,m.__saved__newindex=m.__index,m.__newindex
+ m.__index,m.__newindex=m.__no__index,m.__no__newindex
+ m.__protection__depth=1
+ end
+end
+local function unprotect(name)
+ local data=registered[name]
+ if not data then
+ return
+ end
+ local m=getmetatable(data)
+ local pd=m.__protection__depth
+ if pd>1 then
+ m.__protection__depth=pd-1
+ else
+ m.__index,m.__newindex=m.__saved__index,m.__saved__newindex
+ m.__protection__depth=0
+ end
+end
+local function protectall()
+ for name,_ in next,registered do
+ if name~="global" then
+ protect(name)
+ end
+ end
+end
+local function unprotectall()
+ for name,_ in next,registered do
+ if name~="global" then
+ unprotect(name)
+ end
+ end
+end
+namespaces.register=register
+namespaces.private=private
+namespaces.protect=protect
+namespaces.unprotect=unprotect
+namespaces.protectall=protectall
+namespaces.unprotectall=unprotectall
+namespaces.private("namespaces") registered={} register("global")
+directives.register("system.protect",function(v)
+ if v then
+ protectall()
+ else
+ unprotectall()
+ end
+end)
+directives.register("system.checkglobals",function(v)
+ if v then
+ report_system("enabling global namespace guard")
+ protect("global")
+ else
+ report_system("disabling global namespace guard")
+ unprotect("global")
+ end
+end)
+end -- of closure
+do -- create closure to overcome 200 locals limit
+package.loaded["util-lua"] = package.loaded["util-lua"] or true
+-- original size: 12575, stripped down to: 8700
-
-
-
-
-
-
-
--- also rewrite previous
-
-local letter = R("az","AZ") + S("_-+")
-local separator = P("://")
-
-local qualified = P(".")^0 * P("/") + letter*P(":") + letter^1*separator + letter^1 * P("/")
-local rootbased = P("/") + letter*P(":")
-
-lpeg.patterns.qualified = qualified
-lpeg.patterns.rootbased = rootbased
-
--- ./name ../name /name c: :// name/name
-
-function file.is_qualified_path(filename)
- return lpegmatch(qualified,filename) ~= nil
+if not modules then modules={} end modules ['util-lua']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ comment="the strip code is written by Peter Cawley",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local rep,sub,byte,dump,format=string.rep,string.sub,string.byte,string.dump,string.format
+local load,loadfile,type=load,loadfile,type
+utilities=utilities or {}
+utilities.lua=utilities.lua or {}
+local luautilities=utilities.lua
+local report_lua=logs.reporter("system","lua")
+local tracestripping=false
+local forcestupidcompile=true
+luautilities.stripcode=true
+luautilities.alwaysstripcode=false
+luautilities.nofstrippedchunks=0
+luautilities.nofstrippedbytes=0
+local strippedchunks={}
+luautilities.strippedchunks=strippedchunks
+luautilities.suffixes={
+ tma="tma",
+ tmc=jit and "tmb" or "tmc",
+ lua="lua",
+ luc=jit and "lub" or "luc",
+ lui="lui",
+ luv="luv",
+ luj="luj",
+ tua="tua",
+ tuc="tuc",
+}
+if jit or status.luatex_version>=74 then
+ local function register(name)
+ if tracestripping then
+ report_lua("stripped bytecode from %a",name or "unknown")
+ end
+ strippedchunks[#strippedchunks+1]=name
+ luautilities.nofstrippedchunks=luautilities.nofstrippedchunks+1
+ end
+ local function stupidcompile(luafile,lucfile,strip)
+ local code=io.loaddata(luafile)
+ if code and code~="" then
+ code=load(code)
+ if code then
+ code=dump(code,strip and luautilities.stripcode or luautilities.alwaysstripcode)
+ if code and code~="" then
+ register(name)
+ io.savedata(lucfile,code)
+ return true,0
+ end
+ else
+ report_lua("fatal error %a in file %a",1,luafile)
+ end
+ else
+ report_lua("fatal error %a in file %a",2,luafile)
+ end
+ return false,0
+ end
+ function luautilities.loadedluacode(fullname,forcestrip,name)
+ name=name or fullname
+ local code=environment.loadpreprocessedfile and environment.loadpreprocessedfile(fullname) or loadfile(fullname)
+ if code then
+ code()
+ end
+ if forcestrip and luautilities.stripcode then
+ if type(forcestrip)=="function" then
+ forcestrip=forcestrip(fullname)
+ end
+ if forcestrip or luautilities.alwaysstripcode then
+ register(name)
+ return load(dump(code,true)),0
+ else
+ return code,0
+ end
+ elseif luautilities.alwaysstripcode then
+ register(name)
+ return load(dump(code,true)),0
+ else
+ return code,0
+ end
+ end
+ function luautilities.strippedloadstring(code,forcestrip,name)
+ if forcestrip and luautilities.stripcode or luautilities.alwaysstripcode then
+ code=load(code)
+ if not code then
+ report_lua("fatal error %a in file %a",3,name)
+ end
+ register(name)
+ code=dump(code,true)
+ end
+ return load(code),0
+ end
+ function luautilities.compile(luafile,lucfile,cleanup,strip,fallback)
+ report_lua("compiling %a into %a",luafile,lucfile)
+ os.remove(lucfile)
+ local done=stupidcompile(luafile,lucfile,strip~=false)
+ if done then
+ report_lua("dumping %a into %a stripped",luafile,lucfile)
+ if cleanup==true and lfs.isfile(lucfile) and lfs.isfile(luafile) then
+ report_lua("removing %a",luafile)
+ os.remove(luafile)
+ end
+ end
+ return done
+ end
+ function luautilities.loadstripped(...)
+ local l=load(...)
+ if l then
+ return load(dump(l,true))
+ end
+ end
+else
+ local function register(name,before,after)
+ local delta=before-after
+ if tracestripping then
+ report_lua("bytecodes stripped from %a, # before %s, # after %s, delta %s",name,before,after,delta)
+ end
+ strippedchunks[#strippedchunks+1]=name
+ luautilities.nofstrippedchunks=luautilities.nofstrippedchunks+1
+ luautilities.nofstrippedbytes=luautilities.nofstrippedbytes+delta
+ return delta
+ end
+ local strip_code_pc
+ if _MAJORVERSION==5 and _MINORVERSION==1 then
+ strip_code_pc=function(dump,name)
+ local before=#dump
+ local version,format,endian,int,size,ins,num=byte(dump,5,11)
+ local subint
+ if endian==1 then
+ subint=function(dump,i,l)
+ local val=0
+ for n=l,1,-1 do
+ val=val*256+byte(dump,i+n-1)
+ end
+ return val,i+l
+ end
+ else
+ subint=function(dump,i,l)
+ local val=0
+ for n=1,l,1 do
+ val=val*256+byte(dump,i+n-1)
+ end
+ return val,i+l
+ end
+ end
+ local strip_function
+ strip_function=function(dump)
+ local count,offset=subint(dump,1,size)
+ local stripped,dirty=rep("\0",size),offset+count
+ offset=offset+count+int*2+4
+ offset=offset+int+subint(dump,offset,int)*ins
+ count,offset=subint(dump,offset,int)
+ for n=1,count do
+ local t
+ t,offset=subint(dump,offset,1)
+ if t==1 then
+ offset=offset+1
+ elseif t==4 then
+ offset=offset+size+subint(dump,offset,size)
+ elseif t==3 then
+ offset=offset+num
+ end
+ end
+ count,offset=subint(dump,offset,int)
+ stripped=stripped..sub(dump,dirty,offset-1)
+ for n=1,count do
+ local proto,off=strip_function(sub(dump,offset,-1))
+ stripped,offset=stripped..proto,offset+off-1
+ end
+ offset=offset+subint(dump,offset,int)*int+int
+ count,offset=subint(dump,offset,int)
+ for n=1,count do
+ offset=offset+subint(dump,offset,size)+size+int*2
+ end
+ count,offset=subint(dump,offset,int)
+ for n=1,count do
+ offset=offset+subint(dump,offset,size)+size
+ end
+ stripped=stripped..rep("\0",int*3)
+ return stripped,offset
+ end
+ dump=sub(dump,1,12)..strip_function(sub(dump,13,-1))
+ local after=#dump
+ local delta=register(name,before,after)
+ return dump,delta
+ end
+ else
+ strip_code_pc=function(dump,name)
+ return dump,0
+ end
+ end
+ function luautilities.loadedluacode(fullname,forcestrip,name)
+ local code=environment.loadpreprocessedfile and environment.preprocessedloadfile(fullname) or loadfile(fullname)
+ if code then
+ code()
+ end
+ if forcestrip and luautilities.stripcode then
+ if type(forcestrip)=="function" then
+ forcestrip=forcestrip(fullname)
+ end
+ if forcestrip then
+ local code,n=strip_code_pc(dump(code),name)
+ return load(code),n
+ elseif luautilities.alwaysstripcode then
+ return load(strip_code_pc(dump(code),name))
+ else
+ return code,0
+ end
+ elseif luautilities.alwaysstripcode then
+ return load(strip_code_pc(dump(code),name))
+ else
+ return code,0
+ end
+ end
+ function luautilities.strippedloadstring(code,forcestrip,name)
+ local n=0
+ if (forcestrip and luautilities.stripcode) or luautilities.alwaysstripcode then
+ code=load(code)
+ if not code then
+ report_lua("fatal error in file %a",name)
+ end
+ code,n=strip_code_pc(dump(code),name)
+ end
+ return load(code),n
+ end
+ local function stupidcompile(luafile,lucfile,strip)
+ local code=io.loaddata(luafile)
+ local n=0
+ if code and code~="" then
+ code=load(code)
+ if not code then
+ report_lua("fatal error in file %a",luafile)
+ end
+ code=dump(code)
+ if strip then
+ code,n=strip_code_pc(code,luautilities.stripcode or luautilities.alwaysstripcode,luafile)
+ end
+ if code and code~="" then
+ io.savedata(lucfile,code)
+ end
+ end
+ return n
+ end
+ local luac_normal="texluac -o %q %q"
+ local luac_strip="texluac -s -o %q %q"
+ function luautilities.compile(luafile,lucfile,cleanup,strip,fallback)
+ report_lua("compiling %a into %a",luafile,lucfile)
+ os.remove(lucfile)
+ local done=false
+ if strip~=false then
+ strip=true
+ end
+ if forcestupidcompile then
+ fallback=true
+ elseif strip then
+ done=os.spawn(format(luac_strip,lucfile,luafile))==0
+ else
+ done=os.spawn(format(luac_normal,lucfile,luafile))==0
+ end
+ if not done and fallback then
+ local n=stupidcompile(luafile,lucfile,strip)
+ if n>0 then
+ report_lua("%a dumped into %a (%i bytes stripped)",luafile,lucfile,n)
+ else
+ report_lua("%a dumped into %a (unstripped)",luafile,lucfile)
+ end
+ cleanup=false
+ done=true
+ end
+ if done and cleanup==true and lfs.isfile(lucfile) and lfs.isfile(luafile) then
+ report_lua("removing %a",luafile)
+ os.remove(luafile)
+ end
+ return done
+ end
+ luautilities.loadstripped=loadstring
end
-function file.is_rootbased_path(filename)
- return lpegmatch(rootbased,filename) ~= nil
-end
--- actually these are schemes
+end -- of closure
-local slash = S("\\/")
-local period = P(".")
-local drive = C(R("az","AZ")) * P(":")
-local path = C(((1-slash)^0 * slash)^0)
-local suffix = period * C(P(1-period)^0 * P(-1))
-local base = C((1-suffix)^0)
+do -- create closure to overcome 200 locals limit
-drive = drive + Cc("")
-path = path + Cc("")
-base = base + Cc("")
-suffix = suffix + Cc("")
+package.loaded["util-deb"] = package.loaded["util-deb"] or true
-local pattern_a = drive * path * base * suffix
-local pattern_b = path * base * suffix
-local pattern_c = C(drive * path) * C(base * suffix)
+-- original size: 3708, stripped down to: 2568
-function file.splitname(str,splitdrive)
- if splitdrive then
- return lpegmatch(pattern_a,str) -- returns drive, path, base, suffix
+if not modules then modules={} end modules ['util-deb']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local debug=require "debug"
+local getinfo=debug.getinfo
+local type,next,tostring=type,next,tostring
+local format,find=string.format,string.find
+local is_boolean=string.is_boolean
+utilities=utilities or {}
+local debugger=utilities.debugger or {}
+utilities.debugger=debugger
+local counters={}
+local names={}
+local report=logs.reporter("debugger")
+local function hook()
+ local f=getinfo(2)
+ if f then
+ local n="unknown"
+ if f.what=="C" then
+ n=f.name or ''
+ if not names[n] then
+ names[n]=format("%42s",n)
+ end
else
- return lpegmatch(pattern_b,str) -- returns path, base, suffix
- end
+ n=f.name or f.namewhat or f.what
+ if not n or n=="" then
+ n="?"
+ end
+ if not names[n] then
+ names[n]=format("%42s : % 5i : %s",n,f.linedefined or 0,f.short_src or "unknown source")
+ end
+ end
+ counters[n]=(counters[n] or 0)+1
+ end
+end
+function debugger.showstats(printer,threshold)
+ printer=printer or report
+ threshold=threshold or 0
+ local total,grandtotal,functions=0,0,0
+ local dataset={}
+ for name,count in next,counters do
+ dataset[#dataset+1]={ name,count }
+ end
+ table.sort(dataset,function(a,b) return a[2]==b[2] and b[1]>a[1] or a[2]>b[2] end)
+ for i=1,#dataset do
+ local d=dataset[i]
+ local name=d[1]
+ local count=d[2]
+ if count>threshold and not find(name,"for generator") then
+ printer(format("%8i %s\n",count,names[name]))
+ total=total+count
+ end
+ grandtotal=grandtotal+count
+ functions=functions+1
+ end
+ printer("\n")
+ printer(format("functions : % 10i\n",functions))
+ printer(format("total : % 10i\n",total))
+ printer(format("grand total: % 10i\n",grandtotal))
+ printer(format("threshold : % 10i\n",threshold))
end
-
-function file.nametotable(str,splitdrive) -- returns table
- local path, drive, subpath, name, base, suffix = lpegmatch(pattern_c,str)
- if splitdrive then
- return {
- path = path,
- drive = drive,
- subpath = subpath,
- name = name,
- base = base,
- suffix = suffix,
- }
+function debugger.savestats(filename,threshold)
+ local f=io.open(filename,'w')
+ if f then
+ debugger.showstats(function(str) f:write(str) end,threshold)
+ f:close()
+ end
+end
+function debugger.enable()
+ debug.sethook(hook,"c")
+end
+function debugger.disable()
+ debug.sethook()
+end
+function traceback()
+ local level=1
+ while true do
+ local info=debug.getinfo(level,"Sl")
+ if not info then
+ break
+ elseif info.what=="C" then
+ print(format("%3i : C function",level))
else
- return {
- path = path,
- name = name,
- base = base,
- suffix = suffix,
- }
+ print(format("%3i : [%s]:%d",level,info.short_src,info.currentline))
end
-end
-
--- function test(t) for k, v in next, t do print(v, "=>", file.splitname(v)) end end
---
--- test { "c:", "c:/aa", "c:/aa/bb", "c:/aa/bb/cc", "c:/aa/bb/cc.dd", "c:/aa/bb/cc.dd.ee" }
--- test { "c:", "c:aa", "c:aa/bb", "c:aa/bb/cc", "c:aa/bb/cc.dd", "c:aa/bb/cc.dd.ee" }
--- test { "/aa", "/aa/bb", "/aa/bb/cc", "/aa/bb/cc.dd", "/aa/bb/cc.dd.ee" }
--- test { "aa", "aa/bb", "aa/bb/cc", "aa/bb/cc.dd", "aa/bb/cc.dd.ee" }
-
-
--- for myself:
-
-function file.strip(name,dir)
- local b, a = match(name,"^(.-)" .. dir .. "(.*)$")
- return a ~= "" and a or name
+ level=level+1
+ end
end
@@ -3060,64 +7388,292 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-md5'] = {
- version = 1.001,
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
+package.loaded["util-mrg"] = package.loaded["util-mrg"] or true
+
+-- original size: 7294, stripped down to: 5798
+
+if not modules then modules={} end modules ['util-mrg']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
}
+local gsub,format=string.gsub,string.format
+local concat=table.concat
+local type,next=type,next
+local P,R,S,V,Ct,C,Cs,Cc,Cp,Cmt,Cb,Cg=lpeg.P,lpeg.R,lpeg.S,lpeg.V,lpeg.Ct,lpeg.C,lpeg.Cs,lpeg.Cc,lpeg.Cp,lpeg.Cmt,lpeg.Cb,lpeg.Cg
+local lpegmatch,patterns=lpeg.match,lpeg.patterns
+utilities=utilities or {}
+local merger=utilities.merger or {}
+utilities.merger=merger
+merger.strip_comment=true
+local report=logs.reporter("system","merge")
+utilities.report=report
+local m_begin_merge="begin library merge"
+local m_end_merge="end library merge"
+local m_begin_closure="do -- create closure to overcome 200 locals limit"
+local m_end_closure="end -- of closure"
+local m_pattern="%c+".."%-%-%s+"..m_begin_merge.."%c+(.-)%c+".."%-%-%s+"..m_end_merge.."%c+"
+local m_format="\n\n-- "..m_begin_merge.."\n%s\n".."-- "..m_end_merge.."\n\n"
+local m_faked="-- ".."created merged file".."\n\n".."-- "..m_begin_merge.."\n\n".."-- "..m_end_merge.."\n\n"
+local m_report=[[
+-- used libraries : %s
+-- skipped libraries : %s
+-- original bytes : %s
+-- stripped bytes : %s
+]]
+local m_preloaded=[[package.loaded[%q] = package.loaded[%q] or true]]
+local function self_fake()
+ return m_faked
+end
+local function self_nothing()
+ return ""
+end
+local function self_load(name)
+ local data=io.loaddata(name) or ""
+ if data=="" then
+ report("unknown file %a",name)
+ else
+ report("inserting file %a",name)
+ end
+ return data or ""
+end
+local space=patterns.space
+local eol=patterns.newline
+local equals=P("=")^0
+local open=P("[")*Cg(equals,"init")*P("[")*P("\n")^-1
+local close=P("]")*C(equals)*P("]")
+local closeeq=Cmt(close*Cb("init"),function(s,i,a,b) return a==b end)
+local longstring=open*(1-closeeq)^0*close
+local quoted=patterns.quoted
+local emptyline=space^0*eol
+local operator1=P("<=")+P(">=")+P("~=")+P("..")+S("/^<>=*+%%")
+local operator2=S("*+/")
+local operator3=S("-")
+local separator=S(",;")
+local ignore=(P("]")*space^1*P("=")*space^1*P("]"))/"]=["+(P("=")*space^1*P("{"))/"={"+(P("(")*space^1)/"("+(P("{")*(space+eol)^1*P("}"))/"{}"
+local strings=quoted
+local longcmt=(emptyline^0*P("--")*longstring*emptyline^0)/""
+local longstr=longstring
+local comment=emptyline^0*P("--")*P("-")^0*(1-eol)^0*emptyline^1/"\n"
+local pack=((eol+space)^0/"")*operator1*((eol+space)^0/"")+((eol+space)^0/"")*operator2*((space)^0/"")+((eol+space)^1/"")*operator3*((space)^1/"")+((space)^0/"")*separator*((space)^0/"")
+local lines=emptyline^2/"\n"
+local spaces=(space*space)/" "
+local compact=Cs ((
+ ignore+strings+longcmt+longstr+comment+pack+lines+spaces+1
+)^1 )
+local strip=Cs((emptyline^2/"\n"+1)^0)
+local stripreturn=Cs((1-P("return")*space^1*P(1-space-eol)^1*(space+eol)^0*P(-1))^1)
+function merger.compact(data)
+ return lpegmatch(strip,lpegmatch(compact,data))
+end
+local function self_compact(data)
+ local delta=0
+ if merger.strip_comment then
+ local before=#data
+ data=lpegmatch(compact,data)
+ data=lpegmatch(strip,data)
+ local after=#data
+ delta=before-after
+ report("original size %s, compacted to %s, stripped %s",before,after,delta)
+ data=format("-- original size: %s, stripped down to: %s\n\n%s",before,after,data)
+ end
+ return lpegmatch(stripreturn,data) or data,delta
+end
+local function self_save(name,data)
+ if data~="" then
+ io.savedata(name,data)
+ report("saving %s with size %s",name,#data)
+ end
+end
+local function self_swap(data,code)
+ return data~="" and (gsub(data,m_pattern,function() return format(m_format,code) end,1)) or ""
+end
+local function self_libs(libs,list)
+ local result,f,frozen,foundpath={},nil,false,nil
+ result[#result+1]="\n"
+ if type(libs)=='string' then libs={ libs } end
+ if type(list)=='string' then list={ list } end
+ for i=1,#libs do
+ local lib=libs[i]
+ for j=1,#list do
+ local pth=gsub(list[j],"\\","/")
+ report("checking library path %a",pth)
+ local name=pth.."/"..lib
+ if lfs.isfile(name) then
+ foundpath=pth
+ end
+ end
+ if foundpath then break end
+ end
+ if foundpath then
+ report("using library path %a",foundpath)
+ local right,wrong,original,stripped={},{},0,0
+ for i=1,#libs do
+ local lib=libs[i]
+ local fullname=foundpath.."/"..lib
+ if lfs.isfile(fullname) then
+ report("using library %a",fullname)
+ local preloaded=file.nameonly(lib)
+ local data=io.loaddata(fullname,true)
+ original=original+#data
+ local data,delta=self_compact(data)
+ right[#right+1]=lib
+ result[#result+1]=m_begin_closure
+ result[#result+1]=format(m_preloaded,preloaded,preloaded)
+ result[#result+1]=data
+ result[#result+1]=m_end_closure
+ stripped=stripped+delta
+ else
+ report("skipping library %a",fullname)
+ wrong[#wrong+1]=lib
+ end
+ end
+ right=#right>0 and concat(right," ") or "-"
+ wrong=#wrong>0 and concat(wrong," ") or "-"
+ report("used libraries: %a",right)
+ report("skipped libraries: %a",wrong)
+ report("original bytes: %a",original)
+ report("stripped bytes: %a",stripped)
+ result[#result+1]=format(m_report,right,wrong,original,stripped)
+ else
+ report("no valid library path found")
+ end
+ return concat(result,"\n\n")
+end
+function merger.selfcreate(libs,list,target)
+ if target then
+ self_save(target,self_swap(self_fake(),self_libs(libs,list)))
+ end
+end
+function merger.selfmerge(name,libs,list,target)
+ self_save(target or name,self_swap(self_load(name),self_libs(libs,list)))
+end
+function merger.selfclean(name)
+ self_save(name,self_swap(self_load(name),self_nothing()))
+end
--- This also provides file checksums and checkers.
-local md5, file = md5, file
-local gsub, format, byte = string.gsub, string.format, string.byte
+end -- of closure
-local function convert(str,fmt)
- return (gsub(md5.sum(str),".",function(chr) return format(fmt,byte(chr)) end))
-end
+do -- create closure to overcome 200 locals limit
-if not md5.HEX then function md5.HEX(str) return convert(str,"%02X") end end
-if not md5.hex then function md5.hex(str) return convert(str,"%02x") end end
-if not md5.dec then function md5.dec(str) return convert(str,"%03i") end end
+package.loaded["util-tpl"] = package.loaded["util-tpl"] or true
+-- original size: 5655, stripped down to: 3242
-function file.needs_updating(oldname,newname,threshold) -- size modification access change
- local oldtime = lfs.attributes(oldname, modification)
- local newtime = lfs.attributes(newname, modification)
- if newtime >= oldtime then
- return false
- elseif oldtime - newtime < (threshold or 1) then
- return false
- else
- return true
+if not modules then modules={} end modules ['util-tpl']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+utilities.templates=utilities.templates or {}
+local templates=utilities.templates
+local trace_template=false trackers.register("templates.trace",function(v) trace_template=v end)
+local report_template=logs.reporter("template")
+local tostring=tostring
+local format,sub=string.format,string.sub
+local P,C,Cs,Carg,lpegmatch=lpeg.P,lpeg.C,lpeg.Cs,lpeg.Carg,lpeg.match
+local replacer
+local function replacekey(k,t,how,recursive)
+ local v=t[k]
+ if not v then
+ if trace_template then
+ report_template("unknown key %a",k)
end
-end
-
-function file.checksum(name)
- if md5 then
- local data = io.loaddata(name)
- if data then
- return md5.HEX(data)
- end
+ return ""
+ else
+ v=tostring(v)
+ if trace_template then
+ report_template("setting key %a to value %a",k,v)
end
- return nil
-end
-
-function file.loadchecksum(name)
- if md5 then
- local data = io.loaddata(name .. ".md5")
- return data and (gsub(data,"%s",""))
+ if recursive then
+ return lpegmatch(replacer,v,1,t,how,recursive)
+ else
+ return v
end
- return nil
+ end
end
-
-function file.savechecksum(name, checksum)
- if not checksum then checksum = file.checksum(name) end
- if checksum then
- io.savedata(name .. ".md5",checksum)
- return checksum
- end
- return nil
+local sqlescape=lpeg.replacer {
+ { "'","''" },
+ { "\\","\\\\" },
+ { "\r\n","\\n" },
+ { "\r","\\n" },
+}
+local sqlquotedescape=lpeg.Cs(lpeg.Cc("'")*sqlescape*lpeg.Cc("'"))
+local escapers={
+ lua=function(s)
+ return sub(format("%q",s),2,-2)
+ end,
+ sql=function(s)
+ return lpegmatch(sqlescape,s)
+ end,
+}
+local quotedescapers={
+ lua=function(s)
+ return format("%q",s)
+ end,
+ sql=function(s)
+ return lpegmatch(sqlquotedescape,s)
+ end,
+}
+lpeg.patterns.sqlescape=sqlescape
+lpeg.patterns.sqlescape=sqlquotedescape
+local luaescaper=escapers.lua
+local quotedluaescaper=quotedescapers.lua
+local function replacekeyunquoted(s,t,how,recurse)
+ local escaper=how and escapers[how] or luaescaper
+ return escaper(replacekey(s,t,how,recurse))
+end
+local function replacekeyquoted(s,t,how,recurse)
+ local escaper=how and quotedescapers[how] or quotedluaescaper
+ return escaper(replacekey(s,t,how,recurse))
+end
+local single=P("%")
+local double=P("%%")
+local lquoted=P("%[")
+local rquoted=P("]%")
+local lquotedq=P("%(")
+local rquotedq=P(")%")
+local escape=double/'%%'
+local nosingle=single/''
+local nodouble=double/''
+local nolquoted=lquoted/''
+local norquoted=rquoted/''
+local nolquotedq=lquotedq/''
+local norquotedq=rquotedq/''
+local key=nosingle*((C((1-nosingle )^1)*Carg(1)*Carg(2)*Carg(3))/replacekey )*nosingle
+local quoted=nolquotedq*((C((1-norquotedq)^1)*Carg(1)*Carg(2)*Carg(3))/replacekeyquoted )*norquotedq
+local unquoted=nolquoted*((C((1-norquoted )^1)*Carg(1)*Carg(2)*Carg(3))/replacekeyunquoted)*norquoted
+local any=P(1)
+ replacer=Cs((unquoted+quoted+escape+key+any)^0)
+local function replace(str,mapping,how,recurse)
+ if mapping and str then
+ return lpegmatch(replacer,str,1,mapping,how or "lua",recurse or false) or str
+ else
+ return str
+ end
+end
+templates.replace=replace
+function templates.load(filename,mapping,how,recurse)
+ local data=io.loaddata(filename) or ""
+ if mapping and next(mapping) then
+ return replace(data,mapping,how,recurse)
+ else
+ return data
+ end
+end
+function templates.resolve(t,mapping,how,recurse)
+ if not mapping then
+ mapping=t
+ end
+ for k,v in next,t do
+ t[k]=replace(v,mapping,how,recurse)
+ end
+ return t
end
@@ -3125,1225 +7681,1316 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-url'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local char, gmatch, gsub, format, byte, find = string.char, string.gmatch, string.gsub, string.format, string.byte, string.find
-local concat = table.concat
-local tonumber, type = tonumber, type
-local P, C, R, S, Cs, Cc, Ct = lpeg.P, lpeg.C, lpeg.R, lpeg.S, lpeg.Cs, lpeg.Cc, lpeg.Ct
-local lpegmatch, lpegpatterns, replacer = lpeg.match, lpeg.patterns, lpeg.replacer
+package.loaded["util-env"] = package.loaded["util-env"] or true
--- from wikipedia:
---
--- foo://username:password@example.com:8042/over/there/index.dtb?type=animal;name=narwhal#nose
--- \_/ \_______________/ \_________/ \__/ \___/ \_/ \______________________/ \__/
--- | | | | | | | |
--- | userinfo hostname port | | query fragment
--- | \________________________________/\_____________|____|/
--- scheme | | | |
--- | authority path | |
--- | | |
--- | path interpretable as filename
--- | ___________|____________ |
--- / \ / \ |
--- urn:example:animal:ferret:nose interpretable as extension
-
-url = url or { }
-local url = url
-
-local tochar = function(s) return char(tonumber(s,16)) end
-
-local colon = P(":")
-local qmark = P("?")
-local hash = P("#")
-local slash = P("/")
-local percent = P("%")
-local endofstring = P(-1)
-
-local hexdigit = R("09","AF","af")
-local plus = P("+")
-local nothing = Cc("")
-local escaped = (plus / " ") + (percent * C(hexdigit * hexdigit) / tochar)
-
--- we assume schemes with more than 1 character (in order to avoid problems with windows disks)
--- we also assume that when we have a scheme, we also have an authority
-
-local schemestr = Cs((escaped+(1-colon-slash-qmark-hash))^2)
-local authoritystr = Cs((escaped+(1- slash-qmark-hash))^0)
-local pathstr = Cs((escaped+(1- qmark-hash))^0)
-local querystr = Cs((escaped+(1- hash))^0)
-local fragmentstr = Cs((escaped+(1- endofstring))^0)
-
-local scheme = schemestr * colon + nothing
-local authority = slash * slash * authoritystr + nothing
-local path = slash * pathstr + nothing
-local query = qmark * querystr + nothing
-local fragment = hash * fragmentstr + nothing
-
-local validurl = scheme * authority * path * query * fragment
-local parser = Ct(validurl)
-
-lpegpatterns.url = validurl
-lpegpatterns.urlsplitter = parser
-
-local escapes = { } ; for i=0,255 do escapes[i] = format("%%%02X",i) end
-
-local escaper = Cs((R("09","AZ","az") + S("-./_") + P(1) / escapes)^0)
-
-lpegpatterns.urlescaper = escaper
-
--- todo: reconsider Ct as we can as well have five return values (saves a table)
--- so we can have two parsers, one with and one without
+-- original size: 7702, stripped down to: 4701
-local function split(str)
- return (type(str) == "string" and lpegmatch(parser,str)) or str
+if not modules then modules={} end modules ['util-env']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local allocate,mark=utilities.storage.allocate,utilities.storage.mark
+local format,sub,match,gsub,find=string.format,string.sub,string.match,string.gsub,string.find
+local unquoted,quoted=string.unquoted,string.quoted
+local concat,insert,remove=table.concat,table.insert,table.remove
+environment=environment or {}
+local environment=environment
+os.setlocale(nil,nil)
+function os.setlocale()
end
-
-local isscheme = schemestr * colon * slash * slash -- this test also assumes authority
-
-local function hasscheme(str)
- local scheme = lpegmatch(isscheme,str) -- at least one character
- return scheme ~= "" and scheme or false
-end
-
-
--- todo: cache them
-
-local rootletter = R("az","AZ")
- + S("_-+")
-local separator = P("://")
-local qualified = P(".")^0 * P("/")
- + rootletter * P(":")
- + rootletter^1 * separator
- + rootletter^1 * P("/")
-local rootbased = P("/")
- + rootletter * P(":")
-
-local barswapper = replacer("|",":")
-local backslashswapper = replacer("\\","/")
-
-local function hashed(str) -- not yet ok (/test?test)
- local s = split(str)
- local somescheme = s[1] ~= ""
- local somequery = s[4] ~= ""
- if not somescheme and not somequery then
- s = {
- scheme = "file",
- authority = "",
- path = str,
- query = "",
- fragment = "",
- original = str,
- noscheme = true,
- filename = str,
- }
- else -- not always a filename but handy anyway
- local authority, path, filename = s[2], s[3]
- if authority == "" then
- filename = path
+local validengines=allocate {
+ ["luatex"]=true,
+ ["luajittex"]=true,
+}
+local basicengines=allocate {
+ ["luatex"]="luatex",
+ ["texlua"]="luatex",
+ ["texluac"]="luatex",
+ ["luajittex"]="luajittex",
+ ["texluajit"]="luajittex",
+}
+local luaengines=allocate {
+ ["lua"]=true,
+ ["luajit"]=true,
+}
+environment.validengines=validengines
+environment.basicengines=basicengines
+if not arg then
+elseif luaengines[file.removesuffix(arg[-1])] then
+elseif validengines[file.removesuffix(arg[0])] then
+ if arg[1]=="--luaonly" then
+ arg[-1]=arg[0]
+ arg[ 0]=arg[2]
+ for k=3,#arg do
+ arg[k-2]=arg[k]
+ end
+ remove(arg)
+ remove(arg)
+ else
+ end
+ local originalzero=file.basename(arg[0])
+ local specialmapping={ luatools=="base" }
+ if originalzero~="mtxrun" and originalzero~="mtxrun.lua" then
+ arg[0]=specialmapping[originalzero] or originalzero
+ insert(arg,0,"--script")
+ insert(arg,0,"mtxrun")
+ end
+end
+environment.arguments=allocate()
+environment.files=allocate()
+environment.sortedflags=nil
+function environment.initializearguments(arg)
+ local arguments,files={},{}
+ environment.arguments,environment.files,environment.sortedflags=arguments,files,nil
+ for index=1,#arg do
+ local argument=arg[index]
+ if index>0 then
+ local flag,value=match(argument,"^%-+(.-)=(.-)$")
+ if flag then
+ flag=gsub(flag,"^c:","")
+ arguments[flag]=unquoted(value or "")
+ else
+ flag=match(argument,"^%-+(.+)")
+ if flag then
+ flag=gsub(flag,"^c:","")
+ arguments[flag]=true
else
- filename = authority .. "/" .. path
+ files[#files+1]=argument
end
- s = {
- scheme = s[1],
- authority = authority,
- path = path,
- query = s[4],
- fragment = s[5],
- original = str,
- noscheme = false,
- filename = filename,
- }
+ end
end
- return s
+ end
+ environment.ownname=file.reslash(environment.ownname or arg[0] or 'unknown.lua')
end
-
--- Here we assume:
---
--- files: /// = relative
--- files: //// = absolute (!)
-
-
-
-url.split = split
-url.hasscheme = hasscheme
-url.hashed = hashed
-
-function url.addscheme(str,scheme) -- no authority
- if hasscheme(str) then
- return str
- elseif not scheme then
- return "file:///" .. str
+function environment.setargument(name,value)
+ environment.arguments[name]=value
+end
+function environment.getargument(name,partial)
+ local arguments,sortedflags=environment.arguments,environment.sortedflags
+ if arguments[name] then
+ return arguments[name]
+ elseif partial then
+ if not sortedflags then
+ sortedflags=allocate(table.sortedkeys(arguments))
+ for k=1,#sortedflags do
+ sortedflags[k]="^"..sortedflags[k]
+ end
+ environment.sortedflags=sortedflags
+ end
+ for k=1,#sortedflags do
+ local v=sortedflags[k]
+ if find(name,v) then
+ return arguments[sub(v,2,#v)]
+ end
+ end
+ end
+ return nil
+end
+environment.argument=environment.getargument
+function environment.splitarguments(separator)
+ local done,before,after=false,{},{}
+ local originalarguments=environment.originalarguments
+ for k=1,#originalarguments do
+ local v=originalarguments[k]
+ if not done and v==separator then
+ done=true
+ elseif done then
+ after[#after+1]=v
else
- return scheme .. ":///" .. str
- end
-end
-
-function url.construct(hash) -- dodo: we need to escape !
- local fullurl, f = { }, 0
- local scheme, authority, path, query, fragment = hash.scheme, hash.authority, hash.path, hash.query, hash.fragment
- if scheme and scheme ~= "" then
- f = f + 1 ; fullurl[f] = scheme .. "://"
- end
- if authority and authority ~= "" then
- f = f + 1 ; fullurl[f] = authority
- end
- if path and path ~= "" then
- f = f + 1 ; fullurl[f] = "/" .. path
- end
- if query and query ~= "" then
- f = f + 1 ; fullurl[f] = "?".. query
+ before[#before+1]=v
end
- if fragment and fragment ~= "" then
- f = f + 1 ; fullurl[f] = "#".. fragment
- end
- return lpegmatch(escaper,concat(fullurl))
+ end
+ return before,after
end
-
-function url.filename(filename)
- local t = hashed(filename)
- return (t.scheme == "file" and (gsub(t.path,"^/([a-zA-Z])([:|])/)","%1:"))) or filename
+function environment.reconstructcommandline(arg,noquote)
+ arg=arg or environment.originalarguments
+ if noquote and #arg==1 then
+ local a=arg[1]
+ a=resolvers.resolve(a)
+ a=unquoted(a)
+ return a
+ elseif #arg>0 then
+ local result={}
+ for i=1,#arg do
+ local a=arg[i]
+ a=resolvers.resolve(a)
+ a=unquoted(a)
+ a=gsub(a,'"','\\"')
+ if find(a," ") then
+ result[#result+1]=quoted(a)
+ else
+ result[#result+1]=a
+ end
+ end
+ return concat(result," ")
+ else
+ return ""
+ end
end
-
-function url.query(str)
- if type(str) == "string" then
- local t = { }
- for k, v in gmatch(str,"([^&=]*)=([^&=]*)") do
- t[k] = v
- end
- return t
+if arg then
+ local newarg,instring={},false
+ for index=1,#arg do
+ local argument=arg[index]
+ if find(argument,"^\"") then
+ newarg[#newarg+1]=gsub(argument,"^\"","")
+ if not find(argument,"\"$") then
+ instring=true
+ end
+ elseif find(argument,"\"$") then
+ newarg[#newarg]=newarg[#newarg].." "..gsub(argument,"\"$","")
+ instring=false
+ elseif instring then
+ newarg[#newarg]=newarg[#newarg].." "..argument
else
- return str
+ newarg[#newarg+1]=argument
end
+ end
+ for i=1,-5,-1 do
+ newarg[i]=arg[i]
+ end
+ environment.initializearguments(newarg)
+ environment.originalarguments=mark(newarg)
+ environment.rawarguments=mark(arg)
+ arg={}
end
-
-
-
-
-
-
-
-
end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-dir'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- dir.expandname will be merged with cleanpath and collapsepath
-
-local type = type
-local find, gmatch, match, gsub = string.find, string.gmatch, string.match, string.gsub
-local concat, insert, remove = table.concat, table.insert, table.remove
-local lpegmatch = lpeg.match
-
-local P, S, R, C, Cc, Cs, Ct, Cv, V = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.Cc, lpeg.Cs, lpeg.Ct, lpeg.Cv, lpeg.V
+package.loaded["luat-env"] = package.loaded["luat-env"] or true
-dir = dir or { }
-local dir = dir
-local lfs = lfs
+-- original size: 5874, stripped down to: 4184
-local attributes = lfs.attributes
-local walkdir = lfs.dir
-local isdir = lfs.isdir
-local isfile = lfs.isfile
-local currentdir = lfs.currentdir
-
--- handy
-
-function dir.current()
- return (gsub(currentdir(),"\\","/"))
-end
-
--- optimizing for no find (*) does not save time
-
-
-local lfsisdir = isdir
-
-local function isdir(path)
- path = gsub(path,"[/\\]+$","")
- return lfsisdir(path)
+ if not modules then modules={} end modules ['luat-env']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local rawset,rawget,loadfile,assert=rawset,rawget,loadfile,assert
+local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end)
+local report_lua=logs.reporter("resolvers","lua")
+local luautilities=utilities.lua
+local luasuffixes=luautilities.suffixes
+environment=environment or {}
+local environment=environment
+local mt={
+ __index=function(_,k)
+ if k=="version" then
+ local version=tex.toks and tex.toks.contextversiontoks
+ if version and version~="" then
+ rawset(environment,"version",version)
+ return version
+ else
+ return "unknown"
+ end
+ elseif k=="kind" then
+ local kind=tex.toks and tex.toks.contextkindtoks
+ if kind and kind~="" then
+ rawset(environment,"kind",kind)
+ return kind
+ else
+ return "unknown"
+ end
+ elseif k=="jobname" or k=="formatname" then
+ local name=tex and tex[k]
+ if name or name=="" then
+ rawset(environment,k,name)
+ return name
+ else
+ return "unknown"
+ end
+ elseif k=="outputfilename" then
+ local name=environment.jobname
+ rawset(environment,k,name)
+ return name
+ end
+ end
+}
+setmetatable(environment,mt)
+function environment.texfile(filename)
+ return resolvers.findfile(filename,'tex')
+end
+function environment.luafile(filename)
+ local resolved=resolvers.findfile(filename,'tex') or ""
+ if resolved~="" then
+ return resolved
+ end
+ resolved=resolvers.findfile(filename,'texmfscripts') or ""
+ if resolved~="" then
+ return resolved
+ end
+ return resolvers.findfile(filename,'luatexlibs') or ""
+end
+local stripindeed=false directives.register("system.compile.strip",function(v) stripindeed=v end)
+local function strippable(filename)
+ if stripindeed then
+ local modu=modules[file.nameonly(filename)]
+ return modu and modu.dataonly
+ else
+ return false
+ end
end
-
-lfs.isdir = isdir
-
-local function globpattern(path,patt,recurse,action)
- if path == "/" then
- path = path .. "."
- elseif not find(path,"/$") then
- path = path .. '/'
- end
- if isdir(path) then -- lfs.isdir does not like trailing /
- for name in walkdir(path) do -- lfs.dir accepts trailing /
- local full = path .. name
- local mode = attributes(full,'mode')
- if mode == 'file' then
- if find(full,patt) then
- action(full)
- end
- elseif recurse and (mode == "directory") and (name ~= '.') and (name ~= "..") then
- globpattern(full,patt,recurse,action)
- end
- end
+function environment.luafilechunk(filename,silent)
+ filename=file.replacesuffix(filename,"lua")
+ local fullname=environment.luafile(filename)
+ if fullname and fullname~="" then
+ local data=luautilities.loadedluacode(fullname,strippable,filename)
+ if trace_locating then
+ report_lua("loading file %a %s",fullname,not data and "failed" or "succeeded")
+ elseif not silent then
+ texio.write("<",data and "+ " or "- ",fullname,">")
end
-end
-
-dir.globpattern = globpattern
-
-local function collectpattern(path,patt,recurse,result)
- local ok, scanner
- result = result or { }
- if path == "/" then
- ok, scanner, first = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe
- else
- ok, scanner, first = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
- end
- if ok and type(scanner) == "function" then
- if not find(path,"/$") then path = path .. '/' end
- for name in scanner, first do
- local full = path .. name
- local attr = attributes(full)
- local mode = attr.mode
- if mode == 'file' then
- if find(full,patt) then
- result[name] = attr
- end
- elseif recurse and (mode == "directory") and (name ~= '.') and (name ~= "..") then
- attr.list = collectpattern(full,patt,recurse)
- result[name] = attr
- end
- end
+ return data
+ else
+ if trace_locating then
+ report_lua("unknown file %a",filename)
end
- return result
-end
-
-dir.collectpattern = collectpattern
-
-local pattern = Ct {
- [1] = (C(P(".") + P("/")^1) + C(R("az","AZ") * P(":") * P("/")^0) + Cc("./")) * V(2) * V(3),
- [2] = C(((1-S("*?/"))^0 * P("/"))^0),
- [3] = C(P(1)^0)
-}
-
-local filter = Cs ( (
- P("**") / ".*" +
- P("*") / "[^/]*" +
- P("?") / "[^/]" +
- P(".") / "%%." +
- P("+") / "%%+" +
- P("-") / "%%-" +
- P(1)
-)^0 )
-
-local function glob(str,t)
- if type(t) == "function" then
- if type(str) == "table" then
- for s=1,#str do
- glob(str[s],t)
- end
- elseif isfile(str) then
- t(str)
- else
- local split = lpegmatch(pattern,str) -- we could use the file splitter
- if split then
- local root, path, base = split[1], split[2], split[3]
- local recurse = find(base,"%*%*")
- local start = root .. path
- local result = lpegmatch(filter,start .. base)
- globpattern(start,result,recurse,t)
- end
+ return nil
+ end
+end
+function environment.loadluafile(filename,version)
+ local lucname,luaname,chunk
+ local basename=file.removesuffix(filename)
+ if basename==filename then
+ luaname=file.addsuffix(basename,luasuffixes.lua)
+ lucname=file.addsuffix(basename,luasuffixes.luc)
+ else
+ luaname=basename
+ lucname=nil
+ end
+ local fullname=(lucname and environment.luafile(lucname)) or ""
+ if fullname~="" then
+ if trace_locating then
+ report_lua("loading %a",fullname)
+ end
+ chunk=loadfile(fullname)
+ end
+ if chunk then
+ assert(chunk)()
+ if version then
+ local v=version
+ if modules and modules[filename] then
+ v=modules[filename].version
+ elseif versions and versions[filename] then
+ v=versions[filename]
+ end
+ if v==version then
+ return true
+ else
+ if trace_locating then
+ report_lua("version mismatch for %a, lua version %a, luc version %a",filename,v,version)
end
+ environment.loadluafile(filename)
+ end
else
- if type(str) == "table" then
- local t = t or { }
- for s=1,#str do
- glob(str[s],t)
- end
- return t
- elseif isfile(str) then
- if t then
- t[#t+1] = str
- return t
- else
- return { str }
- end
- else
- local split = lpegmatch(pattern,str) -- we could use the file splitter
- if split then
- local t = t or { }
- local action = action or function(name) t[#t+1] = name end
- local root, path, base = split[1], split[2], split[3]
- local recurse = find(base,"%*%*")
- local start = root .. path
- local result = lpegmatch(filter,start .. base)
- globpattern(start,result,recurse,action)
- return t
- else
- return { }
- end
- end
+ return true
end
-end
-
-dir.glob = glob
-
-
-local function globfiles(path,recurse,func,files) -- func == pattern or function
- if type(func) == "string" then
- local s = func
- func = function(name) return find(name,s) end
+ end
+ fullname=(luaname and environment.luafile(luaname)) or ""
+ if fullname~="" then
+ if trace_locating then
+ report_lua("loading %a",fullname)
end
- files = files or { }
- local noffiles = #files
- for name in walkdir(path) do
- if find(name,"^%.") then
- --- skip
- else
- local mode = attributes(name,'mode')
- if mode == "directory" then
- if recurse then
- globfiles(path .. "/" .. name,recurse,func,files)
- end
- elseif mode == "file" then
- if not func or func(name) then
- noffiles = noffiles + 1
- files[noffiles] = path .. "/" .. name
- end
- end
- end
+ chunk=loadfile(fullname)
+ if not chunk then
+ if trace_locating then
+ report_lua("unknown file %a",filename)
+ end
+ else
+ assert(chunk)()
+ return true
end
- return files
+ end
+ return false
end
-dir.globfiles = globfiles
-
--- t = dir.glob("c:/data/develop/context/sources/**/????-*.tex")
--- t = dir.glob("c:/data/develop/tex/texmf/**/*.tex")
--- t = dir.glob("c:/data/develop/context/texmf/**/*.tex")
--- t = dir.glob("f:/minimal/tex/**/*")
--- print(dir.ls("f:/minimal/tex/**/*"))
--- print(dir.ls("*.tex"))
-
-function dir.ls(pattern)
- return concat(glob(pattern),"\n")
-end
+end -- of closure
-local make_indeed = true -- false
+do -- create closure to overcome 200 locals limit
-local onwindows = os.type == "windows" or find(os.getenv("PATH"),";")
+package.loaded["lxml-tab"] = package.loaded["lxml-tab"] or true
-if onwindows then
+-- original size: 42495, stripped down to: 26647
- function dir.mkdirs(...)
- local str, pth, t = "", "", { ... }
- for i=1,#t do
- local s = t[i]
- if s ~= "" then
- if str ~= "" then
- str = str .. "/" .. s
- else
- str = s
- end
- end
- end
- local first, middle, last
- local drive = false
- first, middle, last = match(str,"^(//)(//*)(.*)$")
- if first then
- -- empty network path == local path
- else
- first, last = match(str,"^(//)/*(.-)$")
- if first then
- middle, last = match(str,"([^/]+)/+(.-)$")
- if middle then
- pth = "//" .. middle
- else
- pth = "//" .. last
- last = ""
- end
- else
- first, middle, last = match(str,"^([a-zA-Z]:)(/*)(.-)$")
- if first then
- pth, drive = first .. middle, true
- else
- middle, last = match(str,"^(/*)(.-)$")
- if not middle then
- last = str
- end
- end
- end
- end
- for s in gmatch(last,"[^/]+") do
- if pth == "" then
- pth = s
- elseif drive then
- pth, drive = pth .. s, false
- else
- pth = pth .. "/" .. s
- end
- if make_indeed and not isdir(pth) then
- lfs.mkdir(pth)
- end
- end
- return pth, (isdir(pth) == true)
- end
-
-
-else
-
- function dir.mkdirs(...)
- local str, pth, t = "", "", { ... }
- for i=1,#t do
- local s = t[i]
- if s and s ~= "" then -- we catch nil and false
- if str ~= "" then
- str = str .. "/" .. s
- else
- str = s
- end
- end
- end
- str = gsub(str,"/+","/")
- if find(str,"^/") then
- pth = "/"
- for s in gmatch(str,"[^/]+") do
- local first = (pth == "/")
- if first then
- pth = pth .. s
- else
- pth = pth .. "/" .. s
- end
- if make_indeed and not first and not isdir(pth) then
- lfs.mkdir(pth)
- end
- end
- else
- pth = "."
- for s in gmatch(str,"[^/]+") do
- pth = pth .. "/" .. s
- if make_indeed and not isdir(pth) then
- lfs.mkdir(pth)
- end
- end
- end
- return pth, (isdir(pth) == true)
- end
-
-
+if not modules then modules={} end modules ['lxml-tab']={
+ version=1.001,
+ comment="this module is the basis for the lxml-* ones",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local trace_entities=false trackers.register("xml.entities",function(v) trace_entities=v end)
+local report_xml=logs and logs.reporter("xml","core") or function(...) print(string.format(...)) end
+xml=xml or {}
+local xml=xml
+local concat,remove,insert=table.concat,table.remove,table.insert
+local type,next,setmetatable,getmetatable,tonumber=type,next,setmetatable,getmetatable,tonumber
+local lower,find,match,gsub=string.lower,string.find,string.match,string.gsub
+local utfchar=utf.char
+local lpegmatch=lpeg.match
+local P,S,R,C,V,C,Cs=lpeg.P,lpeg.S,lpeg.R,lpeg.C,lpeg.V,lpeg.C,lpeg.Cs
+local formatters=string.formatters
+xml.xmlns=xml.xmlns or {}
+local check=P(false)
+local parse=check
+function xml.registerns(namespace,pattern)
+ check=check+C(P(lower(pattern)))/namespace
+ parse=P { P(check)+1*V(1) }
end
-
-dir.makedirs = dir.mkdirs
-
--- we can only define it here as it uses dir.current
-
-if onwindows then
-
- function dir.expandname(str) -- will be merged with cleanpath and collapsepath
- local first, nothing, last = match(str,"^(//)(//*)(.*)$")
- if first then
- first = dir.current() .. "/"
- end
- if not first then
- first, last = match(str,"^(//)/*(.*)$")
- end
- if not first then
- first, last = match(str,"^([a-zA-Z]:)(.*)$")
- if first and not find(last,"^/") then
- local d = currentdir()
- if lfs.chdir(first) then
- first = dir.current()
- end
- lfs.chdir(d)
- end
- end
- if not first then
- first, last = dir.current(), str
- end
- last = gsub(last,"//","/")
- last = gsub(last,"/%./","/")
- last = gsub(last,"^/*","")
- first = gsub(first,"/*$","")
- if last == "" or last == "." then
- return first
- else
- return first .. "/" .. last
- end
- end
-
-else
-
- function dir.expandname(str) -- will be merged with cleanpath and collapsepath
- if not find(str,"^/") then
- str = currentdir() .. "/" .. str
- end
- str = gsub(str,"//","/")
- str = gsub(str,"/%./","/")
- str = gsub(str,"(.)/%.$","%1")
- return str
- end
-
+function xml.checkns(namespace,url)
+ local ns=lpegmatch(parse,lower(url))
+ if ns and namespace~=ns then
+ xml.xmlns[namespace]=ns
+ end
end
-
-file.expandname = dir.expandname -- for convenience
-
-local stack = { }
-
-function dir.push(newdir)
- insert(stack,lfs.currentdir())
+function xml.resolvens(url)
+ return lpegmatch(parse,lower(url)) or ""
+end
+local nsremap,resolvens=xml.xmlns,xml.resolvens
+local stack={}
+local top={}
+local dt={}
+local at={}
+local xmlns={}
+local errorstr=nil
+local entities={}
+local strip=false
+local cleanup=false
+local utfize=false
+local resolve_predefined=false
+local unify_predefined=false
+local dcache={}
+local hcache={}
+local acache={}
+local mt={}
+local function initialize_mt(root)
+ mt={ __index=root }
end
-
-function dir.pop()
- local d = remove(stack)
- if d then
- lfs.chdir(d)
- end
- return d
+function xml.setproperty(root,k,v)
+ getmetatable(root).__index[k]=v
end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['l-boolean'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
+function xml.checkerror(top,toclose)
+ return ""
+end
+local function add_attribute(namespace,tag,value)
+ if cleanup and #value>0 then
+ value=cleanup(value)
+ end
+ if tag=="xmlns" then
+ xmlns[#xmlns+1]=resolvens(value)
+ at[tag]=value
+ elseif namespace=="" then
+ at[tag]=value
+ elseif namespace=="xmlns" then
+ xml.checkns(tag,value)
+ at["xmlns:"..tag]=value
+ else
+ at[namespace..":"..tag]=value
+ end
+end
+local function add_empty(spacing,namespace,tag)
+ if #spacing>0 then
+ dt[#dt+1]=spacing
+ end
+ local resolved=namespace=="" and xmlns[#xmlns] or nsremap[namespace] or namespace
+ top=stack[#stack]
+ dt=top.dt
+ local t={ ns=namespace or "",rn=resolved,tg=tag,at=at,dt={},__p__=top }
+ dt[#dt+1]=t
+ setmetatable(t,mt)
+ if at.xmlns then
+ remove(xmlns)
+ end
+ at={}
+end
+local function add_begin(spacing,namespace,tag)
+ if #spacing>0 then
+ dt[#dt+1]=spacing
+ end
+ local resolved=namespace=="" and xmlns[#xmlns] or nsremap[namespace] or namespace
+ top={ ns=namespace or "",rn=resolved,tg=tag,at=at,dt={},__p__=stack[#stack] }
+ setmetatable(top,mt)
+ dt=top.dt
+ stack[#stack+1]=top
+ at={}
+end
+local function add_end(spacing,namespace,tag)
+ if #spacing>0 then
+ dt[#dt+1]=spacing
+ end
+ local toclose=remove(stack)
+ top=stack[#stack]
+ if #stack<1 then
+ errorstr=formatters["unable to close %s %s"](tag,xml.checkerror(top,toclose) or "")
+ elseif toclose.tg~=tag then
+ errorstr=formatters["unable to close %s with %s %s"](toclose.tg,tag,xml.checkerror(top,toclose) or "")
+ end
+ dt=top.dt
+ dt[#dt+1]=toclose
+ if toclose.at.xmlns then
+ remove(xmlns)
+ end
+end
+local function add_text(text)
+ if cleanup and #text>0 then
+ dt[#dt+1]=cleanup(text)
+ else
+ dt[#dt+1]=text
+ end
+end
+local function add_special(what,spacing,text)
+ if #spacing>0 then
+ dt[#dt+1]=spacing
+ end
+ if strip and (what=="@cm@" or what=="@dt@") then
+ else
+ dt[#dt+1]={ special=true,ns="",tg=what,dt={ text } }
+ end
+end
+local function set_message(txt)
+ errorstr="garbage at the end of the file: "..gsub(txt,"([ \n\r\t]*)","")
+end
+local reported_attribute_errors={}
+local function attribute_value_error(str)
+ if not reported_attribute_errors[str] then
+ report_xml("invalid attribute value %a",str)
+ reported_attribute_errors[str]=true
+ at._error_=str
+ end
+ return str
+end
+local function attribute_specification_error(str)
+ if not reported_attribute_errors[str] then
+ report_xml("invalid attribute specification %a",str)
+ reported_attribute_errors[str]=true
+ at._error_=str
+ end
+ return str
+end
+xml.placeholders={
+ unknown_dec_entity=function(str) return str=="" and "&error;" or formatters["&%s;"](str) end,
+ unknown_hex_entity=function(str) return formatters["%s;"](str) end,
+ unknown_any_entity=function(str) return formatters["%s;"](str) end,
}
-
-local type, tonumber = type, tonumber
-
-boolean = boolean or { }
-local boolean = boolean
-
-function boolean.tonumber(b)
- if b then return 1 else return 0 end -- test and return or return
+local placeholders=xml.placeholders
+local function fromhex(s)
+ local n=tonumber(s,16)
+ if n then
+ return utfchar(n)
+ else
+ return formatters["h:%s"](s),true
+ end
end
-
-function toboolean(str,tolerant)
- if tolerant then
- local tstr = type(str)
- if tstr == "string" then
- return str == "true" or str == "yes" or str == "on" or str == "1" or str == "t"
- elseif tstr == "number" then
- return tonumber(str) ~= 0
- elseif tstr == "nil" then
- return false
- else
- return str
- end
- elseif str == "true" then
- return true
- elseif str == "false" then
- return false
+local function fromdec(s)
+ local n=tonumber(s)
+ if n then
+ return utfchar(n)
+ else
+ return formatters["d:%s"](s),true
+ end
+end
+local rest=(1-P(";"))^0
+local many=P(1)^0
+local parsedentity=P("&")*(P("#x")*(rest/fromhex)+P("#")*(rest/fromdec))*P(";")*P(-1)+(P("#x")*(many/fromhex)+P("#")*(many/fromdec))
+local predefined_unified={
+ [38]="&",
+ [42]=""",
+ [47]="'",
+ [74]="<",
+ [76]=">",
+}
+local predefined_simplified={
+ [38]="&",amp="&",
+ [42]='"',quot='"',
+ [47]="'",apos="'",
+ [74]="<",lt="<",
+ [76]=">",gt=">",
+}
+local nofprivates=0xF0000
+local privates_u={
+ [ [[&]] ]="&",
+ [ [["]] ]=""",
+ [ [[']] ]="'",
+ [ [[<]] ]="<",
+ [ [[>]] ]=">",
+}
+local privates_p={}
+local privates_n={
+}
+local escaped=utf.remapper(privates_u)
+local function unescaped(s)
+ local p=privates_n[s]
+ if not p then
+ nofprivates=nofprivates+1
+ p=utfchar(nofprivates)
+ privates_n[s]=p
+ s="&"..s..";"
+ privates_u[p]=s
+ privates_p[p]=s
+ end
+ return p
+end
+local unprivatized=utf.remapper(privates_p)
+xml.privatetoken=unescaped
+xml.unprivatized=unprivatized
+xml.privatecodes=privates_n
+local function handle_hex_entity(str)
+ local h=hcache[str]
+ if not h then
+ local n=tonumber(str,16)
+ h=unify_predefined and predefined_unified[n]
+ if h then
+ if trace_entities then
+ report_xml("utfize, converting hex entity %s; into %a",str,h)
+ end
+ elseif utfize then
+ h=(n and utfchar(n)) or xml.unknown_hex_entity(str) or ""
+ if not n then
+ report_xml("utfize, ignoring hex entity %s;",str)
+ elseif trace_entities then
+ report_xml("utfize, converting hex entity %s; into %a",str,h)
+ end
else
- return str
+ if trace_entities then
+ report_xml("found entity %s;",str)
+ end
+ h=""..str..";"
end
+ hcache[str]=h
+ end
+ return h
end
-
-string.toboolean = toboolean
-
-function string.is_boolean(str,default)
- if type(str) == "string" then
- if str == "true" or str == "yes" or str == "on" or str == "t" then
- return true
- elseif str == "false" or str == "no" or str == "off" or str == "f" then
- return false
- end
+local function handle_dec_entity(str)
+ local d=dcache[str]
+ if not d then
+ local n=tonumber(str)
+ d=unify_predefined and predefined_unified[n]
+ if d then
+ if trace_entities then
+ report_xml("utfize, converting dec entity %s; into %a",str,d)
+ end
+ elseif utfize then
+ d=(n and utfchar(n)) or placeholders.unknown_dec_entity(str) or ""
+ if not n then
+ report_xml("utfize, ignoring dec entity %s;",str)
+ elseif trace_entities then
+ report_xml("utfize, converting dec entity %s; into %a",str,d)
+ end
+ else
+ if trace_entities then
+ report_xml("found entity %s;",str)
+ end
+ d=""..str..";"
end
- return default
+ dcache[str]=d
+ end
+ return d
end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['l-unicode'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-if not unicode then
-
- unicode = { utf8 = { } }
-
- local floor, char = math.floor, string.char
-
- function unicode.utf8.utfchar(n)
- if n < 0x80 then
- return char(n)
- elseif n < 0x800 then
- return char(
- 0xC0 + floor(n/0x40),
- 0x80 + (n % 0x40)
- )
- elseif n < 0x10000 then
- return char(
- 0xE0 + floor(n/0x1000),
- 0x80 + (floor(n/0x40) % 0x40),
- 0x80 + (n % 0x40)
- )
- elseif n < 0x40000 then
- return char(
- 0xF0 + floor(n/0x40000),
- 0x80 + floor(n/0x1000),
- 0x80 + (floor(n/0x40) % 0x40),
- 0x80 + (n % 0x40)
- )
+xml.parsedentitylpeg=parsedentity
+local function handle_any_entity(str)
+ if resolve then
+ local a=acache[str]
+ if not a then
+ a=resolve_predefined and predefined_simplified[str]
+ if a then
+ if trace_entities then
+ report_xml("resolving entity &%s; to predefined %a",str,a)
+ end
+ else
+ if type(resolve)=="function" then
+ a=resolve(str) or entities[str]
else
- -- return char(
- -- 0xF1 + floor(n/0x1000000),
- -- 0x80 + floor(n/0x40000),
- -- 0x80 + floor(n/0x1000),
- -- 0x80 + (floor(n/0x40) % 0x40),
- -- 0x80 + (n % 0x40)
- -- )
- return "?"
+ a=entities[str]
end
- end
-
+ if a then
+ if type(a)=="function" then
+ if trace_entities then
+ report_xml("expanding entity &%s; to function call",str)
+ end
+ a=a(str) or ""
+ end
+ a=lpegmatch(parsedentity,a) or a
+ if trace_entities then
+ report_xml("resolving entity &%s; to internal %a",str,a)
+ end
+ else
+ local unknown_any_entity=placeholders.unknown_any_entity
+ if unknown_any_entity then
+ a=unknown_any_entity(str) or ""
+ end
+ if a then
+ if trace_entities then
+ report_xml("resolving entity &%s; to external %s",str,a)
+ end
+ else
+ if trace_entities then
+ report_xml("keeping entity &%s;",str)
+ end
+ if str=="" then
+ a="&error;"
+ else
+ a="&"..str..";"
+ end
+ end
+ end
+ end
+ acache[str]=a
+ elseif trace_entities then
+ if not acache[str] then
+ report_xml("converting entity &%s; to %a",str,a)
+ acache[str]=a
+ end
+ end
+ return a
+ else
+ local a=acache[str]
+ if not a then
+ a=resolve_predefined and predefined_simplified[str]
+ if a then
+ acache[str]=a
+ if trace_entities then
+ report_xml("entity &%s; becomes %a",str,a)
+ end
+ elseif str=="" then
+ if trace_entities then
+ report_xml("invalid entity &%s;",str)
+ end
+ a="&error;"
+ acache[str]=a
+ else
+ if trace_entities then
+ report_xml("entity &%s; is made private",str)
+ end
+ a=unescaped(str)
+ acache[str]=a
+ end
+ end
+ return a
+ end
end
-
-local unicode = unicode
-
-utf = utf or unicode.utf8
-
-local concat = table.concat
-local utfchar, utfbyte, utfgsub = utf.char, utf.byte, utf.gsub
-local char, byte, find, bytepairs, utfvalues, format = string.char, string.byte, string.find, string.bytepairs, string.utfvalues, string.format
-local type = type
-
-local utfsplitlines = string.utfsplitlines
-
--- 0 EF BB BF UTF-8
--- 1 FF FE UTF-16-little-endian
--- 2 FE FF UTF-16-big-endian
--- 3 FF FE 00 00 UTF-32-little-endian
--- 4 00 00 FE FF UTF-32-big-endian
-
-unicode.utfname = {
- [0] = 'utf-8',
- [1] = 'utf-16-le',
- [2] = 'utf-16-be',
- [3] = 'utf-32-le',
- [4] = 'utf-32-be'
+local function handle_end_entity(chr)
+ report_xml("error in entity, %a found instead of %a",chr,";")
+end
+local space=S(' \r\n\t')
+local open=P('<')
+local close=P('>')
+local squote=S("'")
+local dquote=S('"')
+local equal=P('=')
+local slash=P('/')
+local colon=P(':')
+local semicolon=P(';')
+local ampersand=P('&')
+local valid=R('az','AZ','09')+S('_-.')
+local name_yes=C(valid^1)*colon*C(valid^1)
+local name_nop=C(P(true))*C(valid^1)
+local name=name_yes+name_nop
+local utfbom=lpeg.patterns.utfbom
+local spacing=C(space^0)
+local anyentitycontent=(1-open-semicolon-space-close)^0
+local hexentitycontent=R("AF","af","09")^0
+local decentitycontent=R("09")^0
+local parsedentity=P("#")/""*(
+ P("x")/""*(hexentitycontent/handle_hex_entity)+(decentitycontent/handle_dec_entity)
+ )+(anyentitycontent/handle_any_entity)
+local entity=ampersand/""*parsedentity*((semicolon/"")+#(P(1)/handle_end_entity))
+local text_unparsed=C((1-open)^1)
+local text_parsed=Cs(((1-open-ampersand)^1+entity)^1)
+local somespace=space^1
+local optionalspace=space^0
+local value=(squote*Cs((entity+(1-squote))^0)*squote)+(dquote*Cs((entity+(1-dquote))^0)*dquote)
+local endofattributes=slash*close+close
+local whatever=space*name*optionalspace*equal
+local wrongvalue=Cs(P(entity+(1-space-endofattributes))^1)/attribute_value_error
+local attributevalue=value+wrongvalue
+local attribute=(somespace*name*optionalspace*equal*optionalspace*attributevalue)/add_attribute
+local attributes=(attribute+somespace^-1*(((1-endofattributes)^1)/attribute_specification_error))^0
+local parsedtext=text_parsed/add_text
+local unparsedtext=text_unparsed/add_text
+local balanced=P { "["*((1-S"[]")+V(1))^0*"]" }
+local emptyelement=(spacing*open*name*attributes*optionalspace*slash*close)/add_empty
+local beginelement=(spacing*open*name*attributes*optionalspace*close)/add_begin
+local endelement=(spacing*open*slash*name*optionalspace*close)/add_end
+local begincomment=open*P("!--")
+local endcomment=P("--")*close
+local begininstruction=open*P("?")
+local endinstruction=P("?")*close
+local begincdata=open*P("![CDATA[")
+local endcdata=P("]]")*close
+local someinstruction=C((1-endinstruction)^0)
+local somecomment=C((1-endcomment )^0)
+local somecdata=C((1-endcdata )^0)
+local function normalentity(k,v ) entities[k]=v end
+local function systementity(k,v,n) entities[k]=v end
+local function publicentity(k,v,n) entities[k]=v end
+local begindoctype=open*P("!DOCTYPE")
+local enddoctype=close
+local beginset=P("[")
+local endset=P("]")
+local doctypename=C((1-somespace-close)^0)
+local elementdoctype=optionalspace*P("=5.1 where %z is depricated
-
-function unicode.utftype(f)
- local str = f:read(4)
- if not str then
- f:seek('set')
- return 0
- -- elseif find(str,"^%z%z\254\255") then -- depricated
- -- elseif find(str,"^\000\000\254\255") then -- not permitted and bugged
- elseif find(str,"\000\000\254\255",1,true) then -- seems to work okay (TH)
- return 4
- -- elseif find(str,"^\255\254%z%z") then -- depricated
- -- elseif find(str,"^\255\254\000\000") then -- not permitted and bugged
- elseif find(str,"\255\254\000\000",1,true) then -- seems to work okay (TH)
- return 3
- elseif find(str,"^\254\255") then
- f:seek('set',2)
- return 2
- elseif find(str,"^\255\254") then
- f:seek('set',2)
- return 1
- elseif find(str,"^\239\187\191") then
- f:seek('set',3)
- return 0
+local grammar_unparsed_text=P { "preamble",
+ preamble=utfbom^0*instruction^0*(doctype+comment+instruction)^0*V("parent")*trailer,
+ parent=beginelement*V("children")^0*endelement,
+ children=unparsedtext+V("parent")+emptyelement+comment+cdata+instruction,
+}
+local function _xmlconvert_(data,settings)
+ settings=settings or {}
+ strip=settings.strip_cm_and_dt
+ utfize=settings.utfize_entities
+ resolve=settings.resolve_entities
+ resolve_predefined=settings.resolve_predefined_entities
+ unify_predefined=settings.unify_predefined_entities
+ cleanup=settings.text_cleanup
+ entities=settings.entities or {}
+ if utfize==nil then
+ settings.utfize_entities=true
+ utfize=true
+ end
+ if resolve_predefined==nil then
+ settings.resolve_predefined_entities=true
+ resolve_predefined=true
+ end
+ stack,top,at,xmlns,errorstr={},{},{},{},nil
+ acache,hcache,dcache={},{},{}
+ reported_attribute_errors={}
+ if settings.parent_root then
+ mt=getmetatable(settings.parent_root)
+ else
+ initialize_mt(top)
+ end
+ stack[#stack+1]=top
+ top.dt={}
+ dt=top.dt
+ if not data or data=="" then
+ errorstr="empty xml file"
+ elseif utfize or resolve then
+ if lpegmatch(grammar_parsed_text,data) then
+ errorstr=""
else
- f:seek('set')
- return 0
+ errorstr="invalid xml file - parsed text"
end
+ elseif type(data)=="string" then
+ if lpegmatch(grammar_unparsed_text,data) then
+ errorstr=""
+ else
+ errorstr="invalid xml file - unparsed text"
+ end
+ else
+ errorstr="invalid xml file - no text at all"
+ end
+ local result
+ if errorstr and errorstr~="" then
+ result={ dt={ { ns="",tg="error",dt={ errorstr },at={},er=true } } }
+ setmetatable(stack,mt)
+ local errorhandler=settings.error_handler
+ if errorhandler==false then
+ else
+ errorhandler=errorhandler or xml.errorhandler
+ if errorhandler then
+ local currentresource=settings.currentresource
+ if currentresource and currentresource~="" then
+ xml.errorhandler(formatters["load error in [%s]: %s"](currentresource,errorstr))
+ else
+ xml.errorhandler(formatters["load error: %s"](errorstr))
+ end
+ end
+ end
+ else
+ result=stack[1]
+ end
+ if not settings.no_root then
+ result={ special=true,ns="",tg='@rt@',dt=result.dt,at={},entities=entities,settings=settings }
+ setmetatable(result,mt)
+ local rdt=result.dt
+ for k=1,#rdt do
+ local v=rdt[k]
+ if type(v)=="table" and not v.special then
+ result.ri=k
+ v.__p__=result
+ break
+ end
+ end
+ end
+ if errorstr and errorstr~="" then
+ result.error=true
+ end
+ result.statistics={
+ entities={
+ decimals=dcache,
+ hexadecimals=hcache,
+ names=acache,
+ }
+ }
+ strip,utfize,resolve,resolve_predefined=nil,nil,nil,nil
+ unify_predefined,cleanup,entities=nil,nil,nil
+ stack,top,at,xmlns,errorstr=nil,nil,nil,nil,nil
+ acache,hcache,dcache=nil,nil,nil
+ reported_attribute_errors,mt,errorhandler=nil,nil,nil
+ return result
end
-
-
-
-local function utf16_to_utf8_be(t)
- if type(t) == "string" then
- t = utfsplitlines(str)
- end
- local result = { } -- we reuse result
- for i=1,#t do
- local r, more = 0, 0
- for left, right in bytepairs(t[i]) do
- if right then
- local now = 256*left + right
- if more > 0 then
- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
- more = 0
- r = r + 1
- result[r] = utfchar(now)
- elseif now >= 0xD800 and now <= 0xDBFF then
- more = now
- else
- r = r + 1
- result[r] = utfchar(now)
- end
- end
- end
- t[i] = concat(result,"",1,r) -- we reused tmp, hence t
- end
- return t
+function xmlconvert(data,settings)
+ local ok,result=pcall(function() return _xmlconvert_(data,settings) end)
+ if ok then
+ return result
+ else
+ return _xmlconvert_("",settings)
+ end
+end
+xml.convert=xmlconvert
+function xml.inheritedconvert(data,xmldata)
+ local settings=xmldata.settings
+ if settings then
+ settings.parent_root=xmldata
+ end
+ local xc=xmlconvert(data,settings)
+ return xc
end
-
-local function utf16_to_utf8_le(t)
- if type(t) == "string" then
- t = utfsplitlines(str)
- end
- local result = { } -- we reuse result
- for i=1,#t do
- local r, more = 0, 0
- for left, right in bytepairs(t[i]) do
- if right then
- local now = 256*right + left
- if more > 0 then
- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
- more = 0
- r = r + 1
- result[r] = utfchar(now)
- elseif now >= 0xD800 and now <= 0xDBFF then
- more = now
- else
- r = r + 1
- result[r] = utfchar(now)
- end
- end
- end
- t[i] = concat(result,"",1,r) -- we reused tmp, hence t
- end
- return t
+function xml.is_valid(root)
+ return root and root.dt and root.dt[1] and type(root.dt[1])=="table" and not root.dt[1].er
end
-
-local function utf32_to_utf8_be(t)
- if type(t) == "string" then
- t = utfsplitlines(t)
+function xml.package(tag,attributes,data)
+ local ns,tg=match(tag,"^(.-):?([^:]+)$")
+ local t={ ns=ns,tg=tg,dt=data or "",at=attributes or {} }
+ setmetatable(t,mt)
+ return t
+end
+function xml.is_valid(root)
+ return root and not root.error
+end
+xml.errorhandler=report_xml
+function xml.load(filename,settings)
+ local data=""
+ if type(filename)=="string" then
+ local f=io.open(filename,'r')
+ if f then
+ data=f:read("*all")
+ f:close()
+ end
+ elseif filename then
+ data=filename:read("*all")
+ end
+ if settings then
+ settings.currentresource=filename
+ local result=xmlconvert(data,settings)
+ settings.currentresource=nil
+ return result
+ else
+ return xmlconvert(data,{ currentresource=filename })
+ end
+end
+local no_root={ no_root=true }
+function xml.toxml(data)
+ if type(data)=="string" then
+ local root={ xmlconvert(data,no_root) }
+ return (#root>1 and root) or root[1]
+ else
+ return data
+ end
+end
+local function copy(old,tables)
+ if old then
+ tables=tables or {}
+ local new={}
+ if not tables[old] then
+ tables[old]=new
end
- local result = { } -- we reuse result
- for i=1,#t do
- local r, more = 0, -1
- for a,b in bytepairs(t[i]) do
- if a and b then
- if more < 0 then
- more = 256*256*256*a + 256*256*b
- else
- r = r + 1
- result[t] = utfchar(more + 256*a + b)
- more = -1
- end
- else
- break
- end
- end
- t[i] = concat(result,"",1,r)
+ for k,v in next,old do
+ new[k]=(type(v)=="table" and (tables[v] or copy(v,tables))) or v
end
- return t
-end
-
-local function utf32_to_utf8_le(t)
- if type(t) == "string" then
- t = utfsplitlines(t)
+ local mt=getmetatable(old)
+ if mt then
+ setmetatable(new,mt)
end
- local result = { } -- we reuse result
- for i=1,#t do
- local r, more = 0, -1
- for a,b in bytepairs(t[i]) do
- if a and b then
- if more < 0 then
- more = 256*b + a
- else
- r = r + 1
- result[t] = utfchar(more + 256*256*256*b + 256*256*a)
- more = -1
- end
- else
- break
- end
+ return new
+ else
+ return {}
+ end
+end
+xml.copy=copy
+function xml.checkbom(root)
+ if root.ri then
+ local dt=root.dt
+ for k=1,#dt do
+ local v=dt[k]
+ if type(v)=="table" and v.special and v.tg=="@pi@" and find(v.dt[1],"xml.*version=") then
+ return
+ end
+ end
+ insert(dt,1,{ special=true,ns="",tg="@pi@",dt={ "xml version='1.0' standalone='yes'" } } )
+ insert(dt,2,"\n" )
+ end
+end
+local function verbose_element(e,handlers)
+ local handle=handlers.handle
+ local serialize=handlers.serialize
+ local ens,etg,eat,edt,ern=e.ns,e.tg,e.at,e.dt,e.rn
+ local ats=eat and next(eat) and {}
+ if ats then
+ for k,v in next,eat do
+ ats[#ats+1]=formatters['%s=%q'](k,escaped(v))
+ end
+ end
+ if ern and trace_entities and ern~=ens then
+ ens=ern
+ end
+ if ens~="" then
+ if edt and #edt>0 then
+ if ats then
+ handle("<",ens,":",etg," ",concat(ats," "),">")
+ else
+ handle("<",ens,":",etg,">")
+ end
+ for i=1,#edt do
+ local e=edt[i]
+ if type(e)=="string" then
+ handle(escaped(e))
+ else
+ serialize(e,handlers)
+ end
+ end
+ handle("",ens,":",etg,">")
+ else
+ if ats then
+ handle("<",ens,":",etg," ",concat(ats," "),"/>")
+ else
+ handle("<",ens,":",etg,"/>")
+ end
+ end
+ else
+ if edt and #edt>0 then
+ if ats then
+ handle("<",etg," ",concat(ats," "),">")
+ else
+ handle("<",etg,">")
+ end
+ for i=1,#edt do
+ local e=edt[i]
+ if type(e)=="string" then
+ handle(escaped(e))
+ else
+ serialize(e,handlers)
end
- t[i] = concat(result,"",1,r)
+ end
+ handle("",etg,">")
+ else
+ if ats then
+ handle("<",etg," ",concat(ats," "),"/>")
+ else
+ handle("<",etg,"/>")
+ end
end
- return t
+ end
end
-
-unicode.utf32_to_utf8_be = utf32_to_utf8_be
-unicode.utf32_to_utf8_le = utf32_to_utf8_le
-unicode.utf16_to_utf8_be = utf16_to_utf8_be
-unicode.utf16_to_utf8_le = utf16_to_utf8_le
-
-function unicode.utf8_to_utf8(t)
- return type(t) == "string" and utfsplitlines(t) or t
+local function verbose_pi(e,handlers)
+ handlers.handle("",e.dt[1],"?>")
end
-
-function unicode.utf16_to_utf8(t,endian)
- return endian and utf16_to_utf8_be(t) or utf16_to_utf8_le(t) or t
+local function verbose_comment(e,handlers)
+ handlers.handle("")
end
-
-function unicode.utf32_to_utf8(t,endian)
- return endian and utf32_to_utf8_be(t) or utf32_to_utf8_le(t) or t
+local function verbose_cdata(e,handlers)
+ handlers.handle("")
end
-
-local function little(c)
- local b = byte(c)
- if b < 0x10000 then
- return char(b%256,b/256)
- else
- b = b - 0x10000
- local b1, b2 = b/1024 + 0xD800, b%1024 + 0xDC00
- return char(b1%256,b1/256,b2%256,b2/256)
- end
+local function verbose_doctype(e,handlers)
+ handlers.handle("")
end
-
-local function big(c)
- local b = byte(c)
- if b < 0x10000 then
- return char(b/256,b%256)
- else
- b = b - 0x10000
- local b1, b2 = b/1024 + 0xD800, b%1024 + 0xDC00
- return char(b1/256,b1%256,b2/256,b2%256)
- end
+local function verbose_root(e,handlers)
+ handlers.serialize(e.dt,handlers)
end
-
-function unicode.utf8_to_utf16(str,littleendian)
- if littleendian then
- return char(255,254) .. utfgsub(str,".",little)
+local function verbose_text(e,handlers)
+ handlers.handle(escaped(e))
+end
+local function verbose_document(e,handlers)
+ local serialize=handlers.serialize
+ local functions=handlers.functions
+ for i=1,#e do
+ local ei=e[i]
+ if type(ei)=="string" then
+ functions["@tx@"](ei,handlers)
else
- return char(254,255) .. utfgsub(str,".",big)
+ serialize(ei,handlers)
end
+ end
end
-
-function unicode.utfcodes(str)
- local t, n = { }, 0
- for u in utfvalues(str) do
- n = n + 1
- t[n] = format("0x%04X",u)
- end
- return concat(t,separator or " ")
+local function serialize(e,handlers,...)
+ local initialize=handlers.initialize
+ local finalize=handlers.finalize
+ local functions=handlers.functions
+ if initialize then
+ local state=initialize(...)
+ if not state==true then
+ return state
+ end
+ end
+ local etg=e.tg
+ if etg then
+ (functions[etg] or functions["@el@"])(e,handlers)
+ else
+ functions["@dc@"](e,handlers)
+ end
+ if finalize then
+ return finalize()
+ end
end
-
-function unicode.ustring(s)
- return format("U+%05X",type(s) == "number" and s or utfbyte(s))
+local function xserialize(e,handlers)
+ local functions=handlers.functions
+ local etg=e.tg
+ if etg then
+ (functions[etg] or functions["@el@"])(e,handlers)
+ else
+ functions["@dc@"](e,handlers)
+ end
+end
+local handlers={}
+local function newhandlers(settings)
+ local t=table.copy(handlers[settings and settings.parent or "verbose"] or {})
+ if settings then
+ for k,v in next,settings do
+ if type(v)=="table" then
+ local tk=t[k] if not tk then tk={} t[k]=tk end
+ for kk,vv in next,v do
+ tk[kk]=vv
+ end
+ else
+ t[k]=v
+ end
+ end
+ if settings.name then
+ handlers[settings.name]=t
+ end
+ end
+ utilities.storage.mark(t)
+ return t
+end
+local nofunction=function() end
+function xml.sethandlersfunction(handler,name,fnc)
+ handler.functions[name]=fnc or nofunction
end
-
-function unicode.xstring(s)
- return format("0x%05X",type(s) == "number" and s or utfbyte(s))
+function xml.gethandlersfunction(handler,name)
+ return handler.functions[name]
end
-
-
-local lpegmatch = lpeg.match
-local patterns = lpeg.patterns
-local utftype = patterns.utftype
-
-function unicode.filetype(data)
- return data and lpegmatch(utftype,data) or "unknown"
+function xml.gethandlers(name)
+ return handlers[name]
end
-
-local toentities = lpeg.Cs (
- (
- patterns.utf8one
- + (
- patterns.utf8two
- + patterns.utf8three
- + patterns.utf8four
- ) / function(s) local b = utfbyte(s) if b < 127 then return s else return format("%X;",b) end end
- )^0
-)
-
-patterns.toentities = toentities
-
-function utf.toentities(str)
- return lpegmatch(toentities,str)
-end
-
-
-
-
-local P, C, R, Cs = lpeg.P, lpeg.C, lpeg.R, lpeg.Cs
-
-local one = P(1)
-local two = C(1) * C(1)
-local four = C(R(utfchar(0xD8),utfchar(0xFF))) * C(1) * C(1) * C(1)
-
--- actually one of them is already utf ... sort of useless this one
-
-local pattern = P("\254\255") * Cs( (
- four / function(a,b,c,d)
- local ab = 0xFF * byte(a) + byte(b)
- local cd = 0xFF * byte(c) + byte(d)
- return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000)
- end
- + two / function(a,b)
- return utfchar(byte(a)*256 + byte(b))
- end
- + one
- )^1 )
- + P("\255\254") * Cs( (
- four / function(b,a,d,c)
- local ab = 0xFF * byte(a) + byte(b)
- local cd = 0xFF * byte(c) + byte(d)
- return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000)
- end
- + two / function(b,a)
- return utfchar(byte(a)*256 + byte(b))
- end
- + one
- )^1 )
-
-function string.toutf(s)
- return lpegmatch(pattern,s) or s -- todo: utf32
-end
-
-local validatedutf = Cs (
- (
- patterns.utf8one
- + patterns.utf8two
- + patterns.utf8three
- + patterns.utf8four
- + P(1) / "�"
- )^0
-)
-
-patterns.validatedutf = validatedutf
-
-function string.validutf(str)
- return lpegmatch(validatedutf,str)
-end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['l-math'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
+newhandlers {
+ name="verbose",
+ initialize=false,
+ finalize=false,
+ serialize=xserialize,
+ handle=print,
+ functions={
+ ["@dc@"]=verbose_document,
+ ["@dt@"]=verbose_doctype,
+ ["@rt@"]=verbose_root,
+ ["@el@"]=verbose_element,
+ ["@pi@"]=verbose_pi,
+ ["@cm@"]=verbose_comment,
+ ["@cd@"]=verbose_cdata,
+ ["@tx@"]=verbose_text,
+ }
}
-
-local floor, sin, cos, tan = math.floor, math.sin, math.cos, math.tan
-
-if not math.round then
- function math.round(x) return floor(x + 0.5) end
-end
-
-if not math.div then
- function math.div(n,m) return floor(n/m) end
+local result
+local xmlfilehandler=newhandlers {
+ name="file",
+ initialize=function(name)
+ result=io.open(name,"wb")
+ return result
+ end,
+ finalize=function()
+ result:close()
+ return true
+ end,
+ handle=function(...)
+ result:write(...)
+ end,
+}
+function xml.save(root,name)
+ serialize(root,xmlfilehandler,name)
end
-
-if not math.mod then
- function math.mod(n,m) return n % m end
+local result
+local xmlstringhandler=newhandlers {
+ name="string",
+ initialize=function()
+ result={}
+ return result
+ end,
+ finalize=function()
+ return concat(result)
+ end,
+ handle=function(...)
+ result[#result+1]=concat {... }
+ end,
+}
+local function xmltostring(root)
+ if not root then
+ return ""
+ elseif type(root)=="string" then
+ return root
+ else
+ return serialize(root,xmlstringhandler) or ""
+ end
end
-
-local pipi = 2*math.pi/360
-
-if not math.sind then
- function math.sind(d) return sin(d*pipi) end
- function math.cosd(d) return cos(d*pipi) end
- function math.tand(d) return tan(d*pipi) end
+local function __tostring(root)
+ return (root and xmltostring(root)) or ""
end
-
-if not math.odd then
- function math.odd (n) return n % 2 ~= 0 end
- function math.even(n) return n % 2 == 0 end
+initialize_mt=function(root)
+ mt={ __tostring=__tostring,__index=root }
end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['util-tab'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-utilities = utilities or {}
-utilities.tables = utilities.tables or { }
-local tables = utilities.tables
-
-local format, gmatch, rep = string.format, string.gmatch, string.rep
-local concat, insert, remove = table.concat, table.insert, table.remove
-local setmetatable, getmetatable, tonumber, tostring = setmetatable, getmetatable, tonumber, tostring
-local type, next, rawset, tonumber = type, next, rawset, tonumber
-
-function tables.definetable(target) -- defines undefined tables
- local composed, t, n = nil, { }, 0
- for name in gmatch(target,"([^%.]+)") do
- n = n + 1
- if composed then
- composed = composed .. "." .. name
- else
- composed = name
- end
- t[n] = format("%s = %s or { }",composed,composed)
+xml.defaulthandlers=handlers
+xml.newhandlers=newhandlers
+xml.serialize=serialize
+xml.tostring=xmltostring
+local function xmlstring(e,handle)
+ if not handle or (e.special and e.tg~="@rt@") then
+ elseif e.tg then
+ local edt=e.dt
+ if edt then
+ for i=1,#edt do
+ xmlstring(edt[i],handle)
+ end
end
- return concat(t,"\n")
+ else
+ handle(e)
+ end
end
-
-function tables.accesstable(target,root)
- local t = root or _G
- for name in gmatch(target,"([^%.]+)") do
- t = t[name]
- if not t then
- return
- end
+xml.string=xmlstring
+function xml.settings(e)
+ while e do
+ local s=e.settings
+ if s then
+ return s
+ else
+ e=e.__p__
end
- return t
+ end
+ return nil
end
-
-function tables.migratetable(target,v,root)
- local t = root or _G
- local names = string.split(target,".")
- for i=1,#names-1 do
- local name = names[i]
- t[name] = t[name] or { }
- t = t[name]
- if not t then
- return
- end
+function xml.root(e)
+ local r=e
+ while e do
+ e=e.__p__
+ if e then
+ r=e
end
- t[names[#names]] = v
+ end
+ return r
end
-
-function tables.removevalue(t,value) -- todo: n
- if value then
- for i=1,#t do
- if t[i] == value then
- remove(t,i)
- -- remove all, so no: return
- end
- end
- end
+function xml.parent(root)
+ return root.__p__
end
-
-function tables.insertbeforevalue(t,value,extra)
- for i=1,#t do
- if t[i] == extra then
- remove(t,i)
- end
- end
- for i=1,#t do
- if t[i] == value then
- insert(t,i,extra)
- return
- end
- end
- insert(t,1,extra)
+function xml.body(root)
+ return root.ri and root.dt[root.ri] or root
end
-
-function tables.insertaftervalue(t,value,extra)
- for i=1,#t do
- if t[i] == extra then
- remove(t,i)
- end
- end
- for i=1,#t do
- if t[i] == value then
- insert(t,i+1,extra)
- return
- end
- end
- insert(t,#t+1,extra)
+function xml.name(root)
+ if not root then
+ return ""
+ end
+ local ns=root.ns
+ local tg=root.tg
+ if ns=="" then
+ return tg
+ else
+ return ns..":"..tg
+ end
end
-
--- experimental
-
-local function toxml(t,d,result,step)
- for k, v in table.sortedpairs(t) do
- if type(v) == "table" then
- if type(k) == "number" then
- result[#result+1] = format("%s",d,k)
- toxml(v,d..step,result,step)
- result[#result+1] = format("%s ",d,k)
- else
- result[#result+1] = format("%s<%s>",d,k)
- toxml(v,d..step,result,step)
- result[#result+1] = format("%s%s>",d,k)
- end
- elseif type(k) == "number" then
- result[#result+1] = format("%s%s ",d,k,v,k)
- else
- result[#result+1] = format("%s<%s>%s%s>",d,k,tostring(v),k)
- end
- end
+function xml.erase(dt,k)
+ if dt then
+ if k then
+ dt[k]=""
+ else for k=1,#dt do
+ dt[1]={ "" }
+ end end
+ end
end
-
-function table.toxml(t,name,nobanner,indent,spaces)
- local noroot = name == false
- local result = (nobanner or noroot) and { } or { "" }
- local indent = rep(" ",indent or 0)
- local spaces = rep(" ",spaces or 1)
- if noroot then
- toxml( t, inndent, result, spaces)
- else
- toxml( { [name or "root"] = t }, indent, result, spaces)
- end
- return concat(result,"\n")
+function xml.assign(dt,k,root)
+ if dt and k then
+ dt[k]=type(root)=="table" and xml.body(root) or root
+ return dt[k]
+ else
+ return xml.body(root)
+ end
+end
+function xml.tocdata(e,wrapper)
+ local whatever=type(e)=="table" and xmltostring(e.dt) or e or ""
+ if wrapper then
+ whatever=formatters["<%s>%s%s>"](wrapper,whatever,wrapper)
+ end
+ local t={ special=true,ns="",tg="@cd@",at={},rn="",dt={ whatever },__p__=e }
+ setmetatable(t,getmetatable(e))
+ e.dt={ t }
end
-
--- also experimental
-
--- encapsulate(table,utilities.tables)
--- encapsulate(table,utilities.tables,true)
--- encapsulate(table,true)
-
-function tables.encapsulate(core,capsule,protect)
- if type(capsule) ~= "table" then
- protect = true
- capsule = { }
- end
- for key, value in next, core do
- if capsule[key] then
- print(format("\ninvalid inheritance '%s' in '%s': %s",key,tostring(core)))
- os.exit()
- else
- capsule[key] = value
- end
- end
- if protect then
- for key, value in next, core do
- core[key] = nil
+function xml.makestandalone(root)
+ if root.ri then
+ local dt=root.dt
+ for k=1,#dt do
+ local v=dt[k]
+ if type(v)=="table" and v.special and v.tg=="@pi@" then
+ local txt=v.dt[1]
+ if find(txt,"xml.*version=") then
+ v.dt[1]=txt.." standalone='yes'"
+ break
end
- setmetatable(core, {
- __index = capsule,
- __newindex = function(t,key,value)
- if capsule[key] then
- print(format("\ninvalid overload '%s' in '%s'",key,tostring(core)))
- os.exit()
- else
- rawset(t,key,value)
- end
- end
- } )
+ end
end
+ end
+ return root
+end
+function xml.kind(e)
+ local dt=e and e.dt
+ if dt then
+ local n=#dt
+ if n==1 then
+ local d=dt[1]
+ if d.special then
+ local tg=d.tg
+ if tg=="@cd@" then
+ return "cdata"
+ elseif tg=="@cm" then
+ return "comment"
+ elseif tg=="@pi@" then
+ return "instruction"
+ elseif tg=="@dt@" then
+ return "declaration"
+ end
+ elseif type(d)=="string" then
+ return "text"
+ end
+ return "element"
+ elseif n>0 then
+ return "mixed"
+ end
+ end
+ return "empty"
end
@@ -4351,9885 +8998,3514 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['util-sto'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local setmetatable, getmetatable = setmetatable, getmetatable
-
-utilities = utilities or { }
-utilities.storage = utilities.storage or { }
-local storage = utilities.storage
-
-function storage.mark(t)
- if not t then
- texio.write_nl("fatal error: storage cannot be marked")
- return -- os.exit()
- end
- local m = getmetatable(t)
- if not m then
- m = { }
- setmetatable(t,m)
- end
- m.__storage__ = true
- return t
-end
-
-function storage.allocate(t)
- t = t or { }
- local m = getmetatable(t)
- if not m then
- m = { }
- setmetatable(t,m)
- end
- m.__storage__ = true
- return t
-end
-
-function storage.marked(t)
- local m = getmetatable(t)
- return m and m.__storage__
-end
-
-function storage.checked(t)
- if not t then
- texio.write_nl("fatal error: storage has not been allocated")
- return -- os.exit()
- end
- return t
-end
+package.loaded["lxml-lpt"] = package.loaded["lxml-lpt"] or true
+-- original size: 48956, stripped down to: 30516
-function storage.setinitializer(data,initialize)
- local m = getmetatable(data) or { }
- m.__index = function(data,k)
- m.__index = nil -- so that we can access the entries during initializing
- initialize()
- return data[k]
- end
- setmetatable(data, m)
+if not modules then modules={} end modules ['lxml-lpt']={
+ version=1.001,
+ comment="this module is the basis for the lxml-* ones",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local concat,remove,insert=table.concat,table.remove,table.insert
+local type,next,tonumber,tostring,setmetatable,load,select=type,next,tonumber,tostring,setmetatable,load,select
+local format,upper,lower,gmatch,gsub,find,rep=string.format,string.upper,string.lower,string.gmatch,string.gsub,string.find,string.rep
+local lpegmatch,lpegpatterns=lpeg.match,lpeg.patterns
+local setmetatableindex=table.setmetatableindex
+local formatters=string.formatters
+local trace_lpath=false if trackers then trackers.register("xml.path",function(v) trace_lpath=v end) end
+local trace_lparse=false if trackers then trackers.register("xml.parse",function(v) trace_lparse=v end) end
+local trace_lprofile=false if trackers then trackers.register("xml.profile",function(v) trace_lpath=v trace_lparse=v trace_lprofile=v end) end
+local report_lpath=logs.reporter("xml","lpath")
+local xml=xml
+local lpathcalls=0 function xml.lpathcalls () return lpathcalls end
+local lpathcached=0 function xml.lpathcached() return lpathcached end
+xml.functions=xml.functions or {}
+local functions=xml.functions
+xml.expressions=xml.expressions or {}
+local expressions=xml.expressions
+xml.finalizers=xml.finalizers or {}
+local finalizers=xml.finalizers
+xml.specialhandler=xml.specialhandler or {}
+local specialhandler=xml.specialhandler
+lpegpatterns.xml=lpegpatterns.xml or {}
+local xmlpatterns=lpegpatterns.xml
+finalizers.xml=finalizers.xml or {}
+finalizers.tex=finalizers.tex or {}
+local function fallback (t,name)
+ local fn=finalizers[name]
+ if fn then
+ t[name]=fn
+ else
+ report_lpath("unknown sub finalizer %a",name)
+ fn=function() end
+ end
+ return fn
+end
+setmetatableindex(finalizers.xml,fallback)
+setmetatableindex(finalizers.tex,fallback)
+xml.defaultprotocol="xml"
+local apply_axis={}
+apply_axis['root']=function(list)
+ local collected={}
+ for l=1,#list do
+ local ll=list[l]
+ local rt=ll
+ while ll do
+ ll=ll.__p__
+ if ll then
+ rt=ll
+ end
+ end
+ collected[l]=rt
+ end
+ return collected
+end
+apply_axis['self']=function(list)
+ return list
+end
+apply_axis['child']=function(list)
+ local collected,c={},0
+ for l=1,#list do
+ local ll=list[l]
+ local dt=ll.dt
+ if dt then
+ local en=0
+ for k=1,#dt do
+ local dk=dt[k]
+ if dk.tg then
+ c=c+1
+ collected[c]=dk
+ dk.ni=k
+ en=en+1
+ dk.ei=en
+ end
+ end
+ ll.en=en
+ end
+ end
+ return collected
end
-
-local keyisvalue = { __index = function(t,k)
- t[k] = k
- return k
-end }
-
-function storage.sparse(t)
- t = t or { }
- setmetatable(t,keyisvalue)
- return t
+local function collect(list,collected,c)
+ local dt=list.dt
+ if dt then
+ local en=0
+ for k=1,#dt do
+ local dk=dt[k]
+ if dk.tg then
+ c=c+1
+ collected[c]=dk
+ dk.ni=k
+ en=en+1
+ dk.ei=en
+ c=collect(dk,collected,c)
+ end
+ end
+ list.en=en
+ end
+ return c
+end
+apply_axis['descendant']=function(list)
+ local collected,c={},0
+ for l=1,#list do
+ c=collect(list[l],collected,c)
+ end
+ return collected
end
-
--- table namespace ?
-
-local function f_empty () return "" end -- t,k
-local function f_self (t,k) t[k] = k return k end
-local function f_ignore() end -- t,k,v
-
-local t_empty = { __index = f_empty }
-local t_self = { __index = f_self }
-local t_ignore = { __newindex = f_ignore }
-
-function table.setmetatableindex(t,f)
- local m = getmetatable(t)
- if m then
- if f == "empty" then
- m.__index = f_empty
- elseif f == "key" then
- m.__index = f_self
- else
- m.__index = f
- end
+local function collect(list,collected,c)
+ local dt=list.dt
+ if dt then
+ local en=0
+ for k=1,#dt do
+ local dk=dt[k]
+ if dk.tg then
+ c=c+1
+ collected[c]=dk
+ dk.ni=k
+ en=en+1
+ dk.ei=en
+ c=collect(dk,collected,c)
+ end
+ end
+ list.en=en
+ end
+ return c
+end
+apply_axis['descendant-or-self']=function(list)
+ local collected,c={},0
+ for l=1,#list do
+ local ll=list[l]
+ if ll.special~=true then
+ c=c+1
+ collected[c]=ll
+ end
+ c=collect(ll,collected,c)
+ end
+ return collected
+end
+apply_axis['ancestor']=function(list)
+ local collected,c={},0
+ for l=1,#list do
+ local ll=list[l]
+ while ll do
+ ll=ll.__p__
+ if ll then
+ c=c+1
+ collected[c]=ll
+ end
+ end
+ end
+ return collected
+end
+apply_axis['ancestor-or-self']=function(list)
+ local collected,c={},0
+ for l=1,#list do
+ local ll=list[l]
+ c=c+1
+ collected[c]=ll
+ while ll do
+ ll=ll.__p__
+ if ll then
+ c=c+1
+ collected[c]=ll
+ end
+ end
+ end
+ return collected
+end
+apply_axis['parent']=function(list)
+ local collected,c={},0
+ for l=1,#list do
+ local pl=list[l].__p__
+ if pl then
+ c=c+1
+ collected[c]=pl
+ end
+ end
+ return collected
+end
+apply_axis['attribute']=function(list)
+ return {}
+end
+apply_axis['namespace']=function(list)
+ return {}
+end
+apply_axis['following']=function(list)
+ return {}
+end
+apply_axis['preceding']=function(list)
+ return {}
+end
+apply_axis['following-sibling']=function(list)
+ local collected,c={},0
+ for l=1,#list do
+ local ll=list[l]
+ local p=ll.__p__
+ local d=p.dt
+ for i=ll.ni+1,#d do
+ local di=d[i]
+ if type(di)=="table" then
+ c=c+1
+ collected[c]=di
+ end
+ end
+ end
+ return collected
+end
+apply_axis['preceding-sibling']=function(list)
+ local collected,c={},0
+ for l=1,#list do
+ local ll=list[l]
+ local p=ll.__p__
+ local d=p.dt
+ for i=1,ll.ni-1 do
+ local di=d[i]
+ if type(di)=="table" then
+ c=c+1
+ collected[c]=di
+ end
+ end
+ end
+ return collected
+end
+apply_axis['reverse-sibling']=function(list)
+ local collected,c={},0
+ for l=1,#list do
+ local ll=list[l]
+ local p=ll.__p__
+ local d=p.dt
+ for i=ll.ni-1,1,-1 do
+ local di=d[i]
+ if type(di)=="table" then
+ c=c+1
+ collected[c]=di
+ end
+ end
+ end
+ return collected
+end
+apply_axis['auto-descendant-or-self']=apply_axis['descendant-or-self']
+apply_axis['auto-descendant']=apply_axis['descendant']
+apply_axis['auto-child']=apply_axis['child']
+apply_axis['auto-self']=apply_axis['self']
+apply_axis['initial-child']=apply_axis['child']
+local function apply_nodes(list,directive,nodes)
+ local maxn=#nodes
+ if maxn==3 then
+ local nns,ntg=nodes[2],nodes[3]
+ if not nns and not ntg then
+ if directive then
+ return list
+ else
+ return {}
+ end
else
- if f == "empty" then
- setmetatable(t, t_empty)
- elseif f == "key" then
- setmetatable(t, t_self)
- else
- setmetatable(t,{ __index = f })
- end
- end
- return t
-end
-
-function table.setmetatablenewindex(t,f)
- local m = getmetatable(t)
- if m then
- if f == "ignore" then
- m.__newindex = f_ignore
- else
- m.__newindex = f
+ local collected,c,m,p={},0,0,nil
+ if not nns then
+ for l=1,#list do
+ local ll=list[l]
+ local ltg=ll.tg
+ if ltg then
+ if directive then
+ if ntg==ltg then
+ local llp=ll.__p__;if llp~=p then p,m=llp,1 else m=m+1 end
+ c=c+1
+ collected[c],ll.mi=ll,m
+ end
+ elseif ntg~=ltg then
+ local llp=ll.__p__;if llp~=p then p,m=llp,1 else m=m+1 end
+ c=c+1
+ collected[c],ll.mi=ll,m
+ end
+ end
+ end
+ elseif not ntg then
+ for l=1,#list do
+ local ll=list[l]
+ local lns=ll.rn or ll.ns
+ if lns then
+ if directive then
+ if lns==nns then
+ local llp=ll.__p__;if llp~=p then p,m=llp,1 else m=m+1 end
+ c=c+1
+ collected[c],ll.mi=ll,m
+ end
+ elseif lns~=nns then
+ local llp=ll.__p__;if llp~=p then p,m=llp,1 else m=m+1 end
+ c=c+1
+ collected[c],ll.mi=ll,m
+ end
+ end
+ end
+ else
+ for l=1,#list do
+ local ll=list[l]
+ local ltg=ll.tg
+ if ltg then
+ local lns=ll.rn or ll.ns
+ local ok=ltg==ntg and lns==nns
+ if directive then
+ if ok then
+ local llp=ll.__p__;if llp~=p then p,m=llp,1 else m=m+1 end
+ c=c+1
+ collected[c],ll.mi=ll,m
+ end
+ elseif not ok then
+ local llp=ll.__p__;if llp~=p then p,m=llp,1 else m=m+1 end
+ c=c+1
+ collected[c],ll.mi=ll,m
+ end
+ end
+ end
+ end
+ return collected
+ end
+ else
+ local collected,c,m,p={},0,0,nil
+ for l=1,#list do
+ local ll=list[l]
+ local ltg=ll.tg
+ if ltg then
+ local lns=ll.rn or ll.ns
+ local ok=false
+ for n=1,maxn,3 do
+ local nns,ntg=nodes[n+1],nodes[n+2]
+ ok=(not ntg or ltg==ntg) and (not nns or lns==nns)
+ if ok then
+ break
+ end
end
- else
- if f == "ignore" then
- setmetatable(t, t_ignore)
- else
- setmetatable(t,{ __newindex = f })
+ if directive then
+ if ok then
+ local llp=ll.__p__;if llp~=p then p,m=llp,1 else m=m+1 end
+ c=c+1
+ collected[c],ll.mi=ll,m
+ end
+ elseif not ok then
+ local llp=ll.__p__;if llp~=p then p,m=llp,1 else m=m+1 end
+ c=c+1
+ collected[c],ll.mi=ll,m
end
+ end
end
- return t
+ return collected
+ end
end
-
-function table.setmetatablecall(t,f)
- local m = getmetatable(t)
- if m then
- m.__call = f
+local quit_expression=false
+local function apply_expression(list,expression,order)
+ local collected,c={},0
+ quit_expression=false
+ for l=1,#list do
+ local ll=list[l]
+ if expression(list,ll,l,order) then
+ c=c+1
+ collected[c]=ll
+ end
+ if quit_expression then
+ break
+ end
+ end
+ return collected
+end
+local P,V,C,Cs,Cc,Ct,R,S,Cg,Cb=lpeg.P,lpeg.V,lpeg.C,lpeg.Cs,lpeg.Cc,lpeg.Ct,lpeg.R,lpeg.S,lpeg.Cg,lpeg.Cb
+local spaces=S(" \n\r\t\f")^0
+local lp_space=S(" \n\r\t\f")
+local lp_any=P(1)
+local lp_noequal=P("!=")/"~="+P("<=")+P(">=")+P("==")
+local lp_doequal=P("=")/"=="
+local lp_or=P("|")/" or "
+local lp_and=P("&")/" and "
+local lp_builtin=P (
+ P("text")/"(ll.dt[1] or '')"+
+ P("content")/"ll.dt"+
+ P("name")/"((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)"+P("tag")/"ll.tg"+P("position")/"l"+
+ P("firstindex")/"1"+P("lastindex")/"(#ll.__p__.dt or 1)"+P("firstelement")/"1"+P("lastelement")/"(ll.__p__.en or 1)"+P("first")/"1"+P("last")/"#list"+P("rootposition")/"order"+P("order")/"order"+P("element")/"(ll.ei or 1)"+P("index")/"(ll.ni or 1)"+P("match")/"(ll.mi or 1)"+
+ P("ns")/"ll.ns"
+ )*((spaces*P("(")*spaces*P(")"))/"")
+local lp_attribute=(P("@")+P("attribute::"))/""*Cc("(ll.at and ll.at['")*((R("az","AZ")+S("-_:"))^1)*Cc("'])")
+lp_fastpos_p=P("+")^0*R("09")^1*P(-1)/"l==%0"
+lp_fastpos_n=P("-")*R("09")^1*P(-1)/"(%0<0 and (#list+%0==l))"
+local lp_fastpos=lp_fastpos_n+lp_fastpos_p
+local lp_reserved=C("and")+C("or")+C("not")+C("div")+C("mod")+C("true")+C("false")
+local lp_lua_function=Cs((R("az","AZ","__")^1*(P(".")*R("az","AZ","__")^1)^1)*("("))/"%0"
+local lp_function=C(R("az","AZ","__")^1)*P("(")/function(t)
+ if expressions[t] then
+ return "expr."..t.."("
+ else
+ return "expr.error("
+ end
+end
+local lparent=P("(")
+local rparent=P(")")
+local noparent=1-(lparent+rparent)
+local nested=P{lparent*(noparent+V(1))^0*rparent}
+local value=P(lparent*C((noparent+nested)^0)*rparent)
+local lp_child=Cc("expr.child(ll,'")*R("az","AZ","--","__")^1*Cc("')")
+local lp_number=S("+-")*R("09")^1
+local lp_string=Cc("'")*R("az","AZ","--","__")^1*Cc("'")
+local lp_content=(P("'")*(1-P("'"))^0*P("'")+P('"')*(1-P('"'))^0*P('"'))
+local cleaner
+local lp_special=(C(P("name")+P("text")+P("tag")+P("count")+P("child")))*value/function(t,s)
+ if expressions[t] then
+ s=s and s~="" and lpegmatch(cleaner,s)
+ if s and s~="" then
+ return "expr."..t.."(ll,"..s..")"
else
- setmetatable(t,{ __call = f })
+ return "expr."..t.."(ll)"
end
- return t
+ else
+ return "expr.error("..t..")"
+ end
end
-
-function table.setmetatablekey(t,key,value)
- local m = getmetatable(t)
- if not m then
- m = { }
- setmetatable(t,m)
+local content=lp_builtin+lp_attribute+lp_special+lp_noequal+lp_doequal+lp_or+lp_and+lp_reserved+lp_lua_function+lp_function+lp_content+
+ lp_child+lp_any
+local converter=Cs (
+ lp_fastpos+(P { lparent*(V(1))^0*rparent+content } )^0
+)
+cleaner=Cs ((
+ lp_reserved+lp_number+lp_string+1 )^1 )
+local template_e=[[
+ local expr = xml.expressions
+ return function(list,ll,l,order)
+ return %s
end
- m[key] = value
- return t
+]]
+local template_f_y=[[
+ local finalizer = xml.finalizers['%s']['%s']
+ return function(collection)
+ return finalizer(collection,%s)
+ end
+]]
+local template_f_n=[[
+ return xml.finalizers['%s']['%s']
+]]
+local register_self={ kind="axis",axis="self" }
+local register_parent={ kind="axis",axis="parent" }
+local register_descendant={ kind="axis",axis="descendant" }
+local register_child={ kind="axis",axis="child" }
+local register_descendant_or_self={ kind="axis",axis="descendant-or-self" }
+local register_root={ kind="axis",axis="root" }
+local register_ancestor={ kind="axis",axis="ancestor" }
+local register_ancestor_or_self={ kind="axis",axis="ancestor-or-self" }
+local register_attribute={ kind="axis",axis="attribute" }
+local register_namespace={ kind="axis",axis="namespace" }
+local register_following={ kind="axis",axis="following" }
+local register_following_sibling={ kind="axis",axis="following-sibling" }
+local register_preceding={ kind="axis",axis="preceding" }
+local register_preceding_sibling={ kind="axis",axis="preceding-sibling" }
+local register_reverse_sibling={ kind="axis",axis="reverse-sibling" }
+local register_auto_descendant_or_self={ kind="axis",axis="auto-descendant-or-self" }
+local register_auto_descendant={ kind="axis",axis="auto-descendant" }
+local register_auto_self={ kind="axis",axis="auto-self" }
+local register_auto_child={ kind="axis",axis="auto-child" }
+local register_initial_child={ kind="axis",axis="initial-child" }
+local register_all_nodes={ kind="nodes",nodetest=true,nodes={ true,false,false } }
+local skip={}
+local function errorrunner_e(str,cnv)
+ if not skip[str] then
+ report_lpath("error in expression: %s => %s",str,cnv)
+ skip[str]=cnv or str
+ end
+ return false
end
-
-function table.getmetatablekey(t,key,value)
- local m = getmetatable(t)
- return m and m[key]
+local function errorrunner_f(str,arg)
+ report_lpath("error in finalizer: %s(%s)",str,arg or "")
+ return false
end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['util-mrg'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- hm, quite unreadable
-
-local gsub, format = string.gsub, string.format
-local concat = table.concat
-local type, next = type, next
-
-utilities = utilities or {}
-utilities.merger = utilities.merger or { } -- maybe mergers
-utilities.report = logs and logs.reporter("system") or print
-
-local merger = utilities.merger
-
-merger.strip_comment = true
-
-local m_begin_merge = "begin library merge"
-local m_end_merge = "end library merge"
-local m_begin_closure = "do -- create closure to overcome 200 locals limit"
-local m_end_closure = "end -- of closure"
-
-local m_pattern =
- "%c+" ..
- "%-%-%s+" .. m_begin_merge ..
- "%c+(.-)%c+" ..
- "%-%-%s+" .. m_end_merge ..
- "%c+"
-
-local m_format =
- "\n\n-- " .. m_begin_merge ..
- "\n%s\n" ..
- "-- " .. m_end_merge .. "\n\n"
-
-local m_faked =
- "-- " .. "created merged file" .. "\n\n" ..
- "-- " .. m_begin_merge .. "\n\n" ..
- "-- " .. m_end_merge .. "\n\n"
-
-local function self_fake()
- return m_faked
+local function register_nodes(nodetest,nodes)
+ return { kind="nodes",nodetest=nodetest,nodes=nodes }
end
-
-local function self_nothing()
- return ""
-end
-
-local function self_load(name)
- local data = io.loaddata(name) or ""
- if data == "" then
- utilities.report("merge: unknown file %s",name)
- else
- utilities.report("merge: inserting %s",name)
- end
- return data or ""
-end
-
-local function self_save(name, data)
- if data ~= "" then
- if merger.strip_comment then
- -- saves some 20K
- local n = #data
- data = gsub(data,"%-%-~[^\n\r]*[\r\n]","")
- utilities.report("merge: %s bytes of comment stripped, %s bytes of code left",n-#data,#data)
- end
- io.savedata(name,data)
- utilities.report("merge: saving %s",name)
- end
-end
-
-local function self_swap(data,code)
- return data ~= "" and (gsub(data,m_pattern, function() return format(m_format,code) end, 1)) or ""
-end
-
-local function self_libs(libs,list)
- local result, f, frozen, foundpath = { }, nil, false, nil
- result[#result+1] = "\n"
- if type(libs) == 'string' then libs = { libs } end
- if type(list) == 'string' then list = { list } end
- for i=1,#libs do
- local lib = libs[i]
- for j=1,#list do
- local pth = gsub(list[j],"\\","/") -- file.clean_path
- utilities.report("merge: checking library path %s",pth)
- local name = pth .. "/" .. lib
- if lfs.isfile(name) then
- foundpath = pth
- end
- end
- if foundpath then break end
- end
- if foundpath then
- utilities.report("merge: using library path %s",foundpath)
- local right, wrong = { }, { }
- for i=1,#libs do
- local lib = libs[i]
- local fullname = foundpath .. "/" .. lib
- if lfs.isfile(fullname) then
- utilities.report("merge: using library %s",fullname)
- right[#right+1] = lib
- result[#result+1] = m_begin_closure
- result[#result+1] = io.loaddata(fullname,true)
- result[#result+1] = m_end_closure
- else
- utilities.report("merge: skipping library %s",fullname)
- wrong[#wrong+1] = lib
- end
- end
- if #right > 0 then
- utilities.report("merge: used libraries: %s",concat(right," "))
- end
- if #wrong > 0 then
- utilities.report("merge: skipped libraries: %s",concat(wrong," "))
- end
- else
- utilities.report("merge: no valid library path found")
- end
- return concat(result, "\n\n")
-end
-
-function merger.selfcreate(libs,list,target)
- if target then
- self_save(target,self_swap(self_fake(),self_libs(libs,list)))
- end
-end
-
-function merger.selfmerge(name,libs,list,target)
- self_save(target or name,self_swap(self_load(name),self_libs(libs,list)))
-end
-
-function merger.selfclean(name)
- self_save(name,self_swap(self_load(name),self_nothing()))
-end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['util-lua'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-utilities = utilities or {}
-utilities.lua = utilities.lua or { }
-utilities.report = logs and logs.reporter("system") or print
-
-local function stupidcompile(luafile,lucfile)
- local data = io.loaddata(luafile)
- if data and data ~= "" then
- data = string.dump(data)
- if data and data ~= "" then
- io.savedata(lucfile,data)
- end
- end
-end
-
-function utilities.lua.compile(luafile,lucfile,cleanup,strip,fallback) -- defaults: cleanup=false strip=true
- utilities.report("lua: compiling %s into %s",luafile,lucfile)
- os.remove(lucfile)
- local command = "-o " .. string.quoted(lucfile) .. " " .. string.quoted(luafile)
- if strip ~= false then
- command = "-s " .. command
- end
- local done = os.spawn("texluac " .. command) == 0 -- or os.spawn("luac " .. command) == 0
- if not done and fallback then
- utilities.report("lua: dumping %s into %s (unstripped)",luafile,lucfile)
- stupidcompile(luafile,lucfile) -- maybe use the stripper we have elsewhere
- cleanup = false -- better see how worse it is
- end
- if done and cleanup == true and lfs.isfile(lucfile) and lfs.isfile(luafile) then
- utilities.report("lua: removing %s",luafile)
- os.remove(luafile)
- end
- return done
+local function register_expression(expression)
+ local converted=lpegmatch(converter,expression)
+ local runner=load(format(template_e,converted))
+ runner=(runner and runner()) or function() errorrunner_e(expression,converted) end
+ return { kind="expression",expression=expression,converted=converted,evaluator=runner }
end
-
-
-
-
-
-
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['util-prs'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local P, R, V, C, Ct, Cs, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Carg
-local lpegmatch = lpeg.match
-local concat, format, gmatch, find = table.concat, string.format, string.gmatch, string.find
-local tostring, type, next = tostring, type, next
-
-utilities = utilities or {}
-utilities.parsers = utilities.parsers or { }
-local parsers = utilities.parsers
-parsers.patterns = parsers.patterns or { }
-
-local setmetatableindex = table.setmetatableindex
-local sortedhash = table.sortedhash
-
--- we could use a Cf Cg construct
-
-local escape, left, right = P("\\"), P('{'), P('}')
-
-lpeg.patterns.balanced = P {
- [1] = ((escape * (left+right)) + (1 - (left+right)) + V(2))^0,
- [2] = left * V(1) * right
+local function register_finalizer(protocol,name,arguments)
+ local runner
+ if arguments and arguments~="" then
+ runner=load(format(template_f_y,protocol or xml.defaultprotocol,name,arguments))
+ else
+ runner=load(format(template_f_n,protocol or xml.defaultprotocol,name))
+ end
+ runner=(runner and runner()) or function() errorrunner_f(name,arguments) end
+ return { kind="finalizer",name=name,arguments=arguments,finalizer=runner }
+end
+local expression=P { "ex",
+ ex="["*C((V("sq")+V("dq")+(1-S("[]"))+V("ex"))^0)*"]",
+ sq="'"*(1-S("'"))^0*"'",
+ dq='"'*(1-S('"'))^0*'"',
}
-
-local space = P(' ')
-local equal = P("=")
-local comma = P(",")
-local lbrace = P("{")
-local rbrace = P("}")
-local nobrace = 1 - (lbrace+rbrace)
-local nested = P { lbrace * (nobrace + V(1))^0 * rbrace }
-local spaces = space^0
-local argument = Cs((lbrace/"") * ((nobrace + nested)^0) * (rbrace/""))
-local content = (1-P(-1))^0
-
-lpeg.patterns.nested = nested -- no capture
-lpeg.patterns.argument = argument -- argument after e.g. =
-lpeg.patterns.content = content -- rest after e.g =
-
-local value = P(lbrace * C((nobrace + nested)^0) * rbrace) + C((nested + (1-comma))^0)
-
-local key = C((1-equal-comma)^1)
-local pattern_a = (space+comma)^0 * (key * equal * value + key * C(""))
-local pattern_c = (space+comma)^0 * (key * equal * value)
-
-local key = C((1-space-equal-comma)^1)
-local pattern_b = spaces * comma^0 * spaces * (key * ((spaces * equal * spaces * value) + C("")))
-
--- "a=1, b=2, c=3, d={a{b,c}d}, e=12345, f=xx{a{b,c}d}xx, g={}" : outer {} removes, leading spaces ignored
-
-local hash = { }
-
-local function set(key,value)
- hash[key] = value
-end
-
-local function set(key,value)
- hash[key] = value
-end
-
-local pattern_a_s = (pattern_a/set)^1
-local pattern_b_s = (pattern_b/set)^1
-local pattern_c_s = (pattern_c/set)^1
-
-parsers.patterns.settings_to_hash_a = pattern_a_s
-parsers.patterns.settings_to_hash_b = pattern_b_s
-parsers.patterns.settings_to_hash_c = pattern_c_s
-
-function parsers.make_settings_to_hash_pattern(set,how)
- if how == "strict" then
- return (pattern_c/set)^1
- elseif how == "tolerant" then
- return (pattern_b/set)^1
- else
- return (pattern_a/set)^1
- end
-end
-
-function parsers.settings_to_hash(str,existing)
- if str and str ~= "" then
- hash = existing or { }
- lpegmatch(pattern_a_s,str)
- return hash
- else
- return { }
- end
-end
-
-function parsers.settings_to_hash_tolerant(str,existing)
- if str and str ~= "" then
- hash = existing or { }
- lpegmatch(pattern_b_s,str)
- return hash
- else
- return { }
- end
-end
-
-function parsers.settings_to_hash_strict(str,existing)
- if str and str ~= "" then
- hash = existing or { }
- lpegmatch(pattern_c_s,str)
- return next(hash) and hash
- else
- return nil
- end
-end
-
-local separator = comma * space^0
-local value = P(lbrace * C((nobrace + nested)^0) * rbrace) + C((nested + (1-comma))^0)
-local pattern = Ct(value*(separator*value)^0)
-
--- "aap, {noot}, mies" : outer {} removes, leading spaces ignored
-
-parsers.patterns.settings_to_array = pattern
-
--- we could use a weak table as cache
-
-function parsers.settings_to_array(str,strict)
- if not str or str == "" then
- return { }
- elseif strict then
- if find(str,"{") then
- return lpegmatch(pattern,str)
- else
- return { str }
- end
- else
- return lpegmatch(pattern,str)
- end
-end
-
-local function set(t,v)
- t[#t+1] = v
-end
-
-local value = P(Carg(1)*value) / set
-local pattern = value*(separator*value)^0 * Carg(1)
-
-function parsers.add_settings_to_array(t,str)
- return lpegmatch(pattern,str,nil,t)
-end
-
-function parsers.hash_to_string(h,separator,yes,no,strict,omit)
- if h then
- local t, tn, s = { }, 0, table.sortedkeys(h)
- omit = omit and table.tohash(omit)
- for i=1,#s do
- local key = s[i]
- if not omit or not omit[key] then
- local value = h[key]
- if type(value) == "boolean" then
- if yes and no then
- if value then
- tn = tn + 1
- t[tn] = key .. '=' .. yes
- elseif not strict then
- tn = tn + 1
- t[tn] = key .. '=' .. no
- end
- elseif value or not strict then
- tn = tn + 1
- t[tn] = key .. '=' .. tostring(value)
- end
- else
- tn = tn + 1
- t[tn] = key .. '=' .. value
- end
- end
- end
- return concat(t,separator or ",")
- else
- return ""
- end
-end
-
-function parsers.array_to_string(a,separator)
- if a then
- return concat(a,separator or ",")
- else
- return ""
- end
-end
-
-function parsers.settings_to_set(str,t) -- tohash? -- todo: lpeg -- duplicate anyway
- t = t or { }
--- for s in gmatch(str,"%s*([^, ]+)") do -- space added
- for s in gmatch(str,"[^, ]+") do -- space added
- t[s] = true
- end
- return t
-end
-
-function parsers.simple_hash_to_string(h, separator)
- local t, tn = { }, 0
- for k, v in sortedhash(h) do
- if v then
- tn = tn + 1
- t[tn] = k
- end
- end
- return concat(t,separator or ",")
-end
-
-local value = lbrace * C((nobrace + nested)^0) * rbrace
-local pattern = Ct((space + value)^0)
-
-function parsers.arguments_to_table(str)
- return lpegmatch(pattern,str)
-end
-
--- temporary here (unoptimized)
-
-function parsers.getparameters(self,class,parentclass,settings)
- local sc = self[class]
- if not sc then
- sc = { }
- self[class] = sc
- if parentclass then
- local sp = self[parentclass]
- if not sp then
- sp = { }
- self[parentclass] = sp
- end
- setmetatableindex(sc,sp)
- end
- end
- parsers.settings_to_hash(settings,sc)
-end
-
-function parsers.listitem(str)
- return gmatch(str,"[^, ]+")
-end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['util-fmt'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
+local arguments=P { "ar",
+ ar="("*Cs((V("sq")+V("dq")+V("nq")+P(1-P(")")))^0)*")",
+ nq=((1-S("),'\""))^1)/function(s) return format("%q",s) end,
+ sq=P("'")*(1-P("'"))^0*P("'"),
+ dq=P('"')*(1-P('"'))^0*P('"'),
}
-
-utilities = utilities or { }
-utilities.formatters = utilities.formatters or { }
-local formatters = utilities.formatters
-
-local concat, format = table.concat, string.format
-local tostring, type = tostring, type
-local strip = string.strip
-
-local P, R, Cs = lpeg.P, lpeg.R, lpeg.Cs
-local lpegmatch = lpeg.match
-
--- temporary here
-
-local digit = R("09")
-local period = P(".")
-local zero = P("0")
-local trailingzeros = zero^0 * -digit -- suggested by Roberto R
-local case_1 = period * trailingzeros / ""
-local case_2 = period * (digit - trailingzeros)^1 * (trailingzeros / "")
-local number = digit^1 * (case_1 + case_2)
-local stripper = Cs((number + 1)^0)
-
-
-lpeg.patterns.stripzeros = stripper
-
-function formatters.stripzeros(str)
- return lpegmatch(stripper,str)
-end
-
-function formatters.formatcolumns(result,between)
- if result and #result > 0 then
- between = between or " "
- local widths, numbers = { }, { }
- local first = result[1]
- local n = #first
- for i=1,n do
- widths[i] = 0
- end
- for i=1,#result do
- local r = result[i]
- for j=1,n do
- local rj = r[j]
- local tj = type(rj)
- if tj == "number" then
- numbers[j] = true
- end
- if tj ~= "string" then
- rj = tostring(rj)
- r[j] = rj
- end
- local w = #rj
- if w > widths[j] then
- widths[j] = w
- end
- end
- end
- for i=1,n do
- local w = widths[i]
- if numbers[i] then
- if w > 80 then
- widths[i] = "%s" .. between
- else
- widths[i] = "%0" .. w .. "i" .. between
- end
- else
- if w > 80 then
- widths[i] = "%s" .. between
- elseif w > 0 then
- widths[i] = "%-" .. w .. "s" .. between
- else
- widths[i] = "%s"
- end
- end
- end
- local template = strip(concat(widths))
- for i=1,#result do
- local str = format(template,unpack(result[i]))
- result[i] = strip(str)
- end
- end
- return result
-end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['util.deb'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
+local function register_error(str)
+ return { kind="error",error=format("unparsed: %s",str) }
+end
+local special_1=P("*")*Cc(register_auto_descendant)*Cc(register_all_nodes)
+local special_2=P("/")*Cc(register_auto_self)
+local special_3=P("")*Cc(register_auto_self)
+local no_nextcolon=P(-1)+#(1-P(":"))
+local no_nextlparent=P(-1)+#(1-P("("))
+local pathparser=Ct { "patterns",
+ patterns=spaces*V("protocol")*spaces*(
+ (V("special")*spaces*P(-1) )+(V("initial")*spaces*V("step")*spaces*(P("/")*spaces*V("step")*spaces)^0 )
+ ),
+ protocol=Cg(V("letters"),"protocol")*P("://")+Cg(Cc(nil),"protocol"),
+ step=((V("shortcuts")+P("/")+V("axis"))*spaces*V("nodes")^0+V("error"))*spaces*V("expressions")^0*spaces*V("finalizer")^0,
+ axis=V("descendant")+V("child")+V("parent")+V("self")+V("root")+V("ancestor")+V("descendant_or_self")+V("following_sibling")+V("following")+V("reverse_sibling")+V("preceding_sibling")+V("preceding")+V("ancestor_or_self")+#(1-P(-1))*Cc(register_auto_child),
+ special=special_1+special_2+special_3,
+ initial=(P("/")*spaces*Cc(register_initial_child))^-1,
+ error=(P(1)^1)/register_error,
+ shortcuts_a=V("s_descendant_or_self")+V("s_descendant")+V("s_child")+V("s_parent")+V("s_self")+V("s_root")+V("s_ancestor"),
+ shortcuts=V("shortcuts_a")*(spaces*"/"*spaces*V("shortcuts_a"))^0,
+ s_descendant_or_self=(P("***/")+P("/"))*Cc(register_descendant_or_self),
+ s_descendant=P("**")*Cc(register_descendant),
+ s_child=P("*")*no_nextcolon*Cc(register_child ),
+ s_parent=P("..")*Cc(register_parent ),
+ s_self=P("." )*Cc(register_self ),
+ s_root=P("^^")*Cc(register_root ),
+ s_ancestor=P("^")*Cc(register_ancestor ),
+ descendant=P("descendant::")*Cc(register_descendant ),
+ child=P("child::")*Cc(register_child ),
+ parent=P("parent::")*Cc(register_parent ),
+ self=P("self::")*Cc(register_self ),
+ root=P('root::')*Cc(register_root ),
+ ancestor=P('ancestor::')*Cc(register_ancestor ),
+ descendant_or_self=P('descendant-or-self::')*Cc(register_descendant_or_self ),
+ ancestor_or_self=P('ancestor-or-self::')*Cc(register_ancestor_or_self ),
+ following=P('following::')*Cc(register_following ),
+ following_sibling=P('following-sibling::')*Cc(register_following_sibling ),
+ preceding=P('preceding::')*Cc(register_preceding ),
+ preceding_sibling=P('preceding-sibling::')*Cc(register_preceding_sibling ),
+ reverse_sibling=P('reverse-sibling::')*Cc(register_reverse_sibling ),
+ nodes=(V("nodefunction")*spaces*P("(")*V("nodeset")*P(")")+V("nodetest")*V("nodeset"))/register_nodes,
+ expressions=expression/register_expression,
+ letters=R("az")^1,
+ name=(1-S("/[]()|:*!"))^1,
+ negate=P("!")*Cc(false),
+ nodefunction=V("negate")+P("not")*Cc(false)+Cc(true),
+ nodetest=V("negate")+Cc(true),
+ nodename=(V("negate")+Cc(true))*spaces*((V("wildnodename")*P(":")*V("wildnodename"))+(Cc(false)*V("wildnodename"))),
+ wildnodename=(C(V("name"))+P("*")*Cc(false))*no_nextlparent,
+ nodeset=spaces*Ct(V("nodename")*(spaces*P("|")*spaces*V("nodename"))^0)*spaces,
+ finalizer=(Cb("protocol")*P("/")^-1*C(V("name"))*arguments*P(-1))/register_finalizer,
}
-
--- the tag is kind of generic and used for functions that are not
--- bound to a variable, like node.new, node.copy etc (contrary to for instance
--- node.has_attribute which is bound to a has_attribute local variable in mkiv)
-
-local debug = require "debug"
-
-local getinfo = debug.getinfo
-local type, next, tostring = type, next, tostring
-local format, find = string.format, string.find
-local is_boolean = string.is_boolean
-
-utilities = utilities or { }
-utilities.debugger = utilities.debugger or { }
-local debugger = utilities.debugger
-
-local counters = { }
-local names = { }
-
--- one
-
-local function hook()
- local f = getinfo(2) -- "nS"
- if f then
- local n = "unknown"
- if f.what == "C" then
- n = f.name or ''
- if not names[n] then
- names[n] = format("%42s",n)
- end
- else
- -- source short_src linedefined what name namewhat nups func
- n = f.name or f.namewhat or f.what
- if not n or n == "" then
- n = "?"
- end
- if not names[n] then
- names[n] = format("%42s : % 5i : %s",n,f.linedefined or 0,f.short_src or "unknown source")
- end
- end
- counters[n] = (counters[n] or 0) + 1
- end
-end
-
-function debugger.showstats(printer,threshold) -- hm, something has changed, rubish now
- printer = printer or texio.write or print
- threshold = threshold or 0
- local total, grandtotal, functions = 0, 0, 0
- local dataset = { }
- for name, count in next, counters do
- dataset[#dataset+1] = { name, count }
- end
- table.sort(dataset,function(a,b) return a[2] == b[2] and b[1] > a[1] or a[2] > b[2] end)
- for i=1,#dataset do
- local d = dataset[i]
- local name = d[1]
- local count = d[2]
- if count > threshold and not find(name,"for generator") then -- move up
- printer(format("%8i %s\n", count, names[name]))
- total = total + count
- end
- grandtotal = grandtotal + count
- functions = functions + 1
- end
- printer("\n")
- printer(format("functions : % 10i\n", functions))
- printer(format("total : % 10i\n", total))
- printer(format("grand total: % 10i\n", grandtotal))
- printer(format("threshold : % 10i\n", threshold))
+xmlpatterns.pathparser=pathparser
+local cache={}
+local function nodesettostring(set,nodetest)
+ local t={}
+ for i=1,#set,3 do
+ local directive,ns,tg=set[i],set[i+1],set[i+2]
+ if not ns or ns=="" then ns="*" end
+ if not tg or tg=="" then tg="*" end
+ tg=(tg=="@rt@" and "[root]") or format("%s:%s",ns,tg)
+ t[i]=(directive and tg) or format("not(%s)",tg)
+ end
+ if nodetest==false then
+ return format("not(%s)",concat(t,"|"))
+ else
+ return concat(t,"|")
+ end
end
-
-function debugger.savestats(filename,threshold)
- local f = io.open(filename,'w')
- if f then
- debugger.showstats(function(str) f:write(str) end,threshold)
- f:close()
- end
-end
-
-function debugger.enable()
- debug.sethook(hook,"c")
-end
-
-function debugger.disable()
- debug.sethook()
-end
-
-
-
-
-
-local is_node = node and node.is_node
-local is_lpeg = lpeg and lpeg.type
-
-function inspect(i) -- global function
- local ti = type(i)
- if ti == "table" then
- table.print(i,"table")
- elseif is_node and is_node(i) then
- table.print(nodes.astable(i),tostring(i))
- elseif is_lpeg and is_lpeg(i) then
- lpeg.print(i)
- else
- print(tostring(i))
- end
-end
-
--- from the lua book:
-
-function traceback()
- local level = 1
- while true do
- local info = debug.getinfo(level, "Sl")
- if not info then
- break
- elseif info.what == "C" then
- print(format("%3i : C function",level))
- else
- print(format("%3i : [%s]:%d",level,info.short_src,info.currentline))
- end
- level = level + 1
- end
-end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['trac-inf'] = {
- version = 1.001,
- comment = "companion to trac-inf.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- As we want to protect the global tables, we no longer store the timing
--- in the tables themselves but in a hidden timers table so that we don't
--- get warnings about assignments. This is more efficient than using rawset
--- and rawget.
-
-local format, lower = string.format, string.lower
-local clock = os.gettimeofday or os.clock -- should go in environment
-local write_nl = texio.write_nl
-
-statistics = statistics or { }
-local statistics = statistics
-
-statistics.enable = true
-statistics.threshold = 0.05
-
-local statusinfo, n, registered, timers = { }, 0, { }, { }
-
-local function hastiming(instance)
- return instance and timers[instance]
-end
-
-local function resettiming(instance)
- timers[instance or "notimer"] = { timing = 0, loadtime = 0 }
-end
-
-local function starttiming(instance)
- local timer = timers[instance or "notimer"]
- if not timer then
- timer = { }
- timers[instance or "notimer"] = timer
- end
- local it = timer.timing
- if not it then
- it = 0
- end
- if it == 0 then
- timer.starttime = clock()
- if not timer.loadtime then
- timer.loadtime = 0
- end
- end
- timer.timing = it + 1
-end
-
-local function stoptiming(instance, report)
- local timer = timers[instance or "notimer"]
- local it = timer.timing
- if it > 1 then
- timer.timing = it - 1
- else
- local starttime = timer.starttime
- if starttime then
- local stoptime = clock()
- local loadtime = stoptime - starttime
- timer.stoptime = stoptime
- timer.loadtime = timer.loadtime + loadtime
- if report then
- statistics.report("load time %0.3f",loadtime)
- end
- timer.timing = 0
- return loadtime
- end
- end
- return 0
-end
-
-local function elapsedtime(instance)
- local timer = timers[instance or "notimer"]
- return format("%0.3f",timer and timer.loadtime or 0)
-end
-
-local function elapsedindeed(instance)
- local timer = timers[instance or "notimer"]
- return (timer and timer.loadtime or 0) > statistics.threshold
-end
-
-local function elapsedseconds(instance,rest) -- returns nil if 0 seconds
- if elapsedindeed(instance) then
- return format("%s seconds %s", elapsedtime(instance),rest or "")
- end
-end
-
-statistics.hastiming = hastiming
-statistics.resettiming = resettiming
-statistics.starttiming = starttiming
-statistics.stoptiming = stoptiming
-statistics.elapsedtime = elapsedtime
-statistics.elapsedindeed = elapsedindeed
-statistics.elapsedseconds = elapsedseconds
-
--- general function
-
-function statistics.register(tag,fnc)
- if statistics.enable and type(fnc) == "function" then
- local rt = registered[tag] or (#statusinfo + 1)
- statusinfo[rt] = { tag, fnc }
- registered[tag] = rt
- if #tag > n then n = #tag end
- end
-end
-
-function statistics.show(reporter)
- if statistics.enable then
- if not reporter then reporter = function(tag,data,n) write_nl(tag .. " " .. data) end end
- -- this code will move
- local register = statistics.register
- register("luatex banner", function()
- return lower(status.banner)
- end)
- register("control sequences", function()
- return format("%s of %s + %s", status.cs_count, status.hash_size,status.hash_extra)
- end)
- register("callbacks", function()
- local total, indirect = status.callbacks or 0, status.indirect_callbacks or 0
- return format("%s direct, %s indirect, %s total", total-indirect, indirect, total)
- end)
- collectgarbage("collect")
- register("current memory usage", statistics.memused)
- register("runtime",statistics.runtime)
- for i=1,#statusinfo do
- local s = statusinfo[i]
- local r = s[2]()
- if r then
- reporter(s[1],r,n)
- end
- end
- write_nl("") -- final newline
- statistics.enable = false
- end
-end
-
-local template, report_statistics, nn = nil, nil, 0 -- we only calcute it once
-
-function statistics.showjobstat(tag,data,n)
- if not logs then
- -- sorry
- elseif type(data) == "table" then
- for i=1,#data do
- statistics.showjobstat(tag,data[i],n)
- end
- else
- if not template or n > nn then
- template, n = format("%%-%ss - %%s",n), nn
- report_statistics = logs.reporter("mkiv lua stats")
- end
- report_statistics(format(template,tag,data))
- end
-end
-
-function statistics.memused() -- no math.round yet -)
- local round = math.round or math.floor
- return format("%s MB (ctx: %s MB)",round(collectgarbage("count")/1000), round(status.luastate_bytes/1000000))
-end
-
-starttiming(statistics)
-
-function statistics.formatruntime(runtime) -- indirect so it can be overloaded and
- return format("%s seconds", runtime) -- indeed that happens in cure-uti.lua
-end
-
-function statistics.runtime()
- stoptiming(statistics)
- return statistics.formatruntime(elapsedtime(statistics))
-end
-
-function statistics.timed(action,report)
- report = report or logs.reporter("system")
- starttiming("run")
- action()
- stoptiming("run")
- report("total runtime: %s",elapsedtime("run"))
-end
-
--- where, not really the best spot for this:
-
-commands = commands or { }
-
-function commands.resettimer(name)
- resettiming(name or "whatever")
- starttiming(name or "whatever")
-end
-
-function commands.elapsedtime(name)
- stoptiming(name or "whatever")
- context(elapsedtime(name or "whatever"))
-end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['trac-set'] = { -- might become util-set.lua
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local type, next, tostring = type, next, tostring
-local concat = table.concat
-local format, find, lower, gsub, escapedpattern = string.format, string.find, string.lower, string.gsub, string.escapedpattern
-local is_boolean = string.is_boolean
-local settings_to_hash = utilities.parsers.settings_to_hash
-local allocate = utilities.storage.allocate
-
-utilities = utilities or { }
-local utilities = utilities
-utilities.setters = utilities.setters or { }
-local setters = utilities.setters
-
-local data = { } -- maybe just local
-
--- We can initialize from the cnf file. This is sort of tricky as
--- later defined setters also need to be initialized then. If set
--- this way, we need to ensure that they are not reset later on.
-
-local trace_initialize = false -- only for testing during development
-
-function setters.initialize(filename,name,values) -- filename only for diagnostics
- local setter = data[name]
- if setter then
- local data = setter.data
- if data then
- for key, value in next, values do
- -- key = gsub(key,"_",".")
- value = is_boolean(value,value)
- local functions = data[key]
- if functions then
- if #functions > 0 and not functions.value then
- if trace_initialize then
- setter.report("executing %s (%s -> %s)",key,filename,tostring(value))
- end
- for i=1,#functions do
- functions[i](value)
- end
- functions.value = value
- else
- if trace_initialize then
- setter.report("skipping %s (%s -> %s)",key,filename,tostring(value))
- end
- end
- else
- -- we do a simple preregistration i.e. not in the
- -- list as it might be an obsolete entry
- functions = { default = value }
- data[key] = functions
- if trace_initialize then
- setter.report("storing %s (%s -> %s)",key,filename,tostring(value))
- end
- end
- end
- return true
- end
- end
-end
-
--- user interface code
-
-local function set(t,what,newvalue)
- local data, done = t.data, t.done
- if type(what) == "string" then
- what = settings_to_hash(what) -- inefficient but ok
- end
- if type(what) ~= "table" then
- return
- end
- if not done then -- catch ... why not set?
- done = { }
- t.done = done
- end
- for w, value in next, what do
- if value == "" then
- value = newvalue
- elseif not value then
- value = false -- catch nil
- else
- value = is_boolean(value,value)
- end
- w = "^" .. escapedpattern(w,true) .. "$" -- new: anchored
- for name, functions in next, data do
- if done[name] then
- -- prevent recursion due to wildcards
- elseif find(name,w) then
- done[name] = true
- for i=1,#functions do
- functions[i](value)
- end
- functions.value = value
- end
- end
- end
-end
-
-local function reset(t)
- for name, functions in next, t.data do
- for i=1,#functions do
- functions[i](false)
- end
- functions.value = false
- end
-end
-
-local function enable(t,what)
- set(t,what,true)
-end
-
-local function disable(t,what)
- local data = t.data
- if not what or what == "" then
- t.done = { }
- reset(t)
- else
- set(t,what,false)
- end
-end
-
-function setters.register(t,what,...)
- local data = t.data
- what = lower(what)
- local functions = data[what]
- if not functions then
- functions = { }
- data[what] = functions
- if trace_initialize then
- t.report("defining %s",what)
- end
- end
- local default = functions.default -- can be set from cnf file
- for _, fnc in next, { ... } do
- local typ = type(fnc)
- if typ == "string" then
- if trace_initialize then
- t.report("coupling %s to %s",what,fnc)
- end
- local s = fnc -- else wrong reference
- fnc = function(value) set(t,s,value) end
- elseif typ ~= "function" then
- fnc = nil
- end
- if fnc then
- functions[#functions+1] = fnc
- -- default: set at command line or in cnf file
- -- value : set in tex run (needed when loading runtime)
- local value = functions.value or default
- if value ~= nil then
- fnc(value)
- functions.value = value
- end
- end
- end
- return false -- so we can use it in an assignment
-end
-
-function setters.enable(t,what)
- local e = t.enable
- t.enable, t.done = enable, { }
- enable(t,what)
- t.enable, t.done = e, { }
-end
-
-function setters.disable(t,what)
- local e = t.disable
- t.disable, t.done = disable, { }
- disable(t,what)
- t.disable, t.done = e, { }
-end
-
-function setters.reset(t)
- t.done = { }
- reset(t)
-end
-
-function setters.list(t) -- pattern
- local list = table.sortedkeys(t.data)
- local user, system = { }, { }
- for l=1,#list do
- local what = list[l]
- if find(what,"^%*") then
- system[#system+1] = what
- else
- user[#user+1] = what
- end
- end
- return user, system
-end
-
-function setters.show(t)
- local category = t.name
- local list = setters.list(t)
- t.report()
- for k=1,#list do
- local name = list[k]
- local functions = t.data[name]
- if functions then
- local value, default, modules = functions.value, functions.default, #functions
- value = value == nil and "unset" or tostring(value)
- default = default == nil and "unset" or tostring(default)
- t.report("%-30s modules: %2i default: %6s value: %6s",name,modules,default,value)
- end
- end
- t.report()
-end
-
--- we could have used a bit of oo and the trackers:enable syntax but
--- there is already a lot of code around using the singular tracker
-
--- we could make this into a module but we also want the rest avaliable
-
-local enable, disable, register, list, show = setters.enable, setters.disable, setters.register, setters.list, setters.show
-
-local function report(setter,...)
- local report = logs and logs.report
- if report then
- report(setter.name,...)
- else -- fallback, as this module is loaded before the logger
- write_nl(format("%-15s : %s\n",setter.name,format(...)))
- end
-end
-
-function setters.new(name)
- local setter -- we need to access it in setter itself
- setter = {
- data = allocate(), -- indexed, but also default and value fields
- name = name,
- report = function(...) report (setter,...) end,
- enable = function(...) enable (setter,...) end,
- disable = function(...) disable (setter,...) end,
- register = function(...) register(setter,...) end,
- list = function(...) list (setter,...) end,
- show = function(...) show (setter,...) end,
- }
- data[name] = setter
- return setter
-end
-
-trackers = setters.new("trackers")
-directives = setters.new("directives")
-experiments = setters.new("experiments")
-
-local t_enable, t_disable, t_report = trackers .enable, trackers .disable, trackers .report
-local d_enable, d_disable, d_report = directives .enable, directives .disable, directives .report
-local e_enable, e_disable, e_report = experiments.enable, experiments.disable, experiments.report
-
--- nice trick: we overload two of the directives related functions with variants that
--- do tracing (itself using a tracker) .. proof of concept
-
-local trace_directives = false local trace_directives = false trackers.register("system.directives", function(v) trace_directives = v end)
-local trace_experiments = false local trace_experiments = false trackers.register("system.experiments", function(v) trace_experiments = v end)
-
-function directives.enable(...)
- if trace_directives then
- d_report("enabling: %s",concat({...}," "))
- end
- d_enable(...)
-end
-
-function directives.disable(...)
- if trace_directives then
- d_report("disabling: %s",concat({...}," "))
- end
- d_disable(...)
-end
-
-function experiments.enable(...)
- if trace_experiments then
- e_report("enabling: %s",concat({...}," "))
- end
- e_enable(...)
-end
-
-function experiments.disable(...)
- if trace_experiments then
- e_report("disabling: %s",concat({...}," "))
- end
- e_disable(...)
-end
-
--- a useful example
-
-directives.register("system.nostatistics", function(v)
- statistics.enable = not v
-end)
-
-directives.register("system.nolibraries", function(v)
- libraries = nil -- we discard this tracing for security
-end)
-
--- experiment
-
-local flags = environment and environment.engineflags
-
-if flags then
- if trackers and flags.trackers then
- setters.initialize("flags","trackers", settings_to_hash(flags.trackers))
- -- t_enable(flags.trackers)
- end
- if directives and flags.directives then
- setters.initialize("flags","directives", settings_to_hash(flags.directives))
- -- d_enable(flags.directives)
- end
-end
-
--- here
-
-if texconfig then
-
- -- this happens too late in ini mode but that is no problem
-
- local function set(k,v)
- v = tonumber(v)
- if v then
- texconfig[k] = v
- end
- end
-
- directives.register("luatex.expanddepth", function(v) set("expand_depth",v) end)
- directives.register("luatex.hashextra", function(v) set("hash_extra",v) end)
- directives.register("luatex.nestsize", function(v) set("nest_size",v) end)
- directives.register("luatex.maxinopen", function(v) set("max_in_open",v) end)
- directives.register("luatex.maxprintline", function(v) set("max_print_line",v) end)
- directives.register("luatex.maxstrings", function(v) set("max_strings",v) end)
- directives.register("luatex.paramsize", function(v) set("param_size",v) end)
- directives.register("luatex.savesize", function(v) set("save_size",v) end)
- directives.register("luatex.stacksize", function(v) set("stack_size",v) end)
-
-end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['trac-log'] = {
- version = 1.001,
- comment = "companion to trac-log.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- todo: less categories, more subcategories (e.g. nodes)
-
-
-local write_nl, write = texio and texio.write_nl or print, texio and texio.write or io.write
-local format, gmatch, find = string.format, string.gmatch, string.find
-local concat, insert, remove = table.concat, table.insert, table.remove
-local escapedpattern = string.escapedpattern
-local texcount = tex and tex.count
-local next, type = next, type
-
-local setmetatableindex = table.setmetatableindex
-
---[[ldx--
-This is a prelude to a more extensive logging module. We no longer
-provide based logging a sparsing is relatively easy anyway.
---ldx]]--
-
-logs = logs or { }
-local logs = logs
-
-local moreinfo = [[
-More information about ConTeXt and the tools that come with it can be found at:
-
-maillist : ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
-webpage : http://www.pragma-ade.nl / http://tex.aanhet.net
-wiki : http://contextgarden.net
-]]
-
--- basic loggers
-
-local function ignore() end
-
-setmetatableindex(logs, function(t,k) t[k] = ignore ; return ignore end)
-
-local report, subreport, status, settarget, setformats, settranslations
-
-local direct, subdirect, writer, pushtarget, poptarget
-
-if tex and (tex.jobname or tex.formatname) then
-
- local valueiskey = { __index = function(t,k) t[k] = k return k end } -- will be helper
-
- local target = "term and log"
-
- logs.flush = io.flush
-
- local formats = { } setmetatable(formats, valueiskey)
- local translations = { } setmetatable(translations,valueiskey)
-
- writer = function(...)
- write_nl(target,...)
- end
-
- newline = function()
- write_nl(target,"\n")
- end
-
- report = function(a,b,c,...)
- if c then
- write_nl(target,format("%-15s > %s\n",translations[a],format(formats[b],c,...)))
- elseif b then
- write_nl(target,format("%-15s > %s\n",translations[a],formats[b]))
- elseif a then
- write_nl(target,format("%-15s >\n", translations[a]))
- else
- write_nl(target,"\n")
- end
- end
-
- direct = function(a,b,c,...)
- if c then
- return format("%-15s > %s",translations[a],format(formats[b],c,...))
- elseif b then
- return format("%-15s > %s",translations[a],formats[b])
- elseif a then
- return format("%-15s >", translations[a])
- else
- return ""
- end
- end
-
- subreport = function(a,s,b,c,...)
- if c then
- write_nl(target,format("%-15s > %s > %s\n",translations[a],translations[s],format(formats[b],c,...)))
- elseif b then
- write_nl(target,format("%-15s > %s > %s\n",translations[a],translations[s],formats[b]))
- elseif a then
- write_nl(target,format("%-15s > %s >\n", translations[a],translations[s]))
- else
- write_nl(target,"\n")
- end
- end
-
- subdirect = function(a,s,b,c,...)
- if c then
- return format("%-15s > %s > %s",translations[a],translations[s],format(formats[b],c,...))
- elseif b then
- return format("%-15s > %s > %s",translations[a],translations[s],formats[b])
- elseif a then
- return format("%-15s > %s >", translations[a],translations[s])
- else
- return ""
- end
- end
-
- status = function(a,b,c,...)
- if c then
- write_nl(target,format("%-15s : %s\n",translations[a],format(formats[b],c,...)))
- elseif b then
- write_nl(target,format("%-15s : %s\n",translations[a],formats[b]))
- elseif a then
- write_nl(target,format("%-15s :\n", translations[a]))
- else
- write_nl(target,"\n")
- end
- end
-
- local targets = {
- logfile = "log",
- log = "log",
- file = "log",
- console = "term",
- terminal = "term",
- both = "term and log",
- }
-
- settarget = function(whereto)
- target = targets[whereto or "both"] or targets.both
- if target == "term" or target == "term and log" then
- logs.flush = io.flush
- else
- logs.flush = ignore
- end
- end
-
- local stack = { }
-
- pushtarget = function(newtarget)
- insert(stack,target)
- settarget(newtarget)
- end
-
- poptarget = function()
- if #stack > 0 then
- settarget(remove(stack))
- end
- end
-
- setformats = function(f)
- formats = f
- end
-
- settranslations = function(t)
- translations = t
- end
-
-else
-
- logs.flush = ignore
-
- writer = write_nl
-
- newline = function()
- write_nl("\n")
- end
-
- report = function(a,b,c,...)
- if c then
- write_nl(format("%-15s | %s",a,format(b,c,...)))
- elseif b then
- write_nl(format("%-15s | %s",a,b))
- elseif a then
- write_nl(format("%-15s |", a))
- else
- write_nl("")
- end
- end
-
- subreport = function(a,sub,b,c,...)
- if c then
- write_nl(format("%-15s | %s | %s",a,sub,format(b,c,...)))
- elseif b then
- write_nl(format("%-15s | %s | %s",a,sub,b))
- elseif a then
- write_nl(format("%-15s | %s |", a,sub))
- else
- write_nl("")
- end
- end
-
- status = function(a,b,c,...) -- not to be used in lua anyway
- if c then
- write_nl(format("%-15s : %s\n",a,format(b,c,...)))
- elseif b then
- write_nl(format("%-15s : %s\n",a,b)) -- b can have %'s
- elseif a then
- write_nl(format("%-15s :\n", a))
- else
- write_nl("\n")
- end
- end
-
- direct = ignore
- subdirect = ignore
-
- settarget = ignore
- pushtarget = ignore
- poptarget = ignore
- setformats = ignore
- settranslations = ignore
-
-end
-
-logs.report = report
-logs.subreport = subreport
-logs.status = status
-logs.settarget = settarget
-logs.pushtarget = pushtarget
-logs.poptarget = poptarget
-logs.setformats = setformats
-logs.settranslations = settranslations
-
-logs.direct = direct
-logs.subdirect = subdirect
-logs.writer = writer
-logs.newline = newline
-
--- installer
-
--- todo: renew (un) locks when a new one is added and wildcard
-
-local data, states = { }, nil
-
-function logs.reporter(category,subcategory)
- local logger = data[category]
- if not logger then
- local state = false
- if states == true then
- state = true
- elseif type(states) == "table" then
- for c, _ in next, states do
- if find(category,c) then
- state = true
- break
- end
- end
- end
- logger = {
- reporters = { },
- state = state,
- }
- data[category] = logger
- end
- local reporter = logger.reporters[subcategory or "default"]
- if not reporter then
- if subcategory then
- reporter = function(...)
- if not logger.state then
- subreport(category,subcategory,...)
- end
- end
- logger.reporters[subcategory] = reporter
- else
- local tag = category
- reporter = function(...)
- if not logger.state then
- report(category,...)
- end
- end
- logger.reporters.default = reporter
- end
- end
- return reporter
-end
-
-logs.new = logs.reporter -- for old times sake
-
--- context specicific: this ends up in the macro stream
-
-local ctxreport = logs.writer
-
-function logs.setmessenger(m)
- ctxreport = m
-end
-
-function logs.messenger(category,subcategory)
- -- we need to avoid catcode mess (todo: fast context)
- if subcategory then
- return function(...)
- ctxreport(subdirect(category,subcategory,...))
- end
- else
- return function(...)
- ctxreport(direct(category,...))
- end
- end
-end
-
--- so far
-
-local function setblocked(category,value)
- if category == true then
- -- lock all
- category, value = "*", true
- elseif category == false then
- -- unlock all
- category, value = "*", false
- elseif value == nil then
- -- lock selective
- value = true
- end
- if category == "*" then
- states = value
- for k, v in next, data do
- v.state = value
- end
- else
- states = utilities.parsers.settings_to_hash(category)
- for c, _ in next, states do
- if data[c] then
- v.state = value
- else
- c = escapedpattern(c,true)
- for k, v in next, data do
- if find(k,c) then
- v.state = value
- end
- end
- end
- end
- end
-end
-
-function logs.disable(category,value)
- setblocked(category,value == nil and true or value)
-end
-
-function logs.enable(category)
- setblocked(category,false)
-end
-
-function logs.categories()
- return table.sortedkeys(data)
-end
-
-function logs.show()
- local n, c, s, max = 0, 0, 0, 0
- for category, v in table.sortedpairs(data) do
- n = n + 1
- local state = v.state
- local reporters = v.reporters
- local nc = #category
- if nc > c then
- c = nc
- end
- for subcategory, _ in next, reporters do
- local ns = #subcategory
- if ns > c then
- s = ns
- end
- local m = nc + ns
- if m > max then
- max = m
- end
- end
- local subcategories = concat(table.sortedkeys(reporters),", ")
- if state == true then
- state = "disabled"
- elseif state == false then
- state = "enabled"
- else
- state = "unknown"
- end
- -- no new here
- report("logging","category: '%s', subcategories: '%s', state: '%s'",category,subcategories,state)
- end
- report("logging","categories: %s, max category: %s, max subcategory: %s, max combined: %s",n,c,s,max)
-end
-
-directives.register("logs.blocked", function(v)
- setblocked(v,true)
-end)
-
-directives.register("logs.target", function(v)
- settarget(v)
-end)
-
--- tex specific loggers (might move elsewhere)
-
-local report_pages = logs.reporter("pages") -- not needed but saves checking when we grep for it
-
-local real, user, sub
-
-function logs.start_page_number()
- real, user, sub = texcount.realpageno, texcount.userpageno, texcount.subpageno
--- real, user, sub = 0, 0, 0
-end
-
-local timing = false
-local starttime = nil
-local lasttime = nil
-
-trackers.register("pages.timing", function(v) -- only for myself (diagnostics)
- starttime = os.clock()
- timing = true
-end)
-
-function logs.stop_page_number() -- the first page can includes the initialization so we omit this in average
- if timing then
- local elapsed, average
- local stoptime = os.clock()
- if not lasttime or real < 2 then
- elapsed = stoptime
- average = stoptime
- starttime = stoptime
- else
- elapsed = stoptime - lasttime
- average = (stoptime - starttime) / (real - 1)
- end
- lasttime = stoptime
- if real > 0 then
- if user > 0 then
- if sub > 0 then
- report_pages("flushing realpage %s, userpage %s, subpage %s, time %0.04f / %0.04f",real,user,sub,elapsed,average)
- else
- report_pages("flushing realpage %s, userpage %s, time %0.04f / %0.04f",real,user,elapsed,average)
- end
- else
- report_pages("flushing realpage %s, time %0.04f / %0.04f",real,elapsed,average)
- end
- else
- report_pages("flushing page, time %0.04f / %0.04f",elapsed,average)
- end
- else
- if real > 0 then
- if user > 0 then
- if sub > 0 then
- report_pages("flushing realpage %s, userpage %s, subpage %s",real,user,sub)
- else
- report_pages("flushing realpage %s, userpage %s",real,user)
- end
- else
- report_pages("flushing realpage %s",real)
- end
- else
- report_pages("flushing page")
- end
- end
- logs.flush()
-end
-
-logs.report_job_stat = statistics and statistics.showjobstat
-
-local report_files = logs.reporter("files")
-
-local nesting = 0
-local verbose = false
-local hasscheme = url.hasscheme
-
--- we don't have show_open and show_close callbacks yet
-
-function logs.show_open(name)
- -- if hasscheme(name) ~= "virtual" then
- -- if verbose then
- -- nesting = nesting + 1
- -- report_files("level %s, opening %s",nesting,name)
- -- else
- -- write(format("(%s",name)) -- tex adds a space
- -- end
- -- end
-end
-
-function logs.show_close(name)
- -- if hasscheme(name) ~= "virtual" then
- -- if verbose then
- -- report_files("level %s, closing %s",nesting,name)
- -- nesting = nesting - 1
- -- else
- -- write(")") -- tex adds a space
- -- end
- -- end
-end
-
-function logs.show_load(name)
- -- if hasscheme(name) ~= "virtual" then
- -- if verbose then
- -- report_files("level %s, loading %s",nesting+1,name)
- -- else
- -- write(format("(%s)",name))
- -- end
- -- end
-end
-
--- there may be scripts out there using this:
-
-local simple = logs.reporter("comment")
-
-logs.simple = simple
-logs.simpleline = simple
-
--- obsolete
-
-function logs.setprogram () end -- obsolete
-function logs.extendbanner() end -- obsolete
-function logs.reportlines () end -- obsolete
-function logs.reportbanner() end -- obsolete
-function logs.reportline () end -- obsolete
-function logs.simplelines () end -- obsolete
-function logs.help () end -- obsolete
-
--- applications
-
-local function reportlines(t,str)
- if str then
- for line in gmatch(str,"(.-)[\n\r]") do
- t.report(line)
- end
- end
-end
-
-local function reportbanner(t)
- local banner = t.banner
- if banner then
- t.report(banner)
- t.report()
- end
-end
-
-local function reportversion(t)
- local banner = t.banner
- if banner then
- t.report(banner)
- end
-end
-
-local function reporthelp(t,...)
- local helpinfo = t.helpinfo
- if type(helpinfo) == "string" then
- reportlines(t,helpinfo)
- elseif type(helpinfo) == "table" then
- local tags = { ... }
- for i=1,#tags do
- reportlines(t,t.helpinfo[tags[i]])
- if i < #tags then
- t.report()
- end
- end
- end
-end
-
-local function reportinfo(t)
- t.report()
- reportlines(t,moreinfo)
-end
-
-function logs.application(t)
- t.name = t.name or "unknown"
- t.banner = t.banner
- t.report = logs.reporter(t.name)
- t.help = function(...) reportbanner(t) ; reporthelp(t,...) ; reportinfo(t) end
- t.identify = function() reportbanner(t) end
- t.version = function() reportversion(t) end
- return t
-end
-
--- somewhat special
-
--- logging to a file
-
-
-function logs.system(whereto,process,jobname,category,...)
- local message = format("%s %s => %s => %s => %s\r",os.date("%d/%m/%y %H:%m:%S"),process,jobname,category,format(...))
- for i=1,10 do
- local f = io.open(whereto,"a") -- we can consider keepint the file open
- if f then
- f:write(message)
- f:close()
- break
- else
- sleep(0.1)
- end
- end
-end
-
-local report_system = logs.reporter("system","logs")
-
-function logs.obsolete(old,new)
- local o = loadstring("return " .. new)()
- if type(o) == "function" then
- return function(...)
- report_system("function %s is obsolete, use %s",old,new)
- loadstring(old .. "=" .. new .. " return ".. old)()(...)
- end
- elseif type(o) == "table" then
- local t, m = { }, { }
- m.__index = function(t,k)
- report_system("table %s is obsolete, use %s",old,new)
- m.__index, m.__newindex = o, o
- return o[k]
- end
- m.__newindex = function(t,k,v)
- report_system("table %s is obsolete, use %s",old,new)
- m.__index, m.__newindex = o, o
- o[k] = v
- end
- if libraries then
- libraries.obsolete[old] = t -- true
- end
- setmetatable(t,m)
- return t
- end
-end
-
-if utilities then
- utilities.report = report_system
-end
-
-if tex and tex.error then
- function logs.texerrormessage(...) -- for the moment we put this function here
- tex.error(format(...), { })
- end
-else
- function logs.texerrormessage(...)
- print(format(...))
- end
-end
-
--- do we still need io.flush then?
-
-io.stdout:setvbuf('no')
-io.stderr:setvbuf('no')
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['trac-pro'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local getmetatable, setmetatable, rawset, type = getmetatable, setmetatable, rawset, type
-
--- The protection implemented here is probably not that tight but good enough to catch
--- problems due to naive usage.
---
--- There's a more extensive version (trac-xxx.lua) that supports nesting.
---
--- This will change when we have _ENV in lua 5.2+
-
-local trace_namespaces = false trackers.register("system.namespaces", function(v) trace_namespaces = v end)
-
-local report_system = logs.reporter("system","protection")
-
-namespaces = namespaces or { }
-local namespaces = namespaces
-
-local registered = { }
-
-local function report_index(k,name)
- if trace_namespaces then
- report_system("reference to '%s' in protected namespace '%s', %s",k,name,debug.traceback())
- else
- report_system("reference to '%s' in protected namespace '%s'",k,name)
- end
-end
-
-local function report_newindex(k,name)
- if trace_namespaces then
- report_system("assignment to '%s' in protected namespace '%s', %s",k,name,debug.traceback())
- else
- report_system("assignment to '%s' in protected namespace '%s'",k,name)
- end
-end
-
-local function register(name)
- local data = name == "global" and _G or _G[name]
- if not data then
- return -- error
- end
- registered[name] = data
- local m = getmetatable(data)
- if not m then
- m = { }
- setmetatable(data,m)
- end
- local index, newindex = { }, { }
- m.__saved__index = m.__index
- m.__no__index = function(t,k)
- if not index[k] then
- index[k] = true
- report_index(k,name)
- end
- return nil
- end
- m.__saved__newindex = m.__newindex
- m.__no__newindex = function(t,k,v)
- if not newindex[k] then
- newindex[k] = true
- report_newindex(k,name)
- end
- rawset(t,k,v)
- end
- m.__protection__depth = 0
-end
-
-local function private(name) -- maybe save name
- local data = registered[name]
- if not data then
- data = _G[name]
- if not data then
- data = { }
- _G[name] = data
- end
- register(name)
- end
- return data
-end
-
-local function protect(name)
- local data = registered[name]
- if not data then
- return
- end
- local m = getmetatable(data)
- local pd = m.__protection__depth
- if pd > 0 then
- m.__protection__depth = pd + 1
- else
- m.__save_d_index, m.__saved__newindex = m.__index, m.__newindex
- m.__index, m.__newindex = m.__no__index, m.__no__newindex
- m.__protection__depth = 1
- end
-end
-
-local function unprotect(name)
- local data = registered[name]
- if not data then
- return
- end
- local m = getmetatable(data)
- local pd = m.__protection__depth
- if pd > 1 then
- m.__protection__depth = pd - 1
- else
- m.__index, m.__newindex = m.__saved__index, m.__saved__newindex
- m.__protection__depth = 0
- end
-end
-
-local function protectall()
- for name, _ in next, registered do
- if name ~= "global" then
- protect(name)
- end
- end
-end
-
-local function unprotectall()
- for name, _ in next, registered do
- if name ~= "global" then
- unprotect(name)
- end
- end
-end
-
-namespaces.register = register -- register when defined
-namespaces.private = private -- allocate and register if needed
-namespaces.protect = protect
-namespaces.unprotect = unprotect
-namespaces.protectall = protectall
-namespaces.unprotectall = unprotectall
-
-namespaces.private("namespaces") registered = { } register("global") -- unreachable
-
-directives.register("system.protect", function(v)
- if v then
- protectall()
- else
- unprotectall()
- end
-end)
-
-directives.register("system.checkglobals", function(v)
- if v then
- report_system("enabling global namespace guard")
- protect("global")
- else
- report_system("disabling global namespace guard")
- unprotect("global")
- end
-end)
-
--- dummy section (will go to luat-dum.lua)
-
-
-
-
-
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['luat-env'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- A former version provided functionality for non embeded core
--- scripts i.e. runtime library loading. Given the amount of
--- Lua code we use now, this no longer makes sense. Much of this
--- evolved before bytecode arrays were available and so a lot of
--- code has disappeared already.
-
-local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
-
-local report_lua = logs.reporter("resolvers","lua")
-
-local allocate, mark = utilities.storage.allocate, utilities.storage.mark
-
-local format, sub, match, gsub, find = string.format, string.sub, string.match, string.gsub, string.find
-local unquoted, quoted = string.unquoted, string.quoted
-local concat = table.concat
-
--- precautions
-
-os.setlocale(nil,nil) -- useless feature and even dangerous in luatex
-
-function os.setlocale()
- -- no way you can mess with it
-end
-
--- dirty tricks
-
-if arg and (arg[0] == 'luatex' or arg[0] == 'luatex.exe') and arg[1] == "--luaonly" then
- arg[-1] = arg[0]
- arg[ 0] = arg[2]
- for k=3,#arg do
- arg[k-2] = arg[k]
- end
- arg[#arg] = nil -- last
- arg[#arg] = nil -- pre-last
-end
-
--- environment
-
-environment = environment or { }
-local environment = environment
-
-environment.arguments = allocate()
-environment.files = allocate()
-environment.sortedflags = nil
-
-local mt = {
- __index = function(_,k)
- if k == "version" then
- local version = tex.toks and tex.toks.contextversiontoks
- if version and version ~= "" then
- rawset(environment,"version",version)
- return version
- else
- return "unknown"
- end
- elseif k == "jobname" or k == "formatname" then
- local name = tex and tex[k]
- if name or name== "" then
- rawset(environment,k,name)
- return name
- else
- return "unknown"
- end
- elseif k == "outputfilename" then
- local name = environment.jobname
- rawset(environment,k,name)
- return name
- end
- end
-}
-
-setmetatable(environment,mt)
-
-function environment.initializearguments(arg)
- local arguments, files = { }, { }
- environment.arguments, environment.files, environment.sortedflags = arguments, files, nil
- for index=1,#arg do
- local argument = arg[index]
- if index > 0 then
- local flag, value = match(argument,"^%-+(.-)=(.-)$")
- if flag then
- arguments[flag] = unquoted(value or "")
- else
- flag = match(argument,"^%-+(.+)")
- if flag then
- arguments[flag] = true
- else
- files[#files+1] = argument
- end
- end
- end
- end
- environment.ownname = environment.ownname or arg[0] or 'unknown.lua'
-end
-
-function environment.setargument(name,value)
- environment.arguments[name] = value
-end
-
--- todo: defaults, better checks e.g on type (boolean versus string)
---
--- tricky: too many hits when we support partials unless we add
--- a registration of arguments so from now on we have 'partial'
-
-function environment.argument(name,partial)
- local arguments, sortedflags = environment.arguments, environment.sortedflags
- if arguments[name] then
- return arguments[name]
- elseif partial then
- if not sortedflags then
- sortedflags = allocate(table.sortedkeys(arguments))
- for k=1,#sortedflags do
- sortedflags[k] = "^" .. sortedflags[k]
- end
- environment.sortedflags = sortedflags
- end
- -- example of potential clash: ^mode ^modefile
- for k=1,#sortedflags do
- local v = sortedflags[k]
- if find(name,v) then
- return arguments[sub(v,2,#v)]
- end
- end
- end
- return nil
-end
-
-function environment.splitarguments(separator) -- rather special, cut-off before separator
- local done, before, after = false, { }, { }
- local originalarguments = environment.originalarguments
- for k=1,#originalarguments do
- local v = originalarguments[k]
- if not done and v == separator then
- done = true
- elseif done then
- after[#after+1] = v
- else
- before[#before+1] = v
- end
- end
- return before, after
-end
-
-function environment.reconstructcommandline(arg,noquote)
- arg = arg or environment.originalarguments
- if noquote and #arg == 1 then
- -- we could just do: return unquoted(resolvers.resolve(arg[i]))
- local a = arg[1]
- a = resolvers.resolve(a)
- a = unquoted(a)
- return a
- elseif #arg > 0 then
- local result = { }
- for i=1,#arg do
- -- we could just do: result[#result+1] = format("%q",unquoted(resolvers.resolve(arg[i])))
- local a = arg[i]
- a = resolvers.resolve(a)
- a = unquoted(a)
- a = gsub(a,'"','\\"') -- tricky
- if find(a," ") then
- result[#result+1] = quoted(a)
- else
- result[#result+1] = a
- end
- end
- return concat(result," ")
- else
- return ""
- end
-end
-
-
-if arg then
-
- -- new, reconstruct quoted snippets (maybe better just remove the " then and add them later)
- local newarg, instring = { }, false
-
- for index=1,#arg do
- local argument = arg[index]
- if find(argument,"^\"") then
- newarg[#newarg+1] = gsub(argument,"^\"","")
- if not find(argument,"\"$") then
- instring = true
- end
- elseif find(argument,"\"$") then
- newarg[#newarg] = newarg[#newarg] .. " " .. gsub(argument,"\"$","")
- instring = false
- elseif instring then
- newarg[#newarg] = newarg[#newarg] .. " " .. argument
- else
- newarg[#newarg+1] = argument
- end
- end
- for i=1,-5,-1 do
- newarg[i] = arg[i]
- end
-
- environment.initializearguments(newarg)
-
- environment.originalarguments = mark(newarg)
- environment.rawarguments = mark(arg)
-
- arg = { } -- prevent duplicate handling
-
-end
-
--- weird place ... depends on a not yet loaded module
-
-function environment.texfile(filename)
- return resolvers.findfile(filename,'tex')
-end
-
-function environment.luafile(filename)
- local resolved = resolvers.findfile(filename,'tex') or ""
- if resolved ~= "" then
- return resolved
- end
- resolved = resolvers.findfile(filename,'texmfscripts') or ""
- if resolved ~= "" then
- return resolved
- end
- return resolvers.findfile(filename,'luatexlibs') or ""
-end
-
-environment.loadedluacode = loadfile -- can be overloaded
-
-function environment.luafilechunk(filename,silent) -- used for loading lua bytecode in the format
- filename = file.replacesuffix(filename, "lua")
- local fullname = environment.luafile(filename)
- if fullname and fullname ~= "" then
- local data = environment.loadedluacode(fullname)
- if trace_locating then
- report_lua("loading file %s%s", fullname, not data and " failed" or "")
- elseif not silent then
- texio.write("<",data and "+ " or "- ",fullname,">")
- end
- return data
- else
- if trace_locating then
- report_lua("unknown file %s", filename)
- end
- return nil
- end
-end
-
--- the next ones can use the previous ones / combine
-
-function environment.loadluafile(filename, version)
- local lucname, luaname, chunk
- local basename = file.removesuffix(filename)
- if basename == filename then
- lucname, luaname = basename .. ".luc", basename .. ".lua"
- else
- lucname, luaname = nil, basename -- forced suffix
- end
- -- when not overloaded by explicit suffix we look for a luc file first
- local fullname = (lucname and environment.luafile(lucname)) or ""
- if fullname ~= "" then
- if trace_locating then
- report_lua("loading %s", fullname)
- end
- chunk = loadfile(fullname) -- this way we don't need a file exists check
- end
- if chunk then
- assert(chunk)()
- if version then
- -- we check of the version number of this chunk matches
- local v = version -- can be nil
- if modules and modules[filename] then
- v = modules[filename].version -- new method
- elseif versions and versions[filename] then
- v = versions[filename] -- old method
- end
- if v == version then
- return true
- else
- if trace_locating then
- report_lua("version mismatch for %s: lua=%s, luc=%s", filename, v, version)
- end
- environment.loadluafile(filename)
- end
- else
- return true
- end
- end
- fullname = (luaname and environment.luafile(luaname)) or ""
- if fullname ~= "" then
- if trace_locating then
- report_lua("loading %s", fullname)
- end
- chunk = loadfile(fullname) -- this way we don't need a file exists check
- if not chunk then
- if trace_locating then
- report_lua("unknown file %s", filename)
- end
- else
- assert(chunk)()
- return true
- end
- end
- return false
-end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['lxml-tab'] = {
- version = 1.001,
- comment = "this module is the basis for the lxml-* ones",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- this module needs a cleanup: check latest lpeg, passing args, (sub)grammar, etc etc
--- stripping spaces from e.g. cont-en.xml saves .2 sec runtime so it's not worth the
--- trouble
-
--- todo: when serializing optionally remap named entities to hex (if known in char-ent.lua)
--- maybe when letter -> utf, else name .. then we need an option to the serializer .. a bit
--- of work so we delay this till we cleanup
-
-local trace_entities = false trackers.register("xml.entities", function(v) trace_entities = v end)
-
-local report_xml = logs and logs.reporter("xml","core") or function(...) print(format(...)) end
-
---[[ldx--
-The parser used here is inspired by the variant discussed in the lua book, but
-handles comment and processing instructions, has a different structure, provides
-parent access; a first version used different trickery but was less optimized to we
-went this route. First we had a find based parser, now we have an based one.
-The find based parser can be found in l-xml-edu.lua along with other older code.
-
-Beware, the interface may change. For instance at, ns, tg, dt may get more
-verbose names. Once the code is stable we will also remove some tracing and
-optimize the code.
-
-I might even decide to reimplement the parser using the latest trickery
-as the current variant was written when showed up and it's easier now to
-build tables in one go.
---ldx]]--
-
-xml = xml or { }
-local xml = xml
-
-
-local utf = unicode.utf8
-local concat, remove, insert = table.concat, table.remove, table.insert
-local type, next, setmetatable, getmetatable, tonumber = type, next, setmetatable, getmetatable, tonumber
-local format, lower, find, match, gsub = string.format, string.lower, string.find, string.match, string.gsub
-local utfchar, utffind, utfgsub = utf.char, utf.find, utf.gsub
-local lpegmatch = lpeg.match
-local P, S, R, C, V, C, Cs = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.V, lpeg.C, lpeg.Cs
-
---[[ldx--
-First a hack to enable namespace resolving. A namespace is characterized by
-a . The following function associates a namespace prefix with a
-pattern. We use , which in this case is more than twice as fast as a
-find based solution where we loop over an array of patterns. Less code and
-much cleaner.
---ldx]]--
-
-xml.xmlns = xml.xmlns or { }
-
-local check = P(false)
-local parse = check
-
---[[ldx--
-The next function associates a namespace prefix with an . This
-normally happens independent of parsing.
-
-
-xml.registerns("mml","mathml")
-
---ldx]]--
-
-function xml.registerns(namespace, pattern) -- pattern can be an lpeg
- check = check + C(P(lower(pattern))) / namespace
- parse = P { P(check) + 1 * V(1) }
-end
-
---[[ldx--
-The next function also registers a namespace, but this time we map a
-given namespace prefix onto a registered one, using the given
- . This used for attributes like xmlns:m .
-
-
-xml.checkns("m","http://www.w3.org/mathml")
-
---ldx]]--
-
-function xml.checkns(namespace,url)
- local ns = lpegmatch(parse,lower(url))
- if ns and namespace ~= ns then
- xml.xmlns[namespace] = ns
- end
-end
-
---[[ldx--
-Next we provide a way to turn an into a registered
-namespace. This used for the xmlns attribute.
-
-
-resolvedns = xml.resolvens("http://www.w3.org/mathml")
-
-
-This returns mml .
---ldx]]--
-
-function xml.resolvens(url)
- return lpegmatch(parse,lower(url)) or ""
-end
-
---[[ldx--
-A namespace in an element can be remapped onto the registered
-one efficiently by using the xml.xmlns table.
---ldx]]--
-
---[[ldx--
-This version uses . We follow the same approach as before, stack and top and
-such. This version is about twice as fast which is mostly due to the fact that
-we don't have to prepare the stream for cdata, doctype etc etc. This variant is
-is dedicated to Luigi Scarso, who challenged me with 40 megabyte files that
-took 12.5 seconds to load (1.5 for file io and the rest for tree building). With
-the implementation we got that down to less 7.3 seconds. Loading the 14
- interface definition files (2.6 meg) went down from 1.05 seconds to 0.55.
-
-Next comes the parser. The rather messy doctype definition comes in many
-disguises so it is no surprice that later on have to dedicate quite some
- code to it.
-
-
-
-
-
-
-
-
-
-
-The code may look a bit complex but this is mostly due to the fact that we
-resolve namespaces and attach metatables. There is only one public function:
-
-
-local x = xml.convert(somestring)
-
-
-An optional second boolean argument tells this function not to create a root
-element.
-
-Valid entities are:
-
-
-
-
-
-
---ldx]]--
-
--- not just one big nested table capture (lpeg overflow)
-
-local nsremap, resolvens = xml.xmlns, xml.resolvens
-
-local stack = { }
-local top = { }
-local dt = { }
-local at = { }
-local xmlns = { }
-local errorstr = nil
-local entities = { }
-local strip = false
-local cleanup = false
-local utfize = false
-local resolve_predefined = false
-local unify_predefined = false
-
-local dcache = { }
-local hcache = { }
-local acache = { }
-
-local mt = { }
-
-local function initialize_mt(root)
- mt = { __index = root } -- will be redefined later
-end
-
-function xml.setproperty(root,k,v)
- getmetatable(root).__index[k] = v
-end
-
-function xml.checkerror(top,toclose)
- return "" -- can be set
-end
-
-local function add_attribute(namespace,tag,value)
- if cleanup and #value > 0 then
- value = cleanup(value) -- new
- end
- if tag == "xmlns" then
- xmlns[#xmlns+1] = resolvens(value)
- at[tag] = value
- elseif namespace == "" then
- at[tag] = value
- elseif namespace == "xmlns" then
- xml.checkns(tag,value)
- at["xmlns:" .. tag] = value
- else
- -- for the moment this way:
- at[namespace .. ":" .. tag] = value
- end
-end
-
-local function add_empty(spacing, namespace, tag)
- if #spacing > 0 then
- dt[#dt+1] = spacing
- end
- local resolved = (namespace == "" and xmlns[#xmlns]) or nsremap[namespace] or namespace
- top = stack[#stack]
- dt = top.dt
- local t = { ns=namespace or "", rn=resolved, tg=tag, at=at, dt={}, __p__ = top }
- dt[#dt+1] = t
- setmetatable(t, mt)
- if at.xmlns then
- remove(xmlns)
- end
- at = { }
-end
-
-local function add_begin(spacing, namespace, tag)
- if #spacing > 0 then
- dt[#dt+1] = spacing
- end
- local resolved = (namespace == "" and xmlns[#xmlns]) or nsremap[namespace] or namespace
- top = { ns=namespace or "", rn=resolved, tg=tag, at=at, dt={}, __p__ = stack[#stack] }
- setmetatable(top, mt)
- dt = top.dt
- stack[#stack+1] = top
- at = { }
-end
-
-local function add_end(spacing, namespace, tag)
- if #spacing > 0 then
- dt[#dt+1] = spacing
- end
- local toclose = remove(stack)
- top = stack[#stack]
- if #stack < 1 then
- errorstr = format("nothing to close with %s %s", tag, xml.checkerror(top,toclose) or "")
- elseif toclose.tg ~= tag then -- no namespace check
- errorstr = format("unable to close %s with %s %s", toclose.tg, tag, xml.checkerror(top,toclose) or "")
- end
- dt = top.dt
- dt[#dt+1] = toclose
- -- dt[0] = top -- nasty circular reference when serializing table
- if toclose.at.xmlns then
- remove(xmlns)
- end
-end
-
-local function add_text(text)
- if cleanup and #text > 0 then
- dt[#dt+1] = cleanup(text)
- else
- dt[#dt+1] = text
- end
-end
-
-local function add_special(what, spacing, text)
- if #spacing > 0 then
- dt[#dt+1] = spacing
- end
- if strip and (what == "@cm@" or what == "@dt@") then
- -- forget it
- else
- dt[#dt+1] = { special=true, ns="", tg=what, dt={ text } }
- end
-end
-
-local function set_message(txt)
- errorstr = "garbage at the end of the file: " .. gsub(txt,"([ \n\r\t]*)","")
-end
-
-local reported_attribute_errors = { }
-
-local function attribute_value_error(str)
- if not reported_attribute_errors[str] then
- report_xml("invalid attribute value: %q",str)
- reported_attribute_errors[str] = true
- at._error_ = str
- end
- return str
-end
-
-local function attribute_specification_error(str)
- if not reported_attribute_errors[str] then
- report_xml("invalid attribute specification: %q",str)
- reported_attribute_errors[str] = true
- at._error_ = str
- end
- return str
-end
-
-xml.placeholders = {
- unknown_dec_entity = function(str) return (str == "" and "&error;") or format("&%s;",str) end,
- unknown_hex_entity = function(str) return format("%s;",str) end,
- unknown_any_entity = function(str) return format("%s;",str) end,
-}
-
-local placeholders = xml.placeholders
-
-local function fromhex(s)
- local n = tonumber(s,16)
- if n then
- return utfchar(n)
- else
- return format("h:%s",s), true
- end
-end
-
-local function fromdec(s)
- local n = tonumber(s)
- if n then
- return utfchar(n)
- else
- return format("d:%s",s), true
- end
-end
-
--- one level expansion (simple case), no checking done
-
-local rest = (1-P(";"))^0
-local many = P(1)^0
-
-local parsedentity =
- P("&") * (P("#x")*(rest/fromhex) + P("#")*(rest/fromdec)) * P(";") * P(-1) +
- (P("#x")*(many/fromhex) + P("#")*(many/fromdec))
-
--- parsing in the xml file
-
-local predefined_unified = {
- [38] = "&",
- [42] = """,
- [47] = "'",
- [74] = "<",
- [76] = ">",
-}
-
-local predefined_simplified = {
- [38] = "&", amp = "&",
- [42] = '"', quot = '"',
- [47] = "'", apos = "'",
- [74] = "<", lt = "<",
- [76] = ">", gt = ">",
-}
-
-local nofprivates = 0xF0000 -- shared but seldom used
-
-local privates_u = { -- unescaped
- [ [[&]] ] = "&",
- [ [["]] ] = """,
- [ [[']] ] = "'",
- [ [[<]] ] = "<",
- [ [[>]] ] = ">",
-}
-
-local privates_p = {
-}
-
-local privates_n = {
- -- keeps track of defined ones
-}
-
-local function escaped(s)
- if s == "" then
- return ""
- else -- if utffind(s,privates_u) then
- return (utfgsub(s,".",privates_u))
- -- else
- -- return s
- end
-end
-
-local function unescaped(s)
- local p = privates_n[s]
- if not p then
- nofprivates = nofprivates + 1
- p = utfchar(nofprivates)
- privates_n[s] = p
- s = "&" .. s .. ";" -- todo: use char-ent to map to hex
- privates_u[p] = s
- privates_p[p] = s
- end
- return p
-end
-
-local function unprivatized(s,resolve)
- if s == "" then
- return ""
- else
- return (utfgsub(s,".",privates_p))
- end
-end
-
-xml.privatetoken = unescaped
-xml.unprivatized = unprivatized
-xml.privatecodes = privates_n
-
-local function handle_hex_entity(str)
- local h = hcache[str]
- if not h then
- local n = tonumber(str,16)
- h = unify_predefined and predefined_unified[n]
- if h then
- if trace_entities then
- report_xml("utfize, converting hex entity %s; into %s",str,h)
- end
- elseif utfize then
- h = (n and utfchar(n)) or xml.unknown_hex_entity(str) or ""
- if not n then
- report_xml("utfize, ignoring hex entity %s;",str)
- elseif trace_entities then
- report_xml("utfize, converting hex entity %s; into %s",str,h)
- end
- else
- if trace_entities then
- report_xml("found entity %s;",str)
- end
- h = "" .. str .. ";"
- end
- hcache[str] = h
- end
- return h
-end
-
-local function handle_dec_entity(str)
- local d = dcache[str]
- if not d then
- local n = tonumber(str)
- d = unify_predefined and predefined_unified[n]
- if d then
- if trace_entities then
- report_xml("utfize, converting dec entity %s; into %s",str,d)
- end
- elseif utfize then
- d = (n and utfchar(n)) or placeholders.unknown_dec_entity(str) or ""
- if not n then
- report_xml("utfize, ignoring dec entity %s;",str)
- elseif trace_entities then
- report_xml("utfize, converting dec entity %s; into %s",str,d)
- end
- else
- if trace_entities then
- report_xml("found entity %s;",str)
- end
- d = "" .. str .. ";"
- end
- dcache[str] = d
- end
- return d
-end
-
-xml.parsedentitylpeg = parsedentity
-
-local function handle_any_entity(str)
- if resolve then
- local a = acache[str] -- per instance ! todo
- if not a then
- a = resolve_predefined and predefined_simplified[str]
- if a then
- if trace_entities then
- report_xml("resolved entity &%s; -> %s (predefined)",str,a)
- end
- else
- if type(resolve) == "function" then
- a = resolve(str) or entities[str]
- else
- a = entities[str]
- end
- if a then
- if type(a) == "function" then
- if trace_entities then
- report_xml("expanding entity &%s; (function)",str)
- end
- a = a(str) or ""
- end
- a = lpegmatch(parsedentity,a) or a -- for nested
- if trace_entities then
- report_xml("resolved entity &%s; -> %s (internal)",str,a)
- end
- else
- local unknown_any_entity = placeholders.unknown_any_entity
- if unknown_any_entity then
- a = unknown_any_entity(str) or ""
- end
- if a then
- if trace_entities then
- report_xml("resolved entity &%s; -> %s (external)",str,a)
- end
- else
- if trace_entities then
- report_xml("keeping entity &%s;",str)
- end
- if str == "" then
- a = "&error;"
- else
- a = "&" .. str .. ";"
- end
- end
- end
- end
- acache[str] = a
- elseif trace_entities then
- if not acache[str] then
- report_xml("converting entity &%s; into %s",str,a)
- acache[str] = a
- end
- end
- return a
- else
- local a = acache[str]
- if not a then
- a = resolve_predefined and predefined_simplified[str]
- if a then
- -- one of the predefined
- acache[str] = a
- if trace_entities then
- report_xml("entity &%s; becomes %s",str,tostring(a))
- end
- elseif str == "" then
- if trace_entities then
- report_xml("invalid entity &%s;",str)
- end
- a = "&error;"
- acache[str] = a
- else
- if trace_entities then
- report_xml("entity &%s; is made private",str)
- end
- -- a = "&" .. str .. ";"
- a = unescaped(str)
- acache[str] = a
- end
- end
- return a
- end
-end
-
-local function handle_end_entity(chr)
- report_xml("error in entity, %q found instead of ';'",chr)
-end
-
-local space = S(' \r\n\t')
-local open = P('<')
-local close = P('>')
-local squote = S("'")
-local dquote = S('"')
-local equal = P('=')
-local slash = P('/')
-local colon = P(':')
-local semicolon = P(';')
-local ampersand = P('&')
-local valid = R('az', 'AZ', '09') + S('_-.')
-local name_yes = C(valid^1) * colon * C(valid^1)
-local name_nop = C(P(true)) * C(valid^1)
-local name = name_yes + name_nop
-local utfbom = lpeg.patterns.utfbom -- no capture
-local spacing = C(space^0)
-
------ entitycontent = (1-open-semicolon)^0
-local anyentitycontent = (1-open-semicolon-space-close)^0
-local hexentitycontent = R("AF","af","09")^0
-local decentitycontent = R("09")^0
-local parsedentity = P("#")/"" * (
- P("x")/"" * (hexentitycontent/handle_hex_entity) +
- (decentitycontent/handle_dec_entity)
- ) + (anyentitycontent/handle_any_entity)
-local entity = ampersand/"" * parsedentity * ( (semicolon/"") + #(P(1)/handle_end_entity))
-
-local text_unparsed = C((1-open)^1)
-local text_parsed = Cs(((1-open-ampersand)^1 + entity)^1)
-
-local somespace = space^1
-local optionalspace = space^0
-
------ value = (squote * C((1 - squote)^0) * squote) + (dquote * C((1 - dquote)^0) * dquote) -- ampersand and < also invalid in value
-local value = (squote * Cs((entity + (1 - squote))^0) * squote) + (dquote * Cs((entity + (1 - dquote))^0) * dquote) -- ampersand and < also invalid in value
-
-local endofattributes = slash * close + close -- recovery of flacky html
-local whatever = space * name * optionalspace * equal
------ wrongvalue = C(P(1-whatever-close)^1 + P(1-close)^1) / attribute_value_error
------ wrongvalue = C(P(1-whatever-endofattributes)^1 + P(1-endofattributes)^1) / attribute_value_error
------ wrongvalue = C(P(1-space-endofattributes)^1) / attribute_value_error
-local wrongvalue = Cs(P(entity + (1-space-endofattributes))^1) / attribute_value_error
-
-local attributevalue = value + wrongvalue
-
-local attribute = (somespace * name * optionalspace * equal * optionalspace * attributevalue) / add_attribute
------ attributes = (attribute)^0
-
-local attributes = (attribute + somespace^-1 * (((1-endofattributes)^1)/attribute_specification_error))^0
-
-local parsedtext = text_parsed / add_text
-local unparsedtext = text_unparsed / add_text
-local balanced = P { "[" * ((1 - S"[]") + V(1))^0 * "]" } -- taken from lpeg manual, () example
-
-local emptyelement = (spacing * open * name * attributes * optionalspace * slash * close) / add_empty
-local beginelement = (spacing * open * name * attributes * optionalspace * close) / add_begin
-local endelement = (spacing * open * slash * name * optionalspace * close) / add_end
-
-local begincomment = open * P("!--")
-local endcomment = P("--") * close
-local begininstruction = open * P("?")
-local endinstruction = P("?") * close
-local begincdata = open * P("![CDATA[")
-local endcdata = P("]]") * close
-
-local someinstruction = C((1 - endinstruction)^0)
-local somecomment = C((1 - endcomment )^0)
-local somecdata = C((1 - endcdata )^0)
-
-local function normalentity(k,v ) entities[k] = v end
-local function systementity(k,v,n) entities[k] = v end
-local function publicentity(k,v,n) entities[k] = v end
-
--- todo: separate dtd parser
-
-local begindoctype = open * P("!DOCTYPE")
-local enddoctype = close
-local beginset = P("[")
-local endset = P("]")
-local doctypename = C((1-somespace-close)^0)
-local elementdoctype = optionalspace * P(" &
- cleanup = settings.text_cleanup
- entities = settings.entities or { }
- --
- if utfize == nil then
- settings.utfize_entities = true
- utfize = true
- end
- if resolve_predefined == nil then
- settings.resolve_predefined_entities = true
- resolve_predefined = true
- end
- --
- --
- stack, top, at, xmlns, errorstr = { }, { }, { }, { }, nil
- acache, hcache, dcache = { }, { }, { } -- not stored
- reported_attribute_errors = { }
- if settings.parent_root then
- mt = getmetatable(settings.parent_root)
- else
- initialize_mt(top)
- end
- stack[#stack+1] = top
- top.dt = { }
- dt = top.dt
- if not data or data == "" then
- errorstr = "empty xml file"
- elseif utfize or resolve then
- if lpegmatch(grammar_parsed_text,data) then
- errorstr = ""
- else
- errorstr = "invalid xml file - parsed text"
- end
- elseif type(data) == "string" then
- if lpegmatch(grammar_unparsed_text,data) then
- errorstr = ""
- else
- errorstr = "invalid xml file - unparsed text"
- end
- else
- errorstr = "invalid xml file - no text at all"
- end
- local result
- if errorstr and errorstr ~= "" then
- result = { dt = { { ns = "", tg = "error", dt = { errorstr }, at={ }, er = true } } }
- setmetatable(stack, mt)
- local errorhandler = settings.error_handler
- if errorhandler == false then
- -- no error message
- else
- errorhandler = errorhandler or xml.errorhandler
- if errorhandler then
- xml.errorhandler(format("load error: %s",errorstr))
- end
- end
- else
- result = stack[1]
- end
- if not settings.no_root then
- result = { special = true, ns = "", tg = '@rt@', dt = result.dt, at={ }, entities = entities, settings = settings }
- setmetatable(result, mt)
- local rdt = result.dt
- for k=1,#rdt do
- local v = rdt[k]
- if type(v) == "table" and not v.special then -- always table -)
- result.ri = k -- rootindex
- v.__p__ = result -- new, experiment, else we cannot go back to settings, we need to test this !
- break
- end
- end
- end
- if errorstr and errorstr ~= "" then
- result.error = true
- end
- result.statistics = {
- entities = {
- decimals = dcache,
- hexadecimals = hcache,
- names = acache,
- }
- }
- strip, utfize, resolve, resolve_predefined = nil, nil, nil, nil
- unify_predefined, cleanup, entities = nil, nil, nil
- stack, top, at, xmlns, errorstr = nil, nil, nil, nil, nil
- acache, hcache, dcache = nil, nil, nil
- reported_attribute_errors, mt, errorhandler = nil, nil, nil
- return result
-end
-
--- Because we can have a crash (stack issues) with faulty xml, we wrap this one
--- in a protector:
-
-function xmlconvert(data,settings)
- local ok, result = pcall(function() return _xmlconvert_(data,settings) end)
- if ok then
- return result
- else
- return _xmlconvert_("")
- end
-end
-
-xml.convert = xmlconvert
-
-function xml.inheritedconvert(data,xmldata) -- xmldata is parent
- local settings = xmldata.settings
- if settings then
- settings.parent_root = xmldata -- to be tested
- end
- -- settings.no_root = true
- local xc = xmlconvert(data,settings) -- hm, we might need to locate settings
- -- xc.settings = nil
- -- xc.entities = nil
- -- xc.special = nil
- -- xc.ri = nil
- -- print(xc.tg)
- return xc
-end
-
---[[ldx--
-Packaging data in an xml like table is done with the following
-function. Maybe it will go away (when not used).
---ldx]]--
-
-function xml.is_valid(root)
- return root and root.dt and root.dt[1] and type(root.dt[1]) == "table" and not root.dt[1].er
-end
-
-function xml.package(tag,attributes,data)
- local ns, tg = match(tag,"^(.-):?([^:]+)$")
- local t = { ns = ns, tg = tg, dt = data or "", at = attributes or {} }
- setmetatable(t, mt)
- return t
-end
-
-function xml.is_valid(root)
- return root and not root.error
-end
-
-xml.errorhandler = report_xml
-
---[[ldx--
-We cannot load an from a filehandle so we need to load
-the whole file first. The function accepts a string representing
-a filename or a file handle.
---ldx]]--
-
-function xml.load(filename,settings)
- local data = ""
- if type(filename) == "string" then
- -- local data = io.loaddata(filename) - -todo: check type in io.loaddata
- local f = io.open(filename,'r')
- if f then
- data = f:read("*all")
- f:close()
- end
- elseif filename then -- filehandle
- data = filename:read("*all")
- end
- return xmlconvert(data,settings)
-end
-
---[[ldx--
-When we inject new elements, we need to convert strings to
-valid trees, which is what the next function does.
---ldx]]--
-
-local no_root = { no_root = true }
-
-function xml.toxml(data)
- if type(data) == "string" then
- local root = { xmlconvert(data,no_root) }
- return (#root > 1 and root) or root[1]
- else
- return data
- end
-end
-
---[[ldx--
-For copying a tree we use a dedicated function instead of the
-generic table copier. Since we know what we're dealing with we
-can speed up things a bit. The second argument is not to be used!
---ldx]]--
-
-local function copy(old,tables)
- if old then
- tables = tables or { }
- local new = { }
- if not tables[old] then
- tables[old] = new
- end
- for k,v in next, old do
- new[k] = (type(v) == "table" and (tables[v] or copy(v, tables))) or v
- end
- local mt = getmetatable(old)
- if mt then
- setmetatable(new,mt)
- end
- return new
- else
- return { }
- end
-end
-
-xml.copy = copy
-
---[[ldx--
-In serializing the tree or parts of the tree is a major
-actitivity which is why the following function is pretty optimized resulting
-in a few more lines of code than needed. The variant that uses the formatting
-function for all components is about 15% slower than the concatinating
-alternative.
---ldx]]--
-
--- todo: add when not present
-
-function xml.checkbom(root) -- can be made faster
- if root.ri then
- local dt = root.dt
- for k=1,#dt do
- local v = dt[k]
- if type(v) == "table" and v.special and v.tg == "@pi@" and find(v.dt[1],"xml.*version=") then
- return
- end
- end
- insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
- insert(dt, 2, "\n" )
- end
-end
-
---[[ldx--
-At the cost of some 25% runtime overhead you can first convert the tree to a string
-and then handle the lot.
---ldx]]--
-
--- new experimental reorganized serialize
-
-local function verbose_element(e,handlers) -- options
- local handle = handlers.handle
- local serialize = handlers.serialize
- local ens, etg, eat, edt, ern = e.ns, e.tg, e.at, e.dt, e.rn
- local ats = eat and next(eat) and { }
- if ats then
- for k,v in next, eat do
- ats[#ats+1] = format('%s=%q',k,escaped(v))
- end
- end
- if ern and trace_entities and ern ~= ens then
- ens = ern
- end
- if ens ~= "" then
- if edt and #edt > 0 then
- if ats then
- handle("<",ens,":",etg," ",concat(ats," "),">")
- else
- handle("<",ens,":",etg,">")
- end
- for i=1,#edt do
- local e = edt[i]
- if type(e) == "string" then
- handle(escaped(e))
- else
- serialize(e,handlers)
- end
- end
- handle("",ens,":",etg,">")
- else
- if ats then
- handle("<",ens,":",etg," ",concat(ats," "),"/>")
- else
- handle("<",ens,":",etg,"/>")
- end
- end
- else
- if edt and #edt > 0 then
- if ats then
- handle("<",etg," ",concat(ats," "),">")
- else
- handle("<",etg,">")
- end
- for i=1,#edt do
- local e = edt[i]
- if type(e) == "string" then
- handle(escaped(e)) -- option: hexify escaped entities
- else
- serialize(e,handlers)
- end
- end
- handle("",etg,">")
- else
- if ats then
- handle("<",etg," ",concat(ats," "),"/>")
- else
- handle("<",etg,"/>")
- end
- end
- end
-end
-
-local function verbose_pi(e,handlers)
- handlers.handle("",e.dt[1],"?>")
-end
-
-local function verbose_comment(e,handlers)
- handlers.handle("")
-end
-
-local function verbose_cdata(e,handlers)
- handlers.handle("")
-end
-
-local function verbose_doctype(e,handlers)
- handlers.handle("")
-end
-
-local function verbose_root(e,handlers)
- handlers.serialize(e.dt,handlers)
-end
-
-local function verbose_text(e,handlers)
- handlers.handle(escaped(e))
-end
-
-local function verbose_document(e,handlers)
- local serialize = handlers.serialize
- local functions = handlers.functions
- for i=1,#e do
- local ei = e[i]
- if type(ei) == "string" then
- functions["@tx@"](ei,handlers)
- else
- serialize(ei,handlers)
- end
- end
-end
-
-local function serialize(e,handlers,...)
- local initialize = handlers.initialize
- local finalize = handlers.finalize
- local functions = handlers.functions
- if initialize then
- local state = initialize(...)
- if not state == true then
- return state
- end
- end
- local etg = e.tg
- if etg then
- (functions[etg] or functions["@el@"])(e,handlers)
- -- elseif type(e) == "string" then
- -- functions["@tx@"](e,handlers)
- else
- functions["@dc@"](e,handlers) -- dc ?
- end
- if finalize then
- return finalize()
- end
-end
-
-local function xserialize(e,handlers)
- local functions = handlers.functions
- local etg = e.tg
- if etg then
- (functions[etg] or functions["@el@"])(e,handlers)
- -- elseif type(e) == "string" then
- -- functions["@tx@"](e,handlers)
- else
- functions["@dc@"](e,handlers)
- end
-end
-
-local handlers = { }
-
-local function newhandlers(settings)
- local t = table.copy(handlers.verbose or { }) -- merge
- if settings then
- for k,v in next, settings do
- if type(v) == "table" then
- local tk = t[k] if not tk then tk = { } t[k] = tk end
- for kk,vv in next, v do
- tk[kk] = vv
- end
- else
- t[k] = v
- end
- end
- if settings.name then
- handlers[settings.name] = t
- end
- end
- utilities.storage.mark(t)
- return t
-end
-
-local nofunction = function() end
-
-function xml.sethandlersfunction(handler,name,fnc)
- handler.functions[name] = fnc or nofunction
-end
-
-function xml.gethandlersfunction(handler,name)
- return handler.functions[name]
-end
-
-function xml.gethandlers(name)
- return handlers[name]
-end
-
-newhandlers {
- name = "verbose",
- initialize = false, -- faster than nil and mt lookup
- finalize = false, -- faster than nil and mt lookup
- serialize = xserialize,
- handle = print,
- functions = {
- ["@dc@"] = verbose_document,
- ["@dt@"] = verbose_doctype,
- ["@rt@"] = verbose_root,
- ["@el@"] = verbose_element,
- ["@pi@"] = verbose_pi,
- ["@cm@"] = verbose_comment,
- ["@cd@"] = verbose_cdata,
- ["@tx@"] = verbose_text,
- }
-}
-
---[[ldx--
-How you deal with saving data depends on your preferences. For a 40 MB database
-file the timing on a 2.3 Core Duo are as follows (time in seconds):
-
-
-1.3 : load data from file to string
-6.1 : convert string into tree
-5.3 : saving in file using xmlsave
-6.8 : converting to string using xml.tostring
-3.6 : saving converted string in file
-
-
-Beware, these were timing with the old routine but measurements will not be that
-much different I guess.
---ldx]]--
-
--- maybe this will move to lxml-xml
-
-local result
-
-local xmlfilehandler = newhandlers {
- name = "file",
- initialize = function(name)
- result = io.open(name,"wb")
- return result
- end,
- finalize = function()
- result:close()
- return true
- end,
- handle = function(...)
- result:write(...)
- end,
-}
-
--- no checking on writeability here but not faster either
---
--- local xmlfilehandler = newhandlers {
--- initialize = function(name)
--- io.output(name,"wb")
--- return true
--- end,
--- finalize = function()
--- io.close()
--- return true
--- end,
--- handle = io.write,
--- }
-
-function xml.save(root,name)
- serialize(root,xmlfilehandler,name)
-end
-
-local result
-
-local xmlstringhandler = newhandlers {
- name = "string",
- initialize = function()
- result = { }
- return result
- end,
- finalize = function()
- return concat(result)
- end,
- handle = function(...)
- result[#result+1] = concat { ... }
- end,
-}
-
-local function xmltostring(root) -- 25% overhead due to collecting
- if not root then
- return ""
- elseif type(root) == 'string' then
- return root
- else -- if next(root) then -- next is faster than type (and >0 test)
- return serialize(root,xmlstringhandler) or ""
- end
-end
-
-local function __tostring(root) -- inline
- return (root and xmltostring(root)) or ""
-end
-
-initialize_mt = function(root) -- redefinition
- mt = { __tostring = __tostring, __index = root }
-end
-
-xml.defaulthandlers = handlers
-xml.newhandlers = newhandlers
-xml.serialize = serialize
-xml.tostring = xmltostring
-
---[[ldx--
-The next function operated on the content only and needs a handle function
-that accepts a string.
---ldx]]--
-
-local function xmlstring(e,handle)
- if not handle or (e.special and e.tg ~= "@rt@") then
- -- nothing
- elseif e.tg then
- local edt = e.dt
- if edt then
- for i=1,#edt do
- xmlstring(edt[i],handle)
- end
- end
- else
- handle(e)
- end
-end
-
-xml.string = xmlstring
-
---[[ldx--
-A few helpers:
---ldx]]--
-
-
-function xml.settings(e)
- while e do
- local s = e.settings
- if s then
- return s
- else
- e = e.__p__
- end
- end
- return nil
-end
-
-function xml.root(e)
- local r = e
- while e do
- e = e.__p__
- if e then
- r = e
- end
- end
- return r
-end
-
-function xml.parent(root)
- return root.__p__
-end
-
-function xml.body(root)
- return (root.ri and root.dt[root.ri]) or root -- not ok yet
-end
-
-function xml.name(root)
- if not root then
- return ""
- elseif root.ns == "" then
- return root.tg
- else
- return root.ns .. ":" .. root.tg
- end
-end
-
---[[ldx--
-The next helper erases an element but keeps the table as it is,
-and since empty strings are not serialized (effectively) it does
-not harm. Copying the table would take more time. Usage:
---ldx]]--
-
-function xml.erase(dt,k)
- if dt then
- if k then
- dt[k] = ""
- else for k=1,#dt do
- dt[1] = { "" }
- end end
- end
-end
-
---[[ldx--
-The next helper assigns a tree (or string). Usage:
-
-
-dt[k] = xml.assign(root) or xml.assign(dt,k,root)
-
---ldx]]--
-
-function xml.assign(dt,k,root)
- if dt and k then
- dt[k] = (type(root) == "table" and xml.body(root)) or root
- return dt[k]
- else
- return xml.body(root)
- end
-end
-
--- the following helpers may move
-
---[[ldx--
-The next helper assigns a tree (or string). Usage:
-
-xml.tocdata(e)
-xml.tocdata(e,"error")
-
---ldx]]--
-
-function xml.tocdata(e,wrapper) -- a few more in the aux module
- local whatever = type(e) == "table" and xmltostring(e.dt) or e or ""
- if wrapper then
- whatever = format("<%s>%s%s>",wrapper,whatever,wrapper)
- end
- local t = { special = true, ns = "", tg = "@cd@", at = {}, rn = "", dt = { whatever }, __p__ = e }
- setmetatable(t,getmetatable(e))
- e.dt = { t }
-end
-
-function xml.makestandalone(root)
- if root.ri then
- local dt = root.dt
- for k=1,#dt do
- local v = dt[k]
- if type(v) == "table" and v.special and v.tg == "@pi@" then
- local txt = v.dt[1]
- if find(txt,"xml.*version=") then
- v.dt[1] = txt .. " standalone='yes'"
- break
- end
- end
- end
- end
- return root
-end
-
-function xml.kind(e)
- local dt = e and e.dt
- if dt then
- local n = #dt
- if n == 1 then
- local d = dt[1]
- if d.special then
- local tg = d.tg
- if tg == "@cd@" then
- return "cdata"
- elseif tg == "@cm" then
- return "comment"
- elseif tg == "@pi@" then
- return "instruction"
- elseif tg == "@dt@" then
- return "declaration"
- end
- elseif type(d) == "string" then
- return "text"
- end
- return "element"
- elseif n > 0 then
- return "mixed"
- end
- end
- return "empty"
-end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['lxml-pth'] = {
- version = 1.001,
- comment = "this module is the basis for the lxml-* ones",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- e.ni is only valid after a filter run
--- todo: B/C/[get first match]
-
-local concat, remove, insert = table.concat, table.remove, table.insert
-local type, next, tonumber, tostring, setmetatable, loadstring = type, next, tonumber, tostring, setmetatable, loadstring
-local format, upper, lower, gmatch, gsub, find, rep = string.format, string.upper, string.lower, string.gmatch, string.gsub, string.find, string.rep
-local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
-
-local setmetatableindex = table.setmetatableindex
-
--- beware, this is not xpath ... e.g. position is different (currently) and
--- we have reverse-sibling as reversed preceding sibling
-
---[[ldx--
-This module can be used stand alone but also inside in
-which case it hooks into the tracker code. Therefore we provide a few
-functions that set the tracers. Here we overload a previously defined
-function.
-If I can get in the mood I will make a variant that is XSLT compliant
-but I wonder if it makes sense.
---ldx]]--
-
---[[ldx--
-Expecially the lpath code is experimental, we will support some of xpath, but
-only things that make sense for us; as compensation it is possible to hook in your
-own functions. Apart from preprocessing content for we also need
-this module for process management, like handling and
-files.
-
-
-a/b/c /*/c
-a/b/c/first() a/b/c/last() a/b/c/index(n) a/b/c/index(-n)
-a/b/c/text() a/b/c/text(1) a/b/c/text(-1) a/b/c/text(n)
-
---ldx]]--
-
-local trace_lpath = false if trackers then trackers.register("xml.path", function(v) trace_lpath = v end) end
-local trace_lparse = false if trackers then trackers.register("xml.parse", function(v) trace_lparse = v end) end
-local trace_lprofile = false if trackers then trackers.register("xml.profile", function(v) trace_lpath = v trace_lparse = v trace_lprofile = v end) end
-
-local report_lpath = logs.reporter("xml","lpath")
-
---[[ldx--
-We've now arrived at an interesting part: accessing the tree using a subset
-of and since we're not compatible we call it . We
-will explain more about its usage in other documents.
---ldx]]--
-
-local xml = xml
-
-local lpathcalls = 0 function xml.lpathcalls () return lpathcalls end
-local lpathcached = 0 function xml.lpathcached() return lpathcached end
-
-xml.functions = xml.functions or { } -- internal
-local functions = xml.functions
-
-xml.expressions = xml.expressions or { } -- in expressions
-local expressions = xml.expressions
-
-xml.finalizers = xml.finalizers or { } -- fast do-with ... (with return value other than collection)
-local finalizers = xml.finalizers
-
-xml.specialhandler = xml.specialhandler or { }
-local specialhandler = xml.specialhandler
-
-lpegpatterns.xml = lpegpatterns.xml or { }
-local xmlpatterns = lpegpatterns.xml
-
-finalizers.xml = finalizers.xml or { }
-finalizers.tex = finalizers.tex or { }
-
-local function fallback (t, name)
- local fn = finalizers[name]
- if fn then
- t[name] = fn
- else
- report_lpath("unknown sub finalizer '%s'",tostring(name))
- fn = function() end
- end
- return fn
-end
-
-setmetatableindex(finalizers.xml, fallback)
-setmetatableindex(finalizers.tex, fallback)
-
-xml.defaultprotocol = "xml"
-
--- as xsl does not follow xpath completely here we will also
--- be more liberal especially with regards to the use of | and
--- the rootpath:
---
--- test : all 'test' under current
--- /test : 'test' relative to current
--- a|b|c : set of names
--- (a|b|c) : idem
--- ! : not
---
--- after all, we're not doing transformations but filtering. in
--- addition we provide filter functions (last bit)
---
--- todo: optimizer
---
--- .. : parent
--- * : all kids
--- / : anchor here
--- // : /**/
--- ** : all in between
---
--- so far we had (more practical as we don't transform)
---
--- {/test} : kids 'test' under current node
--- {test} : any kid with tag 'test'
--- {//test} : same as above
-
--- evaluator (needs to be redone, for the moment copied)
-
--- todo: apply_axis(list,notable) and collection vs single
-
-local apply_axis = { }
-
-apply_axis['root'] = function(list)
- local collected = { }
- for l=1,#list do
- local ll = list[l]
- local rt = ll
- while ll do
- ll = ll.__p__
- if ll then
- rt = ll
- end
- end
- collected[l] = rt
- end
- return collected
-end
-
-apply_axis['self'] = function(list)
- return list
-end
-
-apply_axis['child'] = function(list)
- local collected, c = { }, 0
- for l=1,#list do
- local ll = list[l]
- local dt = ll.dt
- if dt then -- weird that this is needed
- local en = 0
- for k=1,#dt do
- local dk = dt[k]
- if dk.tg then
- c = c + 1
- collected[c] = dk
- dk.ni = k -- refresh
- en = en + 1
- dk.ei = en
- end
- end
- ll.en = en
- end
- end
- return collected
-end
-
-local function collect(list,collected,c)
- local dt = list.dt
- if dt then
- local en = 0
- for k=1,#dt do
- local dk = dt[k]
- if dk.tg then
- c = c + 1
- collected[c] = dk
- dk.ni = k -- refresh
- en = en + 1
- dk.ei = en
- c = collect(dk,collected,c)
- end
- end
- list.en = en
- end
- return c
-end
-
-apply_axis['descendant'] = function(list)
- local collected, c = { }, 0
- for l=1,#list do
- c = collect(list[l],collected,c)
- end
- return collected
-end
-
-local function collect(list,collected,c)
- local dt = list.dt
- if dt then
- local en = 0
- for k=1,#dt do
- local dk = dt[k]
- if dk.tg then
- c = c + 1
- collected[c] = dk
- dk.ni = k -- refresh
- en = en + 1
- dk.ei = en
- c = collect(dk,collected,c)
- end
- end
- list.en = en
- end
- return c
-end
-apply_axis['descendant-or-self'] = function(list)
- local collected, c = { }, 0
- for l=1,#list do
- local ll = list[l]
- if ll.special ~= true then -- catch double root
- c = c + 1
- collected[c] = ll
- end
- c = collect(ll,collected,c)
- end
- return collected
-end
-
-apply_axis['ancestor'] = function(list)
- local collected, c = { }, 0
- for l=1,#list do
- local ll = list[l]
- while ll do
- ll = ll.__p__
- if ll then
- c = c + 1
- collected[c] = ll
- end
- end
- end
- return collected
-end
-
-apply_axis['ancestor-or-self'] = function(list)
- local collected, c = { }, 0
- for l=1,#list do
- local ll = list[l]
- c = c + 1
- collected[c] = ll
- while ll do
- ll = ll.__p__
- if ll then
- c = c + 1
- collected[c] = ll
- end
- end
- end
- return collected
-end
-
-apply_axis['parent'] = function(list)
- local collected, c = { }, 0
- for l=1,#list do
- local pl = list[l].__p__
- if pl then
- c = c + 1
- collected[c] = pl
- end
- end
- return collected
-end
-
-apply_axis['attribute'] = function(list)
- return { }
-end
-
-apply_axis['namespace'] = function(list)
- return { }
-end
-
-apply_axis['following'] = function(list) -- incomplete
- return { }
-end
-
-apply_axis['preceding'] = function(list) -- incomplete
- return { }
-end
-
-apply_axis['following-sibling'] = function(list)
- local collected, c = { }, 0
- for l=1,#list do
- local ll = list[l]
- local p = ll.__p__
- local d = p.dt
- for i=ll.ni+1,#d do
- local di = d[i]
- if type(di) == "table" then
- c = c + 1
- collected[c] = di
- end
- end
- end
- return collected
-end
-
-apply_axis['preceding-sibling'] = function(list)
- local collected, c = { }, 0
- for l=1,#list do
- local ll = list[l]
- local p = ll.__p__
- local d = p.dt
- for i=1,ll.ni-1 do
- local di = d[i]
- if type(di) == "table" then
- c = c + 1
- collected[c] = di
- end
- end
- end
- return collected
-end
-
-apply_axis['reverse-sibling'] = function(list) -- reverse preceding
- local collected, c = { }, 0
- for l=1,#list do
- local ll = list[l]
- local p = ll.__p__
- local d = p.dt
- for i=ll.ni-1,1,-1 do
- local di = d[i]
- if type(di) == "table" then
- c = c + 1
- collected[c] = di
- end
- end
- end
- return collected
-end
-
-apply_axis['auto-descendant-or-self'] = apply_axis['descendant-or-self']
-apply_axis['auto-descendant'] = apply_axis['descendant']
-apply_axis['auto-child'] = apply_axis['child']
-apply_axis['auto-self'] = apply_axis['self']
-apply_axis['initial-child'] = apply_axis['child']
-
-local function apply_nodes(list,directive,nodes)
- -- todo: nodes[1] etc ... negated node name in set ... when needed
- -- ... currently ignored
- local maxn = #nodes
- if maxn == 3 then --optimized loop
- local nns, ntg = nodes[2], nodes[3]
- if not nns and not ntg then -- wildcard
- if directive then
- return list
- else
- return { }
- end
- else
- local collected, c, m, p = { }, 0, 0, nil
- if not nns then -- only check tag
- for l=1,#list do
- local ll = list[l]
- local ltg = ll.tg
- if ltg then
- if directive then
- if ntg == ltg then
- local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
- c = c + 1
- collected[c], ll.mi = ll, m
- end
- elseif ntg ~= ltg then
- local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
- c = c + 1
- collected[c], ll.mi = ll, m
- end
- end
- end
- elseif not ntg then -- only check namespace
- for l=1,#list do
- local ll = list[l]
- local lns = ll.rn or ll.ns
- if lns then
- if directive then
- if lns == nns then
- local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
- c = c + 1
- collected[c], ll.mi = ll, m
- end
- elseif lns ~= nns then
- local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
- c = c + 1
- collected[c], ll.mi = ll, m
- end
- end
- end
- else -- check both
- for l=1,#list do
- local ll = list[l]
- local ltg = ll.tg
- if ltg then
- local lns = ll.rn or ll.ns
- local ok = ltg == ntg and lns == nns
- if directive then
- if ok then
- local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
- c = c + 1
- collected[c], ll.mi = ll, m
- end
- elseif not ok then
- local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
- c = c + 1
- collected[c], ll.mi = ll, m
- end
- end
- end
- end
- return collected
- end
- else
- local collected, c, m, p = { }, 0, 0, nil
- for l=1,#list do
- local ll = list[l]
- local ltg = ll.tg
- if ltg then
- local lns = ll.rn or ll.ns
- local ok = false
- for n=1,maxn,3 do
- local nns, ntg = nodes[n+1], nodes[n+2]
- ok = (not ntg or ltg == ntg) and (not nns or lns == nns)
- if ok then
- break
- end
- end
- if directive then
- if ok then
- local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
- c = c + 1
- collected[c], ll.mi = ll, m
- end
- elseif not ok then
- local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
- c = c + 1
- collected[c], ll.mi = ll, m
- end
- end
- end
- return collected
- end
-end
-
-local quit_expression = false
-
-local function apply_expression(list,expression,order)
- local collected, c = { }, 0
- quit_expression = false
- for l=1,#list do
- local ll = list[l]
- if expression(list,ll,l,order) then -- nasty, order alleen valid als n=1
- c = c + 1
- collected[c] = ll
- end
- if quit_expression then
- break
- end
- end
- return collected
-end
-
-local P, V, C, Cs, Cc, Ct, R, S, Cg, Cb = lpeg.P, lpeg.V, lpeg.C, lpeg.Cs, lpeg.Cc, lpeg.Ct, lpeg.R, lpeg.S, lpeg.Cg, lpeg.Cb
-
-local spaces = S(" \n\r\t\f")^0
-local lp_space = S(" \n\r\t\f")
-local lp_any = P(1)
-local lp_noequal = P("!=") / "~=" + P("<=") + P(">=") + P("==")
-local lp_doequal = P("=") / "=="
-local lp_or = P("|") / " or "
-local lp_and = P("&") / " and "
-
-local lp_builtin = P (
- P("text") / "(ll.dt[1] or '')" + -- fragile
- P("content") / "ll.dt" +
- -- P("name") / "(ll.ns~='' and ll.ns..':'..ll.tg)" +
- P("name") / "((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)" +
- P("tag") / "ll.tg" +
- P("position") / "l" + -- is element in finalizer
- P("firstindex") / "1" +
- P("lastindex") / "(#ll.__p__.dt or 1)" +
- P("firstelement") / "1" +
- P("lastelement") / "(ll.__p__.en or 1)" +
- P("first") / "1" +
- P("last") / "#list" +
- P("rootposition") / "order" +
- P("order") / "order" +
- P("element") / "(ll.ei or 1)" +
- P("index") / "(ll.ni or 1)" +
- P("match") / "(ll.mi or 1)" +
- -- P("namespace") / "ll.ns" +
- P("ns") / "ll.ns"
- ) * ((spaces * P("(") * spaces * P(")"))/"")
-
--- for the moment we keep namespaces with attributes
-
-local lp_attribute = (P("@") + P("attribute::")) / "" * Cc("(ll.at and ll.at['") * ((R("az","AZ") + S("-_:"))^1) * Cc("'])")
-local lp_fastpos_p = ((P("+")^0 * R("09")^1 * P(-1)) / function(s) return "l==" .. s end)
-local lp_fastpos_n = ((P("-") * R("09")^1 * P(-1)) / function(s) return "(" .. s .. "<0 and (#list+".. s .. "==l))" end)
-local lp_fastpos = lp_fastpos_n + lp_fastpos_p
-local lp_reserved = C("and") + C("or") + C("not") + C("div") + C("mod") + C("true") + C("false")
-
-local lp_lua_function = C(R("az","AZ","__")^1 * (P(".") * R("az","AZ","__")^1)^1) * ("(") / function(t) -- todo: better . handling
- return t .. "("
-end
-
-local lp_function = C(R("az","AZ","__")^1) * P("(") / function(t) -- todo: better . handling
- if expressions[t] then
- return "expr." .. t .. "("
- else
- return "expr.error("
- end
-end
-
-local lparent = P("(")
-local rparent = P(")")
-local noparent = 1 - (lparent+rparent)
-local nested = P{lparent * (noparent + V(1))^0 * rparent}
-local value = P(lparent * C((noparent + nested)^0) * rparent) -- P{"("*C(((1-S("()"))+V(1))^0)*")"}
-
-local lp_child = Cc("expr.child(ll,'") * R("az","AZ","--","__")^1 * Cc("')")
-local lp_number = S("+-") * R("09")^1
-local lp_string = Cc("'") * R("az","AZ","--","__")^1 * Cc("'")
-local lp_content = (P("'") * (1-P("'"))^0 * P("'") + P('"') * (1-P('"'))^0 * P('"'))
-
-local cleaner
-
-local lp_special = (C(P("name")+P("text")+P("tag")+P("count")+P("child"))) * value / function(t,s)
- if expressions[t] then
- s = s and s ~= "" and lpegmatch(cleaner,s)
- if s and s ~= "" then
- return "expr." .. t .. "(ll," .. s ..")"
- else
- return "expr." .. t .. "(ll)"
- end
- else
- return "expr.error(" .. t .. ")"
- end
-end
-
-local content =
- lp_builtin +
- lp_attribute +
- lp_special +
- lp_noequal + lp_doequal +
- lp_or + lp_and +
- lp_reserved +
- lp_lua_function + lp_function +
- lp_content + -- too fragile
- lp_child +
- lp_any
-
-local converter = Cs (
- lp_fastpos + (P { lparent * (V(1))^0 * rparent + content } )^0
-)
-
-cleaner = Cs ( (
- lp_reserved +
- lp_number +
- lp_string +
-1 )^1 )
-
-
-
-local template_e = [[
- local expr = xml.expressions
- return function(list,ll,l,order)
- return %s
- end
-]]
-
-local template_f_y = [[
- local finalizer = xml.finalizers['%s']['%s']
- return function(collection)
- return finalizer(collection,%s)
- end
-]]
-
-local template_f_n = [[
- return xml.finalizers['%s']['%s']
-]]
-
---
-
-local register_self = { kind = "axis", axis = "self" } -- , apply = apply_axis["self"] }
-local register_parent = { kind = "axis", axis = "parent" } -- , apply = apply_axis["parent"] }
-local register_descendant = { kind = "axis", axis = "descendant" } -- , apply = apply_axis["descendant"] }
-local register_child = { kind = "axis", axis = "child" } -- , apply = apply_axis["child"] }
-local register_descendant_or_self = { kind = "axis", axis = "descendant-or-self" } -- , apply = apply_axis["descendant-or-self"] }
-local register_root = { kind = "axis", axis = "root" } -- , apply = apply_axis["root"] }
-local register_ancestor = { kind = "axis", axis = "ancestor" } -- , apply = apply_axis["ancestor"] }
-local register_ancestor_or_self = { kind = "axis", axis = "ancestor-or-self" } -- , apply = apply_axis["ancestor-or-self"] }
-local register_attribute = { kind = "axis", axis = "attribute" } -- , apply = apply_axis["attribute"] }
-local register_namespace = { kind = "axis", axis = "namespace" } -- , apply = apply_axis["namespace"] }
-local register_following = { kind = "axis", axis = "following" } -- , apply = apply_axis["following"] }
-local register_following_sibling = { kind = "axis", axis = "following-sibling" } -- , apply = apply_axis["following-sibling"] }
-local register_preceding = { kind = "axis", axis = "preceding" } -- , apply = apply_axis["preceding"] }
-local register_preceding_sibling = { kind = "axis", axis = "preceding-sibling" } -- , apply = apply_axis["preceding-sibling"] }
-local register_reverse_sibling = { kind = "axis", axis = "reverse-sibling" } -- , apply = apply_axis["reverse-sibling"] }
-
-local register_auto_descendant_or_self = { kind = "axis", axis = "auto-descendant-or-self" } -- , apply = apply_axis["auto-descendant-or-self"] }
-local register_auto_descendant = { kind = "axis", axis = "auto-descendant" } -- , apply = apply_axis["auto-descendant"] }
-local register_auto_self = { kind = "axis", axis = "auto-self" } -- , apply = apply_axis["auto-self"] }
-local register_auto_child = { kind = "axis", axis = "auto-child" } -- , apply = apply_axis["auto-child"] }
-
-local register_initial_child = { kind = "axis", axis = "initial-child" } -- , apply = apply_axis["initial-child"] }
-
-local register_all_nodes = { kind = "nodes", nodetest = true, nodes = { true, false, false } }
-
-local skip = { }
-
-local function errorrunner_e(str,cnv)
- if not skip[str] then
- report_lpath("error in expression: %s => %s",str,cnv)
- skip[str] = cnv or str
- end
- return false
-end
-local function errorrunner_f(str,arg)
- report_lpath("error in finalizer: %s(%s)",str,arg or "")
- return false
-end
-
-local function register_nodes(nodetest,nodes)
- return { kind = "nodes", nodetest = nodetest, nodes = nodes }
-end
-
-local function register_expression(expression)
- local converted = lpegmatch(converter,expression)
- local runner = loadstring(format(template_e,converted))
- runner = (runner and runner()) or function() errorrunner_e(expression,converted) end
- return { kind = "expression", expression = expression, converted = converted, evaluator = runner }
-end
-
-local function register_finalizer(protocol,name,arguments)
- local runner
- if arguments and arguments ~= "" then
- runner = loadstring(format(template_f_y,protocol or xml.defaultprotocol,name,arguments))
- else
- runner = loadstring(format(template_f_n,protocol or xml.defaultprotocol,name))
- end
- runner = (runner and runner()) or function() errorrunner_f(name,arguments) end
- return { kind = "finalizer", name = name, arguments = arguments, finalizer = runner }
-end
-
-local expression = P { "ex",
- ex = "[" * C((V("sq") + V("dq") + (1 - S("[]")) + V("ex"))^0) * "]",
- sq = "'" * (1 - S("'"))^0 * "'",
- dq = '"' * (1 - S('"'))^0 * '"',
-}
-
-local arguments = P { "ar",
- ar = "(" * Cs((V("sq") + V("dq") + V("nq") + P(1-P(")")))^0) * ")",
- nq = ((1 - S("),'\""))^1) / function(s) return format("%q",s) end,
- sq = P("'") * (1 - P("'"))^0 * P("'"),
- dq = P('"') * (1 - P('"'))^0 * P('"'),
-}
-
--- todo: better arg parser
-
-local function register_error(str)
- return { kind = "error", error = format("unparsed: %s",str) }
-end
-
--- there is a difference in * and /*/ and so we need to catch a few special cases
-
-local special_1 = P("*") * Cc(register_auto_descendant) * Cc(register_all_nodes) -- last one not needed
-local special_2 = P("/") * Cc(register_auto_self)
-local special_3 = P("") * Cc(register_auto_self)
-
-local no_nextcolon = P(-1) + #(1-P(":")) -- newer lpeg needs the P(-1)
-local no_nextlparent = P(-1) + #(1-P("(")) -- newer lpeg needs the P(-1)
-
-local pathparser = Ct { "patterns", -- can be made a bit faster by moving some patterns outside
-
- patterns = spaces * V("protocol") * spaces * (
- ( V("special") * spaces * P(-1) ) +
- ( V("initial") * spaces * V("step") * spaces * (P("/") * spaces * V("step") * spaces)^0 )
- ),
-
- protocol = Cg(V("letters"),"protocol") * P("://") + Cg(Cc(nil),"protocol"),
-
- -- the / is needed for // as descendant or self is somewhat special
- -- step = (V("shortcuts") + V("axis") * spaces * V("nodes")^0 + V("error")) * spaces * V("expressions")^0 * spaces * V("finalizer")^0,
- step = ((V("shortcuts") + P("/") + V("axis")) * spaces * V("nodes")^0 + V("error")) * spaces * V("expressions")^0 * spaces * V("finalizer")^0,
-
- axis = V("descendant") + V("child") + V("parent") + V("self") + V("root") + V("ancestor") +
- V("descendant_or_self") + V("following_sibling") + V("following") +
- V("reverse_sibling") + V("preceding_sibling") + V("preceding") + V("ancestor_or_self") +
- #(1-P(-1)) * Cc(register_auto_child),
-
- special = special_1 + special_2 + special_3,
-
- initial = (P("/") * spaces * Cc(register_initial_child))^-1,
-
- error = (P(1)^1) / register_error,
-
- shortcuts_a = V("s_descendant_or_self") + V("s_descendant") + V("s_child") + V("s_parent") + V("s_self") + V("s_root") + V("s_ancestor"),
-
- shortcuts = V("shortcuts_a") * (spaces * "/" * spaces * V("shortcuts_a"))^0,
-
- s_descendant_or_self = (P("***/") + P("/")) * Cc(register_descendant_or_self), --- *** is a bonus
- s_descendant = P("**") * Cc(register_descendant),
- s_child = P("*") * no_nextcolon * Cc(register_child ),
- s_parent = P("..") * Cc(register_parent ),
- s_self = P("." ) * Cc(register_self ),
- s_root = P("^^") * Cc(register_root ),
- s_ancestor = P("^") * Cc(register_ancestor ),
-
- descendant = P("descendant::") * Cc(register_descendant ),
- child = P("child::") * Cc(register_child ),
- parent = P("parent::") * Cc(register_parent ),
- self = P("self::") * Cc(register_self ),
- root = P('root::') * Cc(register_root ),
- ancestor = P('ancestor::') * Cc(register_ancestor ),
- descendant_or_self = P('descendant-or-self::') * Cc(register_descendant_or_self ),
- ancestor_or_self = P('ancestor-or-self::') * Cc(register_ancestor_or_self ),
- -- attribute = P('attribute::') * Cc(register_attribute ),
- -- namespace = P('namespace::') * Cc(register_namespace ),
- following = P('following::') * Cc(register_following ),
- following_sibling = P('following-sibling::') * Cc(register_following_sibling ),
- preceding = P('preceding::') * Cc(register_preceding ),
- preceding_sibling = P('preceding-sibling::') * Cc(register_preceding_sibling ),
- reverse_sibling = P('reverse-sibling::') * Cc(register_reverse_sibling ),
-
- nodes = (V("nodefunction") * spaces * P("(") * V("nodeset") * P(")") + V("nodetest") * V("nodeset")) / register_nodes,
-
- expressions = expression / register_expression,
-
- letters = R("az")^1,
- name = (1-S("/[]()|:*!"))^1, -- make inline
- negate = P("!") * Cc(false),
-
- nodefunction = V("negate") + P("not") * Cc(false) + Cc(true),
- nodetest = V("negate") + Cc(true),
- nodename = (V("negate") + Cc(true)) * spaces * ((V("wildnodename") * P(":") * V("wildnodename")) + (Cc(false) * V("wildnodename"))),
- wildnodename = (C(V("name")) + P("*") * Cc(false)) * no_nextlparent,
- nodeset = spaces * Ct(V("nodename") * (spaces * P("|") * spaces * V("nodename"))^0) * spaces,
-
- finalizer = (Cb("protocol") * P("/")^-1 * C(V("name")) * arguments * P(-1)) / register_finalizer,
-
-}
-
-xmlpatterns.pathparser = pathparser
-
-local cache = { }
-
-local function nodesettostring(set,nodetest)
- local t = { }
- for i=1,#set,3 do
- local directive, ns, tg = set[i], set[i+1], set[i+2]
- if not ns or ns == "" then ns = "*" end
- if not tg or tg == "" then tg = "*" end
- tg = (tg == "@rt@" and "[root]") or format("%s:%s",ns,tg)
- t[i] = (directive and tg) or format("not(%s)",tg)
- end
- if nodetest == false then
- return format("not(%s)",concat(t,"|"))
- else
- return concat(t,"|")
- end
-end
-
-local function tagstostring(list)
- if #list == 0 then
- return "no elements"
- else
- local t = { }
- for i=1, #list do
- local li = list[i]
- local ns, tg = li.ns, li.tg
- if not ns or ns == "" then ns = "*" end
- if not tg or tg == "" then tg = "*" end
- t[i] = (tg == "@rt@" and "[root]") or format("%s:%s",ns,tg)
- end
- return concat(t," ")
- end
-end
-
-xml.nodesettostring = nodesettostring
-
-local lpath -- we have a harmless kind of circular reference
-
-local lshowoptions = { functions = false }
-
-local function lshow(parsed)
- if type(parsed) == "string" then
- parsed = lpath(parsed)
- end
- report_lpath("%s://%s => %s",parsed.protocol or xml.defaultprotocol,parsed.pattern,
- table.serialize(parsed,false,lshowoptions))
-end
-
-xml.lshow = lshow
-
-local function add_comment(p,str)
- local pc = p.comment
- if not pc then
- p.comment = { str }
- else
- pc[#pc+1] = str
- end
-end
-
-lpath = function (pattern) -- the gain of caching is rather minimal
- lpathcalls = lpathcalls + 1
- if type(pattern) == "table" then
- return pattern
- else
- local parsed = cache[pattern]
- if parsed then
- lpathcached = lpathcached + 1
- else
- parsed = lpegmatch(pathparser,pattern)
- if parsed then
- parsed.pattern = pattern
- local np = #parsed
- if np == 0 then
- parsed = { pattern = pattern, register_self, state = "parsing error" }
- report_lpath("parsing error in '%s'",pattern)
- lshow(parsed)
- else
- -- we could have done this with a more complex parser but this
- -- is cleaner
- local pi = parsed[1]
- if pi.axis == "auto-child" then
- if false then
- add_comment(parsed, "auto-child replaced by auto-descendant-or-self")
- parsed[1] = register_auto_descendant_or_self
- else
- add_comment(parsed, "auto-child replaced by auto-descendant")
- parsed[1] = register_auto_descendant
- end
- elseif pi.axis == "initial-child" and np > 1 and parsed[2].axis then
- add_comment(parsed, "initial-child removed") -- we could also make it a auto-self
- remove(parsed,1)
- end
- local np = #parsed -- can have changed
- if np > 1 then
- local pnp = parsed[np]
- if pnp.kind == "nodes" and pnp.nodetest == true then
- local nodes = pnp.nodes
- if nodes[1] == true and nodes[2] == false and nodes[3] == false then
- add_comment(parsed, "redundant final wildcard filter removed")
- remove(parsed,np)
- end
- end
- end
- end
- else
- parsed = { pattern = pattern }
- end
- cache[pattern] = parsed
- if trace_lparse and not trace_lprofile then
- lshow(parsed)
- end
- end
- return parsed
- end
-end
-
-xml.lpath = lpath
-
--- we can move all calls inline and then merge the trace back
--- technically we can combine axis and the next nodes which is
--- what we did before but this a bit cleaner (but slower too)
--- but interesting is that it's not that much faster when we
--- go inline
---
--- beware: we need to return a collection even when we filter
--- else the (simple) cache gets messed up
-
--- caching found lookups saves not that much (max .1 sec on a 8 sec run)
--- and it also messes up finalizers
-
--- watch out: when there is a finalizer, it's always called as there
--- can be cases that a finalizer returns (or does) something in case
--- there is no match; an example of this is count()
-
-local profiled = { } xml.profiled = profiled
-
-local function profiled_apply(list,parsed,nofparsed,order)
- local p = profiled[parsed.pattern]
- if p then
- p.tested = p.tested + 1
- else
- p = { tested = 1, matched = 0, finalized = 0 }
- profiled[parsed.pattern] = p
- end
- local collected = list
- for i=1,nofparsed do
- local pi = parsed[i]
- local kind = pi.kind
- if kind == "axis" then
- collected = apply_axis[pi.axis](collected)
- elseif kind == "nodes" then
- collected = apply_nodes(collected,pi.nodetest,pi.nodes)
- elseif kind == "expression" then
- collected = apply_expression(collected,pi.evaluator,order)
- elseif kind == "finalizer" then
- collected = pi.finalizer(collected) -- no check on # here
- p.matched = p.matched + 1
- p.finalized = p.finalized + 1
- return collected
- end
- if not collected or #collected == 0 then
- local pn = i < nofparsed and parsed[nofparsed]
- if pn and pn.kind == "finalizer" then
- collected = pn.finalizer(collected)
- p.finalized = p.finalized + 1
- return collected
- end
- return nil
- end
- end
- if collected then
- p.matched = p.matched + 1
- end
- return collected
-end
-
-local function traced_apply(list,parsed,nofparsed,order)
- if trace_lparse then
- lshow(parsed)
- end
- report_lpath("collecting: %s",parsed.pattern)
- report_lpath("root tags : %s",tagstostring(list))
- report_lpath("order : %s",order or "unset")
- local collected = list
- for i=1,nofparsed do
- local pi = parsed[i]
- local kind = pi.kind
- if kind == "axis" then
- collected = apply_axis[pi.axis](collected)
- report_lpath("% 10i : ax : %s",(collected and #collected) or 0,pi.axis)
- elseif kind == "nodes" then
- collected = apply_nodes(collected,pi.nodetest,pi.nodes)
- report_lpath("% 10i : ns : %s",(collected and #collected) or 0,nodesettostring(pi.nodes,pi.nodetest))
- elseif kind == "expression" then
- collected = apply_expression(collected,pi.evaluator,order)
- report_lpath("% 10i : ex : %s -> %s",(collected and #collected) or 0,pi.expression,pi.converted)
- elseif kind == "finalizer" then
- collected = pi.finalizer(collected)
- report_lpath("% 10i : fi : %s : %s(%s)",(type(collected) == "table" and #collected) or 0,parsed.protocol or xml.defaultprotocol,pi.name,pi.arguments or "")
- return collected
- end
- if not collected or #collected == 0 then
- local pn = i < nofparsed and parsed[nofparsed]
- if pn and pn.kind == "finalizer" then
- collected = pn.finalizer(collected)
- report_lpath("% 10i : fi : %s : %s(%s)",(type(collected) == "table" and #collected) or 0,parsed.protocol or xml.defaultprotocol,pn.name,pn.arguments or "")
- return collected
- end
- return nil
- end
- end
- return collected
-end
-
-local function normal_apply(list,parsed,nofparsed,order)
- local collected = list
- for i=1,nofparsed do
- local pi = parsed[i]
- local kind = pi.kind
- if kind == "axis" then
- local axis = pi.axis
- if axis ~= "self" then
- collected = apply_axis[axis](collected)
- end
- elseif kind == "nodes" then
- collected = apply_nodes(collected,pi.nodetest,pi.nodes)
- elseif kind == "expression" then
- collected = apply_expression(collected,pi.evaluator,order)
- elseif kind == "finalizer" then
- return pi.finalizer(collected)
- end
- if not collected or #collected == 0 then
- local pf = i < nofparsed and parsed[nofparsed].finalizer
- if pf then
- return pf(collected) -- can be anything
- end
- return nil
- end
- end
- return collected
-end
-
-
-local function applylpath(list,pattern)
- if not list then
- return
- end
- local parsed = cache[pattern]
- if parsed then
- lpathcalls = lpathcalls + 1
- lpathcached = lpathcached + 1
- elseif type(pattern) == "table" then
- lpathcalls = lpathcalls + 1
- parsed = pattern
- else
- parsed = lpath(pattern) or pattern
- end
- if not parsed then
- return
- end
- local nofparsed = #parsed
- if nofparsed == 0 then
- return -- something is wrong
- end
- if not trace_lpath then
- return normal_apply ({ list },parsed,nofparsed,list.mi)
- elseif trace_lprofile then
- return profiled_apply({ list },parsed,nofparsed,list.mi)
- else
- return traced_apply ({ list },parsed,nofparsed,list.mi)
- end
-end
-
-xml.applylpath = applylpath -- takes a table as first argment, which is what xml.filter will do
-
---[[ldx--
-This is the main filter function. It returns whatever is asked for.
---ldx]]--
-
-function xml.filter(root,pattern) -- no longer funny attribute handling here
- return applylpath(root,pattern)
-end
-
--- internal (parsed)
-
-expressions.child = function(e,pattern)
- return applylpath(e,pattern) -- todo: cache
-end
-expressions.count = function(e,pattern) -- what if pattern == empty or nil
- local collected = applylpath(e,pattern) -- todo: cache
- return pattern and (collected and #collected) or 0
-end
-
--- external
-
-expressions.oneof = function(s,...) -- slow
- local t = {...} for i=1,#t do if s == t[i] then return true end end return false
-end
-expressions.error = function(str)
- xml.errorhandler(format("unknown function in lpath expression: %s",tostring(str or "?")))
- return false
-end
-expressions.undefined = function(s)
- return s == nil
-end
-
-expressions.quit = function(s)
- if s or s == nil then
- quit_expression = true
- end
- return true
-end
-
-expressions.print = function(...)
- print(...)
- return true
-end
-
-expressions.contains = find
-expressions.find = find
-expressions.upper = upper
-expressions.lower = lower
-expressions.number = tonumber
-expressions.boolean = toboolean
-
-function expressions.contains(str,pattern)
- local t = type(str)
- if t == "string" then
- if find(str,pattern) then
- return true
- end
- elseif t == "table" then
- for i=1,#str do
- local d = str[i]
- if type(d) == "string" and find(d,pattern) then
- return true
- end
- end
- end
- return false
-end
-
--- user interface
-
-local function traverse(root,pattern,handle)
- report_lpath("use 'xml.selection' instead for '%s'",pattern)
- local collected = applylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local r = e.__p__
- handle(r,r.dt,e.ni)
- end
- end
-end
-
-local function selection(root,pattern,handle)
- local collected = applylpath(root,pattern)
- if collected then
- if handle then
- for c=1,#collected do
- handle(collected[c])
- end
- else
- return collected
- end
- end
-end
-
-xml.traverse = traverse -- old method, r, d, k
-xml.selection = selection -- new method, simple handle
-
-
--- generic function finalizer (independant namespace)
-
-local function dofunction(collected,fnc)
- if collected then
- local f = functions[fnc]
- if f then
- for c=1,#collected do
- f(collected[c])
- end
- else
- report_lpath("unknown function '%s'",fnc)
- end
- end
-end
-
-finalizers.xml["function"] = dofunction
-finalizers.tex["function"] = dofunction
-
--- functions
-
-expressions.text = function(e,n)
- local rdt = e.__p__.dt
- return (rdt and rdt[n]) or ""
-end
-
-expressions.name = function(e,n) -- ns + tg
- local found = false
- n = tonumber(n) or 0
- if n == 0 then
- found = type(e) == "table" and e
- elseif n < 0 then
- local d, k = e.__p__.dt, e.ni
- for i=k-1,1,-1 do
- local di = d[i]
- if type(di) == "table" then
- if n == -1 then
- found = di
- break
- else
- n = n + 1
- end
- end
- end
- else
- local d, k = e.__p__.dt, e.ni
- for i=k+1,#d,1 do
- local di = d[i]
- if type(di) == "table" then
- if n == 1 then
- found = di
- break
- else
- n = n - 1
- end
- end
- end
- end
- if found then
- local ns, tg = found.rn or found.ns or "", found.tg
- if ns ~= "" then
- return ns .. ":" .. tg
- else
- return tg
- end
- else
- return ""
- end
-end
-
-expressions.tag = function(e,n) -- only tg
- if not e then
- return ""
- else
- local found = false
- n = tonumber(n) or 0
- if n == 0 then
- found = (type(e) == "table") and e -- seems to fail
- elseif n < 0 then
- local d, k = e.__p__.dt, e.ni
- for i=k-1,1,-1 do
- local di = d[i]
- if type(di) == "table" then
- if n == -1 then
- found = di
- break
- else
- n = n + 1
- end
- end
- end
- else
- local d, k = e.__p__.dt, e.ni
- for i=k+1,#d,1 do
- local di = d[i]
- if type(di) == "table" then
- if n == 1 then
- found = di
- break
- else
- n = n - 1
- end
- end
- end
- end
- return (found and found.tg) or ""
- end
-end
-
---[[ldx--
-Often using an iterators looks nicer in the code than passing handler
-functions. The book describes how to use coroutines for that
-purpose ( ). This permits
-code like:
-
-
-for r, d, k in xml.elements(xml.load('text.xml'),"title") do
- print(d[k]) -- old method
-end
-for e in xml.collected(xml.load('text.xml'),"title") do
- print(e) -- new one
-end
-
---ldx]]--
-
-local wrap, yield = coroutine.wrap, coroutine.yield
-
-function xml.elements(root,pattern,reverse) -- r, d, k
- local collected = applylpath(root,pattern)
- if collected then
- if reverse then
- return wrap(function() for c=#collected,1,-1 do
- local e = collected[c] local r = e.__p__ yield(r,r.dt,e.ni)
- end end)
- else
- return wrap(function() for c=1,#collected do
- local e = collected[c] local r = e.__p__ yield(r,r.dt,e.ni)
- end end)
- end
- end
- return wrap(function() end)
-end
-
-function xml.collected(root,pattern,reverse) -- e
- local collected = applylpath(root,pattern)
- if collected then
- if reverse then
- return wrap(function() for c=#collected,1,-1 do yield(collected[c]) end end)
- else
- return wrap(function() for c=1,#collected do yield(collected[c]) end end)
- end
- end
- return wrap(function() end)
-end
-
--- handy
-
-function xml.inspect(collection,pattern)
- pattern = pattern or "."
- for e in xml.collected(collection,pattern or ".") do
- report_lpath("pattern %q\n\n%s\n",pattern,xml.tostring(e))
- end
-end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['lxml-mis'] = {
- version = 1.001,
- comment = "this module is the basis for the lxml-* ones",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local xml, lpeg, string = xml, lpeg, string
-
-local concat = table.concat
-local type, next, tonumber, tostring, setmetatable, loadstring = type, next, tonumber, tostring, setmetatable, loadstring
-local format, gsub, match = string.format, string.gsub, string.match
-local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
-local P, S, R, C, V, Cc, Cs = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.V, lpeg.Cc, lpeg.Cs
-
-lpegpatterns.xml = lpegpatterns.xml or { }
-local xmlpatterns = lpegpatterns.xml
-
---[[ldx--
-The following helper functions best belong to the lxml-ini
-module. Some are here because we need then in the mk
-document and other manuals, others came up when playing with
-this module. Since this module is also used in we've
-put them here instead of loading mode modules there then needed.
---ldx]]--
-
-local function xmlgsub(t,old,new) -- will be replaced
- local dt = t.dt
- if dt then
- for k=1,#dt do
- local v = dt[k]
- if type(v) == "string" then
- dt[k] = gsub(v,old,new)
- else
- xmlgsub(v,old,new)
- end
- end
- end
-end
-
-
-function xml.stripleadingspaces(dk,d,k) -- cosmetic, for manual
- if d and k then
- local dkm = d[k-1]
- if dkm and type(dkm) == "string" then
- local s = match(dkm,"\n(%s+)")
- xmlgsub(dk,"\n"..rep(" ",#s),"\n")
- end
- end
-end
-
-
-
--- 100 * 2500 * "oeps< oeps> oeps&" : gsub:lpeg|lpeg|lpeg
---
--- 1021:0335:0287:0247
-
--- 10 * 1000 * "oeps< oeps> oeps& asfjhalskfjh alskfjh alskfjh alskfjh ;al J;LSFDJ"
---
--- 1559:0257:0288:0190 (last one suggested by roberto)
-
--- escaped = Cs((S("<&>") / xml.escapes + 1)^0)
--- escaped = Cs((S("<")/"<" + S(">")/">" + S("&")/"&" + 1)^0)
-local normal = (1 - S("<&>"))^0
-local special = P("<")/"<" + P(">")/">" + P("&")/"&"
-local escaped = Cs(normal * (special * normal)^0)
-
--- 100 * 1000 * "oeps< oeps> oeps&" : gsub:lpeg == 0153:0280:0151:0080 (last one by roberto)
-
-local normal = (1 - S"&")^0
-local special = P("<")/"<" + P(">")/">" + P("&")/"&"
-local unescaped = Cs(normal * (special * normal)^0)
-
--- 100 * 5000 * "oeps oeps oeps " : gsub:lpeg == 623:501 msec (short tags, less difference)
-
-local cleansed = Cs(((P("<") * (1-P(">"))^0 * P(">"))/"" + 1)^0)
-
-xmlpatterns.escaped = escaped
-xmlpatterns.unescaped = unescaped
-xmlpatterns.cleansed = cleansed
-
-function xml.escaped (str) return lpegmatch(escaped,str) end
-function xml.unescaped(str) return lpegmatch(unescaped,str) end
-function xml.cleansed (str) return lpegmatch(cleansed,str) end
-
--- this might move
-
-function xml.fillin(root,pattern,str,check)
- local e = xml.first(root,pattern)
- if e then
- local n = #e.dt
- if not check or n == 0 or (n == 1 and e.dt[1] == "") then
- e.dt = { str }
- end
- end
-end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['lxml-aux'] = {
- version = 1.001,
- comment = "this module is the basis for the lxml-* ones",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- not all functions here make sense anymore vbut we keep them for
--- compatibility reasons
-
-local trace_manipulations = false trackers.register("lxml.manipulations", function(v) trace_manipulations = v end)
-
-local report_xml = logs.reporter("xml")
-
-local xml = xml
-
-local xmlconvert, xmlcopy, xmlname = xml.convert, xml.copy, xml.name
-local xmlinheritedconvert = xml.inheritedconvert
-local xmlapplylpath = xml.applylpath
-local xmlfilter = xml.filter
-
-local type, setmetatable, getmetatable = type, setmetatable, getmetatable
-local insert, remove, fastcopy, concat = table.insert, table.remove, table.fastcopy, table.concat
-local gmatch, gsub, format, find, strip = string.gmatch, string.gsub, string.format, string.find, string.strip
-local utfbyte = utf.byte
-
-local function report(what,pattern,c,e)
- report_xml("%s element '%s' (root: '%s', position: %s, index: %s, pattern: %s)",what,xmlname(e),xmlname(e.__p__),c,e.ni,pattern)
-end
-
-local function withelements(e,handle,depth)
- if e and handle then
- local edt = e.dt
- if edt then
- depth = depth or 0
- for i=1,#edt do
- local e = edt[i]
- if type(e) == "table" then
- handle(e,depth)
- withelements(e,handle,depth+1)
- end
- end
- end
- end
-end
-
-xml.withelements = withelements
-
-function xml.withelement(e,n,handle) -- slow
- if e and n ~= 0 and handle then
- local edt = e.dt
- if edt then
- if n > 0 then
- for i=1,#edt do
- local ei = edt[i]
- if type(ei) == "table" then
- if n == 1 then
- handle(ei)
- return
- else
- n = n - 1
- end
- end
- end
- elseif n < 0 then
- for i=#edt,1,-1 do
- local ei = edt[i]
- if type(ei) == "table" then
- if n == -1 then
- handle(ei)
- return
- else
- n = n + 1
- end
- end
- end
- end
- end
- end
-end
-
-function xml.each(root,pattern,handle,reverse)
- local collected = xmlapplylpath(root,pattern)
- if collected then
- if reverse then
- for c=#collected,1,-1 do
- handle(collected[c])
- end
- else
- for c=1,#collected do
- handle(collected[c])
- end
- end
- return collected
- end
-end
-
-function xml.processattributes(root,pattern,handle)
- local collected = xmlapplylpath(root,pattern)
- if collected and handle then
- for c=1,#collected do
- handle(collected[c].at)
- end
- end
- return collected
-end
-
---[[ldx--
-The following functions collect elements and texts.
---ldx]]--
-
--- are these still needed -> lxml-cmp.lua
-
-function xml.collect(root, pattern)
- return xmlapplylpath(root,pattern)
-end
-
-function xml.collecttexts(root, pattern, flatten) -- todo: variant with handle
- local collected = xmlapplylpath(root,pattern)
- if collected and flatten then
- local xmltostring = xml.tostring
- for c=1,#collected do
- collected[c] = xmltostring(collected[c].dt)
- end
- end
- return collected or { }
-end
-
-function xml.collect_tags(root, pattern, nonamespace)
- local collected = xmlapplylpath(root,pattern)
- if collected then
- local t, n = { }, 0
- for c=1,#collected do
- local e = collected[c]
- local ns, tg = e.ns, e.tg
- n = n + 1
- if nonamespace then
- t[n] = tg
- elseif ns == "" then
- t[n] = tg
- else
- t[n] = ns .. ":" .. tg
- end
- end
- return t
- end
-end
-
---[[ldx--
-We've now arrived at the functions that manipulate the tree.
---ldx]]--
-
-local no_root = { no_root = true }
-
-local function redo_ni(d)
- for k=1,#d do
- local dk = d[k]
- if type(dk) == "table" then
- dk.ni = k
- end
- end
-end
-
-local function xmltoelement(whatever,root)
- if not whatever then
- return nil
- end
- local element
- if type(whatever) == "string" then
- element = xmlinheritedconvert(whatever,root) -- beware, not really a root
- else
- element = whatever -- we assume a table
- end
- if element.error then
- return whatever -- string
- end
- if element then
- end
- return element
-end
-
-xml.toelement = xmltoelement
-
-local function copiedelement(element,newparent)
- if type(element) == "string" then
- return element
- else
- element = xmlcopy(element).dt
- if newparent and type(element) == "table" then
- element.__p__ = newparent
- end
- return element
- end
-end
-
-function xml.delete(root,pattern)
- if not pattern or pattern == "" then
- local p = root.__p__
- if p then
- if trace_manipulations then
- report('deleting',"--",c,root)
- end
- local d = p.dt
- remove(d,root.ni)
- redo_ni(d) -- can be made faster and inlined
- end
- else
- local collected = xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local p = e.__p__
- if p then
- if trace_manipulations then
- report('deleting',pattern,c,e)
- end
- local d = p.dt
- remove(d,e.ni)
- redo_ni(d) -- can be made faster and inlined
- end
- end
- end
- end
-end
-
-function xml.replace(root,pattern,whatever)
- local element = root and xmltoelement(whatever,root)
- local collected = element and xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local p = e.__p__
- if p then
- if trace_manipulations then
- report('replacing',pattern,c,e)
- end
- local d = p.dt
- d[e.ni] = copiedelement(element,p)
- redo_ni(d) -- probably not needed
- end
- end
- end
-end
-
-local function wrap(e,wrapper)
- local t = {
- rn = e.rn,
- tg = e.tg,
- ns = e.ns,
- at = e.at,
- dt = e.dt,
- __p__ = e,
- }
- setmetatable(t,getmetatable(e))
- e.rn = wrapper.rn or e.rn or ""
- e.tg = wrapper.tg or e.tg or ""
- e.ns = wrapper.ns or e.ns or ""
- e.at = fastcopy(wrapper.at)
- e.dt = { t }
-end
-
-function xml.wrap(root,pattern,whatever)
- if whatever then
- local wrapper = xmltoelement(whatever,root)
- local collected = xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- if trace_manipulations then
- report('wrapping',pattern,c,e)
- end
- wrap(e,wrapper)
- end
- end
- else
- wrap(root,xmltoelement(pattern))
- end
-end
-
-local function inject_element(root,pattern,whatever,prepend)
- local element = root and xmltoelement(whatever,root)
- local collected = element and xmlapplylpath(root,pattern)
- local function inject_e(e)
- local r = e.__p__
- local d, k, rri = r.dt, e.ni, r.ri
- local edt = (rri and d[rri].dt) or (d and d[k] and d[k].dt)
- if edt then
- local be, af
- local cp = copiedelement(element,e)
- if prepend then
- be, af = cp, edt
- else
- be, af = edt, cp
- end
- local bn = #be
- for i=1,#af do
- bn = bn + 1
- be[bn] = af[i]
- end
- if rri then
- r.dt[rri].dt = be
- else
- d[k].dt = be
- end
- redo_ni(d)
- end
- end
- if not collected then
- -- nothing
- elseif collected.tg then
- -- first or so
- inject_e(collected)
- else
- for c=1,#collected do
- inject_e(collected[c])
- end
- end
-end
-
-local function insert_element(root,pattern,whatever,before) -- todo: element als functie
- local element = root and xmltoelement(whatever,root)
- local collected = element and xmlapplylpath(root,pattern)
- local function insert_e(e)
- local r = e.__p__
- local d, k = r.dt, e.ni
- if not before then
- k = k + 1
- end
- insert(d,k,copiedelement(element,r))
- redo_ni(d)
- end
- if not collected then
- -- nothing
- elseif collected.tg then
- -- first or so
- insert_e(collected)
- else
- for c=1,#collected do
- insert_e(collected[c])
- end
- end
-end
-
-xml.insert_element = insert_element
-xml.insertafter = insert_element
-xml.insertbefore = function(r,p,e) insert_element(r,p,e,true) end
-xml.injectafter = inject_element
-xml.injectbefore = function(r,p,e) inject_element(r,p,e,true) end
-
-local function include(xmldata,pattern,attribute,recursive,loaddata)
- -- parse="text" (default: xml), encoding="" (todo)
- -- attribute = attribute or 'href'
- pattern = pattern or 'include'
- loaddata = loaddata or io.loaddata
- local collected = xmlapplylpath(xmldata,pattern)
- if collected then
- for c=1,#collected do
- local ek = collected[c]
- local name = nil
- local ekdt = ek.dt
- local ekat = ek.at
- local epdt = ek.__p__.dt
- if not attribute or attribute == "" then
- name = (type(ekdt) == "table" and ekdt[1]) or ekdt -- check, probably always tab or str
- end
- if not name then
- for a in gmatch(attribute or "href","([^|]+)") do
- name = ekat[a]
- if name then break end
- end
- end
- local data = (name and name ~= "" and loaddata(name)) or ""
- if data == "" then
- epdt[ek.ni] = "" -- xml.empty(d,k)
- elseif ekat["parse"] == "text" then
- -- for the moment hard coded
- epdt[ek.ni] = xml.escaped(data) -- d[k] = xml.escaped(data)
- else
- local xi = xmlinheritedconvert(data,xmldata)
- if not xi then
- epdt[ek.ni] = "" -- xml.empty(d,k)
- else
- if recursive then
- include(xi,pattern,attribute,recursive,loaddata)
- end
- epdt[ek.ni] = xml.body(xi) -- xml.assign(d,k,xi)
- end
- end
- end
- end
-end
-
-xml.include = include
-
-local function stripelement(e,nolines,anywhere)
- local edt = e.dt
- if edt then
- if anywhere then
- local t, n = { }, 0
- for e=1,#edt do
- local str = edt[e]
- if type(str) ~= "string" then
- n = n + 1
- t[n] = str
- elseif str ~= "" then
- -- todo: lpeg for each case
- if nolines then
- str = gsub(str,"%s+"," ")
- end
- str = gsub(str,"^%s*(.-)%s*$","%1")
- if str ~= "" then
- n = n + 1
- t[n] = str
- end
- end
- end
- e.dt = t
- else
- -- we can assume a regular sparse xml table with no successive strings
- -- otherwise we should use a while loop
- if #edt > 0 then
- -- strip front
- local str = edt[1]
- if type(str) ~= "string" then
- -- nothing
- elseif str == "" then
- remove(edt,1)
- else
- if nolines then
- str = gsub(str,"%s+"," ")
- end
- str = gsub(str,"^%s+","")
- if str == "" then
- remove(edt,1)
- else
- edt[1] = str
- end
- end
- end
- local nedt = #edt
- if nedt > 0 then
- -- strip end
- local str = edt[nedt]
- if type(str) ~= "string" then
- -- nothing
- elseif str == "" then
- remove(edt)
- else
- if nolines then
- str = gsub(str,"%s+"," ")
- end
- str = gsub(str,"%s+$","")
- if str == "" then
- remove(edt)
- else
- edt[nedt] = str
- end
- end
- end
- end
- end
- return e -- convenient
-end
-
-xml.stripelement = stripelement
-
-function xml.strip(root,pattern,nolines,anywhere) -- strips all leading and trailing spacing
- local collected = xmlapplylpath(root,pattern) -- beware, indices no longer are valid now
- if collected then
- for i=1,#collected do
- stripelement(collected[i],nolines,anywhere)
- end
- end
-end
-
-local function renamespace(root, oldspace, newspace) -- fast variant
- local ndt = #root.dt
- for i=1,ndt or 0 do
- local e = root[i]
- if type(e) == "table" then
- if e.ns == oldspace then
- e.ns = newspace
- if e.rn then
- e.rn = newspace
- end
- end
- local edt = e.dt
- if edt then
- renamespace(edt, oldspace, newspace)
- end
- end
- end
-end
-
-xml.renamespace = renamespace
-
-function xml.remaptag(root, pattern, newtg)
- local collected = xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- collected[c].tg = newtg
- end
- end
-end
-
-function xml.remapnamespace(root, pattern, newns)
- local collected = xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- collected[c].ns = newns
- end
- end
-end
-
-function xml.checknamespace(root, pattern, newns)
- local collected = xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- if (not e.rn or e.rn == "") and e.ns == "" then
- e.rn = newns
- end
- end
- end
-end
-
-function xml.remapname(root, pattern, newtg, newns, newrn)
- local collected = xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- e.tg, e.ns, e.rn = newtg, newns, newrn
- end
- end
-end
-
---[[ldx--
-Helper (for q2p).
---ldx]]--
-
-function xml.cdatatotext(e)
- local dt = e.dt
- if #dt == 1 then
- local first = dt[1]
- if first.tg == "@cd@" then
- e.dt = first.dt
- end
- else
- -- maybe option
- end
-end
-
--- local x = xml.convert("12 3 ")
--- xml.texttocdata(xml.first(x,"a"))
--- print(x) -- 2 3]]>
-
-function xml.texttocdata(e) -- could be a finalizer
- local dt = e.dt
- local s = xml.tostring(dt) -- no shortcut?
- e.tg = "@cd@"
- e.special = true
- e.ns = ""
- e.rn = ""
- e.dt = { s }
- e.at = nil
-end
-
--- local x = xml.convert("12 3 ")
--- xml.tocdata(xml.first(x,"a"))
--- print(x) -- 12 3]]>
-
-function xml.elementtocdata(e) -- could be a finalizer
- local dt = e.dt
- local s = xml.tostring(e) -- no shortcut?
- e.tg = "@cd@"
- e.special = true
- e.ns = ""
- e.rn = ""
- e.dt = { s }
- e.at = nil
-end
-
-xml.builtinentities = table.tohash { "amp", "quot", "apos", "lt", "gt" } -- used often so share
-
-local entities = characters and characters.entities or nil
-local builtinentities = xml.builtinentities
-
-function xml.addentitiesdoctype(root,option) -- we could also have a 'resolve' i.e. inline hex
- if not entities then
- require("char-ent")
- entities = characters.entities
- end
- if entities and root and root.tg == "@rt@" and root.statistics then
- local list = { }
- local hexify = option == "hexadecimal"
- for k, v in table.sortedhash(root.statistics.entities.names) do
- if not builtinentities[k] then
- local e = entities[k]
- if not e then
- e = format("[%s]",k)
- elseif hexify then
- e = format("%05X;",utfbyte(k))
- end
- list[#list+1] = format(" ",k,e)
- end
- end
- local dt = root.dt
- local n = dt[1].tg == "@pi@" and 2 or 1
- if #list > 0 then
- insert(dt, n, { "\n" })
- insert(dt, n, {
- tg = "@dt@", -- beware, doctype is unparsed
- dt = { format("Something [\n%s\n] ",concat(list)) },
- ns = "",
- special = true,
- })
- insert(dt, n, { "\n\n" })
- else
- -- insert(dt, n, { table.serialize(root.statistics) })
- end
- end
-end
-
--- local str = [==[
---
---
--- test test { test
---
---
--- ]==]
---
--- local x = xml.convert(str)
--- xml.addentitiesdoctype(x,"hexadecimal")
--- print(x)
-
---[[ldx--
-Here are a few synonyms.
---ldx]]--
-
-xml.all = xml.each
-xml.insert = xml.insertafter
-xml.inject = xml.injectafter
-xml.after = xml.insertafter
-xml.before = xml.insertbefore
-xml.process = xml.each
-
--- obsolete
-
-xml.obsolete = xml.obsolete or { }
-local obsolete = xml.obsolete
-
-xml.strip_whitespace = xml.strip obsolete.strip_whitespace = xml.strip
-xml.collect_elements = xml.collect obsolete.collect_elements = xml.collect
-xml.delete_element = xml.delete obsolete.delete_element = xml.delete
-xml.replace_element = xml.replace obsolete.replace_element = xml.replacet
-xml.each_element = xml.each obsolete.each_element = xml.each
-xml.process_elements = xml.process obsolete.process_elements = xml.process
-xml.insert_element_after = xml.insertafter obsolete.insert_element_after = xml.insertafter
-xml.insert_element_before = xml.insertbefore obsolete.insert_element_before = xml.insertbefore
-xml.inject_element_after = xml.injectafter obsolete.inject_element_after = xml.injectafter
-xml.inject_element_before = xml.injectbefore obsolete.inject_element_before = xml.injectbefore
-xml.process_attributes = xml.processattributes obsolete.process_attributes = xml.processattributes
-xml.collect_texts = xml.collecttexts obsolete.collect_texts = xml.collecttexts
-xml.inject_element = xml.inject obsolete.inject_element = xml.inject
-xml.remap_tag = xml.remaptag obsolete.remap_tag = xml.remaptag
-xml.remap_name = xml.remapname obsolete.remap_name = xml.remapname
-xml.remap_namespace = xml.remapnamespace obsolete.remap_namespace = xml.remapnamespace
-
--- new (probably ok)
-
-function xml.cdata(e)
- if e then
- local dt = e.dt
- if dt and #dt == 1 then
- local first = dt[1]
- return first.tg == "@cd@" and first.dt[1] or ""
- end
- end
- return ""
-end
-
-function xml.finalizers.xml.cdata(collected)
- if collected then
- local e = collected[1]
- if e then
- local dt = e.dt
- if dt and #dt == 1 then
- local first = dt[1]
- return first.tg == "@cd@" and first.dt[1] or ""
- end
- end
- end
- return ""
-end
-
-function xml.insertcomment(e,str,n) -- also insertcdata
- table.insert(e.dt,n or 1,{
- tg = "@cm@",
- ns = "",
- special = true,
- at = { },
- dt = { str },
- })
-end
-
-function xml.setcdata(e,str) -- also setcomment
- e.dt = { {
- tg = "@cd@",
- ns = "",
- special = true,
- at = { },
- dt = { str },
- } }
-end
-
--- maybe helpers like this will move to an autoloader
-
-function xml.separate(x,pattern)
- local collected = xmlapplylpath(x,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local d = e.dt
- if d == x then
- report_xml("warning: xml.separate changes root")
- x = d
- end
- local t, n = { "\n" }, 1
- local i, nd = 1, #d
- while i <= nd do
- while i <= nd do
- local di = d[i]
- if type(di) == "string" then
- if di == "\n" or find(di,"^%s+$") then -- first test is speedup
- i = i + 1
- else
- d[i] = strip(di)
- break
- end
- else
- break
- end
- end
- if i > nd then
- break
- end
- t[n+1] = "\n"
- t[n+2] = d[i]
- t[n+3] = "\n"
- n = n + 3
- i = i + 1
- end
- t[n+1] = "\n"
- setmetatable(t,getmetatable(d))
- e.dt = t
- end
- end
- return x
-end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['lxml-xml'] = {
- version = 1.001,
- comment = "this module is the basis for the lxml-* ones",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local concat = table.concat
-local find, lower, upper = string.find, string.lower, string.upper
-
-local xml = xml
-
-local finalizers = xml.finalizers.xml
-local xmlfilter = xml.filter -- we could inline this one for speed
-local xmltostring = xml.tostring
-local xmlserialize = xml.serialize
-local xmlcollected = xml.collected
-local xmlnewhandlers = xml.newhandlers
-
-local function first(collected) -- wrong ?
- return collected and collected[1]
-end
-
-local function last(collected)
- return collected and collected[#collected]
-end
-
-local function all(collected)
- return collected
-end
-
--- local function reverse(collected)
--- if collected then
--- local nc = #collected
--- if nc > 0 then
--- local reversed, r = { }, 0
--- for c=nc,1,-1 do
--- r = r + 1
--- reversed[r] = collected[c]
--- end
--- return reversed
--- else
--- return collected
--- end
--- end
--- end
-
-local reverse = table.reversed
-
-local function attribute(collected,name)
- if collected and #collected > 0 then
- local at = collected[1].at
- return at and at[name]
- end
-end
-
-local function att(id,name)
- local at = id.at
- return at and at[name]
-end
-
-local function count(collected)
- return collected and #collected or 0
-end
-
-local function position(collected,n)
- if not collected then
- return 0
- end
- local nc = #collected
- if nc == 0 then
- return 0
- end
- n = tonumber(n) or 0
- if n < 0 then
- return collected[nc + n + 1]
- elseif n > 0 then
- return collected[n]
- else
- return collected[1].mi or 0
- end
-end
-
-local function match(collected)
- return collected and #collected > 0 and collected[1].mi or 0 -- match
-end
-
-local function index(collected)
- return collected and #collected > 0 and collected[1].ni or 0 -- 0 is new
-end
-
-local function attributes(collected,arguments)
- if collected and #collected > 0 then
- local at = collected[1].at
- if arguments then
- return at[arguments]
- elseif next(at) then
- return at -- all of them
- end
- end
-end
-
-local function chainattribute(collected,arguments) -- todo: optional levels
- if collected and #collected > 0 then
- local e = collected[1]
- while e do
- local at = e.at
- if at then
- local a = at[arguments]
- if a then
- return a
- end
- else
- break -- error
- end
- e = e.__p__
- end
- end
- return ""
-end
-
-local function raw(collected) -- hybrid (not much different from text so it might go)
- if collected and #collected > 0 then
- local e = collected[1] or collected
- return e and xmltostring(e) or "" -- only first as we cannot concat function
- else
- return ""
- end
-end
-
---
-
-local xmltexthandler = xmlnewhandlers {
- name = "string",
- initialize = function()
- result = { }
- return result
- end,
- finalize = function()
- return concat(result)
- end,
- handle = function(...)
- result[#result+1] = concat { ... }
- end,
- escape = false,
-}
-
-local function xmltotext(root)
- local dt = root.dt
- if not dt then
- return ""
- end
- local nt = #dt -- string or table
- if nt == 0 then
- return ""
- elseif nt == 1 and type(dt[1]) == "string" then
- return dt[1] -- no escaping of " ' < > &
- else
- return xmlserialize(root,xmltexthandler) or ""
- end
-end
-
---
-
-local function text(collected) -- hybrid
- if collected then -- no # test here !
- local e = collected[1] or collected -- why fallback to element, how about cdata
- return e and xmltotext(e) or ""
- else
- return ""
- end
-end
-
-local function texts(collected)
- if not collected then
- return { } -- why no nil
- end
- local nc = #collected
- if nc == 0 then
- return { } -- why no nil
- end
- local t, n = { }, 0
- for c=1,nc do
- local e = collected[c]
- if e and e.dt then
- n = n + 1
- t[n] = e.dt
- end
- end
- return t
-end
-
-local function tag(collected,n)
- if not collected then
- return
- end
- local nc = #collected
- if nc == 0 then
- return
- end
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[nc-n+1]
- end
- return c and c.tg
-end
-
-local function name(collected,n)
- if not collected then
- return
- end
- local nc = #collected
- if nc == 0 then
- return
- end
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[nc-n+1]
- end
- if not c then
- -- sorry
- elseif c.ns == "" then
- return c.tg
- else
- return c.ns .. ":" .. c.tg
- end
-end
-
-local function tags(collected,nonamespace)
- if not collected then
- return
- end
- local nc = #collected
- if nc == 0 then
- return
- end
- local t, n = { }, 0
- for c=1,nc do
- local e = collected[c]
- local ns, tg = e.ns, e.tg
- n = n + 1
- if nonamespace or ns == "" then
- t[n] = tg
- else
- t[n] = ns .. ":" .. tg
- end
- end
- return t
-end
-
-local function empty(collected,spacesonly)
- if not collected then
- return true
- end
- local nc = #collected
- if nc == 0 then
- return true
- end
- for c=1,nc do
- local e = collected[c]
- if e then
- local edt = e.dt
- if edt then
- local n = #edt
- if n == 1 then
- local edk = edt[1]
- local typ = type(edk)
- if typ == "table" then
- return false
- elseif edk ~= "" then
- return false
- elseif spacesonly and not find(edk,"%S") then
- return false
- end
- elseif n > 1 then
- return false
- end
- end
- end
- end
- return true
-end
-
-finalizers.first = first
-finalizers.last = last
-finalizers.all = all
-finalizers.reverse = reverse
-finalizers.elements = all
-finalizers.default = all
-finalizers.attribute = attribute
-finalizers.att = att
-finalizers.count = count
-finalizers.position = position
-finalizers.match = match
-finalizers.index = index
-finalizers.attributes = attributes
-finalizers.chainattribute = chainattribute
-finalizers.text = text
-finalizers.texts = texts
-finalizers.tag = tag
-finalizers.name = name
-finalizers.tags = tags
-finalizers.empty = empty
-
--- shortcuts -- we could support xmlfilter(id,pattern,first)
-
-function xml.first(id,pattern)
- return first(xmlfilter(id,pattern))
-end
-
-function xml.last(id,pattern)
- return last(xmlfilter(id,pattern))
-end
-
-function xml.count(id,pattern)
- return count(xmlfilter(id,pattern))
-end
-
-function xml.attribute(id,pattern,a,default)
- return attribute(xmlfilter(id,pattern),a,default)
-end
-
-function xml.raw(id,pattern)
- if pattern then
- return raw(xmlfilter(id,pattern))
- else
- return raw(id)
- end
-end
-
-function xml.text(id,pattern) -- brrr either content or element (when cdata)
- if pattern then
- -- return text(xmlfilter(id,pattern))
- local collected = xmlfilter(id,pattern)
- return collected and #collected > 0 and xmltotext(collected[1]) or ""
- elseif id then
- -- return text(id)
- return xmltotext(id) or ""
- else
- return ""
- end
-end
-
-xml.content = text
-
---
-
-function xml.position(id,pattern,n) -- element
- return position(xmlfilter(id,pattern),n)
-end
-
-function xml.match(id,pattern) -- number
- return match(xmlfilter(id,pattern))
-end
-
-function xml.empty(id,pattern,spacesonly)
- return empty(xmlfilter(id,pattern),spacesonly)
-end
-
-xml.all = xml.filter
-xml.index = xml.position
-xml.found = xml.filter
-
--- a nice one:
-
-local function totable(x)
- local t = { }
- for e in xmlcollected(x[1] or x,"/*") do
- t[e.tg] = xmltostring(e.dt) or ""
- end
- return next(t) and t or nil
-end
-
-xml.table = totable
-finalizers.table = totable
-
-local function textonly(e,t)
- if e then
- local edt = e.dt
- if edt then
- for i=1,#edt do
- local e = edt[i]
- if type(e) == "table" then
- textonly(e,t)
- else
- t[#t+1] = e
- end
- end
- end
- end
- return t
-end
-
-function xml.textonly(e) -- no pattern
- return concat(textonly(e,{}))
-end
-
---
-
--- local x = xml.convert("12 3 ")
--- xml.filter(x,"**/lowerall()") print(x)
--- xml.filter(x,"**/upperall()") print(x)
-
-function finalizers.lowerall(collected)
- for c=1,#collected do
- local e = collected[c]
- if not e.special then
- e.tg = lower(e.tg)
- local eat = e.at
- if eat then
- local t = { }
- for k,v in next, eat do
- t[lower(k)] = v
- end
- e.at = t
- end
- end
- end
-end
-
-function finalizers.upperall(collected)
- for c=1,#collected do
- local e = collected[c]
- if not e.special then
- e.tg = upper(e.tg)
- local eat = e.at
- if eat then
- local t = { }
- for k,v in next, eat do
- t[upper(k)] = v
- end
- e.at = t
- end
- end
- end
-end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['data-ini'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files",
-}
-
-local gsub, find, gmatch, char = string.gsub, string.find, string.gmatch, string.char
-local concat = table.concat
-local next, type = next, type
-
-local filedirname, filebasename, fileextname, filejoin = file.dirname, file.basename, file.extname, file.join
-
-local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
-local trace_detail = false trackers.register("resolvers.details", function(v) trace_detail = v end)
-local trace_expansions = false trackers.register("resolvers.expansions", function(v) trace_expansions = v end)
-
-local report_initialization = logs.reporter("resolvers","initialization")
-
-local ostype, osname, ossetenv, osgetenv = os.type, os.name, os.setenv, os.getenv
-
--- The code here used to be part of a data-res but for convenience
--- we now split it over multiple files. As this file is now the
--- starting point we introduce resolvers here.
-
-resolvers = resolvers or { }
-local resolvers = resolvers
-
--- We don't want the kpse library to kick in. Also, we want to be able to
--- execute programs. Control over execution is implemented later.
-
-texconfig.kpse_init = false
-texconfig.shell_escape = 't'
-
-if kpse and kpse.default_texmfcnf then
- local default_texmfcnf = kpse.default_texmfcnf()
- -- looks more like context:
- default_texmfcnf = gsub(default_texmfcnf,"$SELFAUTOLOC","selfautoloc:")
- default_texmfcnf = gsub(default_texmfcnf,"$SELFAUTODIR","selfautodir:")
- default_texmfcnf = gsub(default_texmfcnf,"$SELFAUTOPARENT","selfautoparent:")
- default_texmfcnf = gsub(default_texmfcnf,"$HOME","home:")
- --
- environment.default_texmfcnf = default_texmfcnf
-end
-
-kpse = { original = kpse }
-
-setmetatable(kpse, {
- __index = function(kp,name)
- report_initialization("fatal error: kpse library is accessed (key: %s)",name)
- os.exit()
- end
-} )
-
--- First we check a couple of environment variables. Some might be
--- set already but we need then later on. We start with the system
--- font path.
-
-do
-
- local osfontdir = osgetenv("OSFONTDIR")
-
- if osfontdir and osfontdir ~= "" then
- -- ok
- elseif osname == "windows" then
- ossetenv("OSFONTDIR","c:/windows/fonts//")
- elseif osname == "macosx" then
- ossetenv("OSFONTDIR","$HOME/Library/Fonts//;/Library/Fonts//;/System/Library/Fonts//")
- end
-
-end
-
--- Next comes the user's home path. We need this as later on we have
--- to replace ~ with its value.
-
-do
-
- local homedir = osgetenv(ostype == "windows" and 'USERPROFILE' or 'HOME') or ''
-
- if not homedir or homedir == "" then
- homedir = char(127) -- we need a value, later we wil trigger on it
- end
-
- homedir = file.collapsepath(homedir)
-
- ossetenv("HOME", homedir) -- can be used in unix cnf files
- ossetenv("USERPROFILE",homedir) -- can be used in windows cnf files
-
- environment.homedir = homedir
-
-end
-
--- The following code sets the name of the own binary and its
--- path. This is fallback code as we have os.selfdir now.
-
-do
-
- local args = environment.originalarguments or arg -- this needs a cleanup
-
- local ownbin = environment.ownbin or args[-2] or arg[-2] or args[-1] or arg[-1] or arg[0] or "luatex"
- local ownpath = environment.ownpath or os.selfdir
-
- ownbin = file.collapsepath(ownbin)
- ownpath = file.collapsepath(ownpath)
-
- if not ownpath or ownpath == "" or ownpath == "unset" then
- ownpath = args[-1] or arg[-1]
- ownpath = ownpath and filedirname(gsub(ownpath,"\\","/"))
- if not ownpath or ownpath == "" then
- ownpath = args[-0] or arg[-0]
- ownpath = ownpath and filedirname(gsub(ownpath,"\\","/"))
- end
- local binary = ownbin
- if not ownpath or ownpath == "" then
- ownpath = ownpath and filedirname(binary)
- end
- if not ownpath or ownpath == "" then
- if os.binsuffix ~= "" then
- binary = file.replacesuffix(binary,os.binsuffix)
- end
- local path = osgetenv("PATH")
- if path then
- for p in gmatch(path,"[^"..io.pathseparator.."]+") do
- local b = filejoin(p,binary)
- if lfs.isfile(b) then
- -- we assume that after changing to the path the currentdir function
- -- resolves to the real location and use this side effect here; this
- -- trick is needed because on the mac installations use symlinks in the
- -- path instead of real locations
- local olddir = lfs.currentdir()
- if lfs.chdir(p) then
- local pp = lfs.currentdir()
- if trace_locating and p ~= pp then
- report_initialization("following symlink '%s' to '%s'",p,pp)
- end
- ownpath = pp
- lfs.chdir(olddir)
- else
- if trace_locating then
- report_initialization("unable to check path '%s'",p)
- end
- ownpath = p
- end
- break
- end
- end
- end
- end
- if not ownpath or ownpath == "" then
- ownpath = "."
- report_initialization("forcing fallback ownpath .")
- elseif trace_locating then
- report_initialization("using ownpath '%s'",ownpath)
- end
- end
-
- environment.ownbin = ownbin
- environment.ownpath = ownpath
-
-end
-
-resolvers.ownpath = environment.ownpath
-
-function resolvers.getownpath()
- return environment.ownpath
-end
-
--- The self variables permit us to use only a few (or even no)
--- environment variables.
-
-do
-
- local ownpath = environment.ownpath or dir.current()
-
- if ownpath then
- ossetenv('SELFAUTOLOC', file.collapsepath(ownpath))
- ossetenv('SELFAUTODIR', file.collapsepath(ownpath .. "/.."))
- ossetenv('SELFAUTOPARENT', file.collapsepath(ownpath .. "/../.."))
- else
- report_initialization("error: unable to locate ownpath")
- os.exit()
- end
-
-end
-
--- The running os:
-
--- todo: check is context sits here os.platform is more trustworthy
--- that the bin check as mtx-update runs from another path
-
-local texos = environment.texos or osgetenv("TEXOS")
-local texmfos = environment.texmfos or osgetenv('SELFAUTODIR')
-
-if not texos or texos == "" then
- texos = file.basename(texmfos)
-end
-
-ossetenv('TEXMFOS', texmfos) -- full bin path
-ossetenv('TEXOS', texos) -- partial bin parent
-ossetenv('SELFAUTOSYSTEM',os.platform) -- bonus
-
-environment.texos = texos
-environment.texmfos = texmfos
-
--- The current root:
-
-local texroot = environment.texroot or osgetenv("TEXROOT")
-
-if not texroot or texroot == "" then
- texroot = osgetenv('SELFAUTOPARENT')
- ossetenv('TEXROOT',texroot)
-end
-
-environment.texroot = file.collapsepath(texroot)
-
--- Tracing. Todo ...
-
-function resolvers.settrace(n) -- no longer number but: 'locating' or 'detail'
- if n then
- trackers.disable("resolvers.*")
- trackers.enable("resolvers."..n)
- end
-end
-
-resolvers.settrace(osgetenv("MTX_INPUT_TRACE"))
-
--- todo:
-
--- if profiler and osgetenv("MTX_PROFILE_RUN") == "YES" then
--- profiler.start("luatex-profile.log")
--- end
-
--- a forward definition
-
-if not resolvers.resolve then
- function resolvers.resolve (s) return s end
- function resolvers.unresolve(s) return s end
- function resolvers.repath (s) return s end
-end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['data-exp'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files",
-}
-
-local format, find, gmatch, lower, char, sub = string.format, string.find, string.gmatch, string.lower, string.char, string.sub
-local concat, sort = table.concat, table.sort
-local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
-local Ct, Cs, Cc, P, C, S = lpeg.Ct, lpeg.Cs, lpeg.Cc, lpeg.P, lpeg.C, lpeg.S
-local type, next = type, next
-
-local ostype = os.type
-local collapsepath = file.collapsepath
-
-local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
-local trace_expansions = false trackers.register("resolvers.expansions", function(v) trace_expansions = v end)
-
-local report_expansions = logs.reporter("resolvers","expansions")
-
-local resolvers = resolvers
-
--- As this bit of code is somewhat special it gets its own module. After
--- all, when working on the main resolver code, I don't want to scroll
--- past this every time. See data-obs.lua for the gsub variant.
-
-local function f_first(a,b)
- local t, n = { }, 0
- for s in gmatch(b,"[^,]+") do
- n = n + 1 ; t[n] = a .. s
- end
- return concat(t,",")
-end
-
-local function f_second(a,b)
- local t, n = { }, 0
- for s in gmatch(a,"[^,]+") do
- n = n + 1 ; t[n] = s .. b
- end
- return concat(t,",")
-end
-
--- kpsewhich --expand-braces '{a,b}{c,d}'
--- ac:bc:ad:bd
-
--- old {a,b}{c,d} => ac ad bc bd
---
--- local function f_both(a,b)
--- local t, n = { }, 0
--- for sa in gmatch(a,"[^,]+") do
--- for sb in gmatch(b,"[^,]+") do
--- n = n + 1 ; t[n] = sa .. sb
--- end
--- end
--- return concat(t,",")
--- end
---
--- new {a,b}{c,d} => ac bc ad bd
-
-local function f_both(a,b)
- local t, n = { }, 0
- for sb in gmatch(b,"[^,]+") do -- and not sa
- for sa in gmatch(a,"[^,]+") do -- sb
- n = n + 1 ; t[n] = sa .. sb
- end
- end
- return concat(t,",")
-end
-
-local left = P("{")
-local right = P("}")
-local var = P((1 - S("{}" ))^0)
-local set = P((1 - S("{},"))^0)
-local other = P(1)
-
-local l_first = Cs( ( Cc("{") * (C(set) * left * C(var) * right / f_first) * Cc("}") + other )^0 )
-local l_second = Cs( ( Cc("{") * (left * C(var) * right * C(set) / f_second) * Cc("}") + other )^0 )
-local l_both = Cs( ( Cc("{") * (left * C(var) * right * left * C(var) * right / f_both) * Cc("}") + other )^0 )
-local l_rest = Cs( ( left * var * (left/"") * var * (right/"") * var * right + other )^0 )
-
-local stripper_1 = lpeg.stripper ("{}@")
-local replacer_1 = lpeg.replacer { { ",}", ",@}" }, { "{,", "{@," }, }
-
-local function splitpathexpr(str, newlist, validate) -- I couldn't resist lpegging it (nice exercise).
- if trace_expansions then
- report_expansions("expanding variable '%s'",str)
- end
- local t, ok, done = newlist or { }, false, false
- local n = #t
- str = lpegmatch(replacer_1,str)
- repeat
- local old = str
- repeat
- local old = str
- str = lpegmatch(l_first, str)
- until old == str
- repeat
- local old = str
- str = lpegmatch(l_second,str)
- until old == str
- repeat
- local old = str
- str = lpegmatch(l_both, str)
- until old == str
- repeat
- local old = str
- str = lpegmatch(l_rest, str)
- until old == str
- until old == str -- or not find(str,"{")
- str = lpegmatch(stripper_1,str)
- if validate then
- for s in gmatch(str,"[^,]+") do
- s = validate(s)
- if s then
- n = n + 1 ; t[n] = s
- end
- end
- else
- for s in gmatch(str,"[^,]+") do
- n = n + 1 ; t[n] = s
- end
- end
- if trace_expansions then
- for k=1,#t do
- report_expansions("% 4i: %s",k,t[k])
- end
- end
- return t
-end
-
--- We could make the previous one public.
-
-local function validate(s)
- s = collapsepath(s) -- already keeps the //
- return s ~= "" and not find(s,"^!*unset/*$") and s
-end
-
-resolvers.validatedpath = validate -- keeps the trailing //
-
-function resolvers.expandedpathfromlist(pathlist)
- local newlist = { }
- for k=1,#pathlist do
- splitpathexpr(pathlist[k],newlist,validate)
- end
- return newlist
-end
-
--- {a,b,c,d}
--- a,b,c/{p,q,r},d
--- a,b,c/{p,q,r}/d/{x,y,z}//
--- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
--- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
--- a{b,c}{d,e}f
--- {a,b,c,d}
--- {a,b,c/{p,q,r},d}
--- {a,b,c/{p,q,r}/d/{x,y,z}//}
--- {a,b,c/{p,q/{x,y,z}},d/{p,q,r}}
--- {a,b,c/{p,q/{x,y,z},w}v,d/{p,q,r}}
--- {$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,.local,}/web2c}
-
-local cleanup = lpeg.replacer {
- { "!" , "" },
- { "\\" , "/" },
-}
-
-function resolvers.cleanpath(str) -- tricky, maybe only simple paths
- local doslashes = (P("\\")/"/" + 1)^0
- local donegation = (P("!") /"" )^0
- local homedir = lpegmatch(Cs(donegation * doslashes),environment.homedir or "")
- if homedir == "~" or homedir == "" or not lfs.isdir(homedir) then
- if trace_expansions then
- report_expansions("no home dir set, ignoring dependent paths")
- end
- function resolvers.cleanpath(str)
- if not str or find(str,"~") then
- return "" -- special case
- else
- return lpegmatch(cleanup,str)
- end
- end
- else
- local dohome = ((P("~")+P("$HOME"))/homedir)^0
- local cleanup = Cs(donegation * dohome * doslashes)
- function resolvers.cleanpath(str)
- return str and lpegmatch(cleanup,str) or ""
- end
- end
- return resolvers.cleanpath(str)
-end
-
--- print(resolvers.cleanpath(""))
--- print(resolvers.cleanpath("!"))
--- print(resolvers.cleanpath("~"))
--- print(resolvers.cleanpath("~/test"))
--- print(resolvers.cleanpath("!~/test"))
--- print(resolvers.cleanpath("~/test~test"))
-
--- This one strips quotes and funny tokens.
-
-local expandhome = P("~") / "$HOME" -- environment.homedir
-
-local dodouble = P('"')/"" * (expandhome + (1 - P('"')))^0 * P('"')/""
-local dosingle = P("'")/"" * (expandhome + (1 - P("'")))^0 * P("'")/""
-local dostring = (expandhome + 1 )^0
-
-local stripper = Cs(
- lpegpatterns.unspacer * (dosingle + dodouble + dostring) * lpegpatterns.unspacer
-)
-
-function resolvers.checkedvariable(str) -- assumes str is a string
- return type(str) == "string" and lpegmatch(stripper,str) or str
-end
-
--- The path splitter:
-
--- A config (optionally) has the paths split in tables. Internally
--- we join them and split them after the expansion has taken place. This
--- is more convenient.
-
-local cache = { }
-
------ splitter = lpeg.tsplitat(S(ostype == "windows" and ";" or ":;")) -- maybe add ,
-local splitter = lpeg.tsplitat(";") -- as we move towards urls, prefixes and use tables we no longer do :
-
-local backslashswapper = lpeg.replacer("\\","/")
-
-local function splitconfigurationpath(str) -- beware, this can be either a path or a { specification }
- if str then
- local found = cache[str]
- if not found then
- if str == "" then
- found = { }
- else
- local split = lpegmatch(splitter,lpegmatch(backslashswapper,str)) -- can be combined
- found = { }
- local noffound = 0
- for i=1,#split do
- local s = split[i]
- if not find(s,"^{*unset}*") then
- noffound = noffound + 1
- found[noffound] = s
- end
- end
- if trace_expansions then
- report_expansions("splitting path specification '%s'",str)
- for k=1,noffound do
- report_expansions("% 4i: %s",k,found[k])
- end
- end
- cache[str] = found
- end
- end
- return found
- end
-end
-
-resolvers.splitconfigurationpath = splitconfigurationpath
-
-function resolvers.splitpath(str)
- if type(str) == 'table' then
- return str
- else
- return splitconfigurationpath(str)
- end
-end
-
-function resolvers.joinpath(str)
- if type(str) == 'table' then
- return file.joinpath(str)
- else
- return str
- end
-end
-
--- The next function scans directories and returns a hash where the
--- entries are either strings or tables.
-
--- starting with . or .. etc or funny char
-
-
-
-
--- a lot of this caching can be stripped away when we have ssd's everywhere
---
--- we could cache all the (sub)paths here if needed
-
-local attributes, directory = lfs.attributes, lfs.dir
-
-local weird = P(".")^1 + lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
-local timer = { }
-local scanned = { }
-local nofscans = 0
-local scancache = { }
-
-local function scan(files,spec,path,n,m,r)
- local full = (path == "" and spec) or (spec .. path .. '/')
- local dirs = { }
- local nofdirs = 0
- for name in directory(full) do
- if not lpegmatch(weird,name) then
- local mode = attributes(full..name,'mode')
- if mode == 'file' then
- n = n + 1
- local f = files[name]
- if f then
- if type(f) == 'string' then
- files[name] = { f, path }
- else
- f[#f+1] = path
- end
- else -- probably unique anyway
- files[name] = path
- local lower = lower(name)
- if name ~= lower then
- files["remap:"..lower] = name
- r = r + 1
- end
- end
- elseif mode == 'directory' then
- m = m + 1
- nofdirs = nofdirs + 1
- if path ~= "" then
- dirs[nofdirs] = path..'/'..name
- else
- dirs[nofdirs] = name
- end
- end
- end
- end
- if nofdirs > 0 then
- sort(dirs)
- for i=1,nofdirs do
- files, n, m, r = scan(files,spec,dirs[i],n,m,r)
- end
- end
- scancache[sub(full,1,-2)] = files
- return files, n, m, r
-end
-
-local fullcache = { }
-
-function resolvers.scanfiles(path,branch,usecache)
- statistics.starttiming(timer)
- local realpath = resolvers.resolve(path) -- no shortcut
- if usecache then
- local files = fullcache[realpath]
- if files then
- if trace_locating then
- report_expansions("using caches scan of path '%s', branch '%s'",path,branch or path)
- end
- return files
- end
- end
- if trace_locating then
- report_expansions("scanning path '%s', branch '%s'",path,branch or path)
- end
- local files, n, m, r = scan({ },realpath .. '/',"",0,0,0)
- files.__path__ = path -- can be selfautoparent:texmf-whatever
- files.__files__ = n
- files.__directories__ = m
- files.__remappings__ = r
- if trace_locating then
- report_expansions("%s files found on %s directories with %s uppercase remappings",n,m,r)
- end
- if usecache then
- scanned[#scanned+1] = realpath
- fullcache[realpath] = files
- end
- nofscans = nofscans + 1
- statistics.stoptiming(timer)
- return files
-end
-
-local function simplescan(files,spec,path) -- first match only, no map and such
- local full = (path == "" and spec) or (spec .. path .. '/')
- local dirs = { }
- local nofdirs = 0
- for name in directory(full) do
- if not lpegmatch(weird,name) then
- local mode = attributes(full..name,'mode')
- if mode == 'file' then
- if not files[name] then
- -- only first match
- files[name] = path
- end
- elseif mode == 'directory' then
- nofdirs = nofdirs + 1
- if path ~= "" then
- dirs[nofdirs] = path..'/'..name
- else
- dirs[nofdirs] = name
- end
- end
- end
- end
- if nofdirs > 0 then
- sort(dirs)
- for i=1,nofdirs do
- files = simplescan(files,spec,dirs[i])
- end
- end
- return files
-end
-
-local simplecache = { }
-local nofsharedscans = 0
-
-function resolvers.simplescanfiles(path,branch,usecache)
- statistics.starttiming(timer)
- local realpath = resolvers.resolve(path) -- no shortcut
- if usecache then
- local files = simplecache[realpath]
- if not files then
- files = scancache[realpath]
- if files then
- nofsharedscans = nofsharedscans + 1
- end
- end
- if files then
- if trace_locating then
- report_expansions("using caches scan of path '%s', branch '%s'",path,branch or path)
- end
- return files
- end
- end
- if trace_locating then
- report_expansions("scanning path '%s', branch '%s'",path,branch or path)
- end
- local files = simplescan({ },realpath .. '/',"")
- if trace_locating then
- report_expansions("%s files found",table.count(files))
- end
- if usecache then
- scanned[#scanned+1] = realpath
- simplecache[realpath] = files
- end
- nofscans = nofscans + 1
- statistics.stoptiming(timer)
- return files
-end
-
-function resolvers.scandata()
- table.sort(scanned)
- return {
- n = nofscans,
- shared = nofsharedscans,
- time = statistics.elapsedtime(timer),
- paths = scanned,
- }
-end
-
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['data-env'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files",
-}
-
-local lower, gsub = string.lower, string.gsub
-
-local resolvers = resolvers
-
-local allocate = utilities.storage.allocate
-local setmetatableindex = table.setmetatableindex
-local fileextname = file.extname
-
-local formats = allocate()
-local suffixes = allocate()
-local dangerous = allocate()
-local suffixmap = allocate()
-
-resolvers.formats = formats
-resolvers.suffixes = suffixes
-resolvers.dangerous = dangerous
-resolvers.suffixmap = suffixmap
-
-local relations = allocate { -- todo: handlers also here
- core = {
- ofm = { -- will become obsolete
- names = { "ofm", "omega font metric", "omega font metrics" },
- variable = 'OFMFONTS',
- suffixes = { 'ofm', 'tfm' },
- },
- ovf = { -- will become obsolete
- names = { "ovf", "omega virtual font", "omega virtual fonts" },
- variable = 'OVFFONTS',
- suffixes = { 'ovf', 'vf' },
- },
- tfm = {
- names = { "tfm", "tex font metric", "tex font metrics" },
- variable = 'TFMFONTS',
- suffixes = { 'tfm' },
- },
- vf = {
- names = { "vf", "virtual font", "virtual fonts" },
- variable = 'VFFONTS',
- suffixes = { 'vf' },
- },
- otf = {
- names = { "otf", "opentype", "opentype font", "opentype fonts"},
- variable = 'OPENTYPEFONTS',
- suffixes = { 'otf' },
- },
- ttf = {
- names = { "ttf", "truetype", "truetype font", "truetype fonts", "truetype collection", "truetype collections", "truetype dictionary", "truetype dictionaries" },
- variable = 'TTFONTS',
- suffixes = { 'ttf', 'ttc', 'dfont' },
- },
- afm = {
- names = { "afm", "adobe font metric", "adobe font metrics" },
- variable = "AFMFONTS",
- suffixes = { "afm" },
- },
- pfb = {
- names = { "pfb", "type1", "type 1", "type1 font", "type 1 font", "type1 fonts", "type 1 fonts" },
- variable = 'T1FONTS',
- suffixes = { 'pfb', 'pfa' },
- },
- fea = {
- names = { "fea", "font feature", "font features", "font feature file", "font feature files" },
- variable = 'FONTFEATURES',
- suffixes = { 'fea' },
- },
- cid = {
- names = { "cid", "cid map", "cid maps", "cid file", "cid files" },
- variable = 'FONTCIDMAPS',
- suffixes = { 'cid', 'cidmap' },
- },
- fmt = {
- names = { "fmt", "format", "tex format" },
- variable = 'TEXFORMATS',
- suffixes = { 'fmt' },
- },
- mem = { -- will become obsolete
- names = { 'mem', "metapost format" },
- variable = 'MPMEMS',
- suffixes = { 'mem' },
- },
- mp = {
- names = { "mp" },
- variable = 'MPINPUTS',
- suffixes = { 'mp', 'mpvi', 'mpiv', 'mpii' },
- },
- tex = {
- names = { "tex" },
- variable = 'TEXINPUTS',
- suffixes = { 'tex', "mkvi", "mkiv", "mkii" },
- },
- icc = {
- names = { "icc", "icc profile", "icc profiles" },
- variable = 'ICCPROFILES',
- suffixes = { 'icc' },
- },
- texmfscripts = {
- names = { "texmfscript", "texmfscripts", "script", "scripts" },
- variable = 'TEXMFSCRIPTS',
- suffixes = { 'rb', 'pl', 'py' },
- },
- lua = {
- names = { "lua" },
- variable = 'LUAINPUTS',
- suffixes = { 'lua', 'luc', 'tma', 'tmc' },
- },
- lib = {
- names = { "lib" },
- variable = 'CLUAINPUTS',
- suffixes = os.libsuffix and { os.libsuffix } or { 'dll', 'so' },
- },
- bib = {
- names = { 'bib' },
- suffixes = { 'bib' },
- },
- bst = {
- names = { 'bst' },
- suffixes = { 'bst' },
- },
- fontconfig = {
- names = { 'fontconfig', 'fontconfig file', 'fontconfig files' },
- variable = 'FONTCONFIG_PATH',
- },
- },
- obsolete = {
- enc = {
- names = { "enc", "enc files", "enc file", "encoding files", "encoding file" },
- variable = 'ENCFONTS',
- suffixes = { 'enc' },
- },
- map = {
- names = { "map", "map files", "map file" },
- variable = 'TEXFONTMAPS',
- suffixes = { 'map' },
- },
- lig = {
- names = { "lig files", "lig file", "ligature file", "ligature files" },
- variable = 'LIGFONTS',
- suffixes = { 'lig' },
- },
- opl = {
- names = { "opl" },
- variable = 'OPLFONTS',
- suffixes = { 'opl' },
- },
- ovp = {
- names = { "ovp" },
- variable = 'OVPFONTS',
- suffixes = { 'ovp' },
- },
- },
- kpse = { -- subset
- base = {
- names = { 'base', "metafont format" },
- variable = 'MFBASES',
- suffixes = { 'base', 'bas' },
- },
- cmap = {
- names = { 'cmap', 'cmap files', 'cmap file' },
- variable = 'CMAPFONTS',
- suffixes = { 'cmap' },
- },
- cnf = {
- names = { 'cnf' },
- suffixes = { 'cnf' },
- },
- web = {
- names = { 'web' },
- suffixes = { 'web', 'ch' }
- },
- cweb = {
- names = { 'cweb' },
- suffixes = { 'w', 'web', 'ch' },
- },
- gf = {
- names = { 'gf' },
- suffixes = { 'gf' },
- },
- mf = {
- names = { 'mf' },
- variable = 'MFINPUTS',
- suffixes = { 'mf' },
- },
- mft = {
- names = { 'mft' },
- suffixes = { 'mft' },
- },
- pk = {
- names = { 'pk' },
- suffixes = { 'pk' },
- },
- },
-}
-
-resolvers.relations = relations
-
--- formats: maps a format onto a variable
-
-function resolvers.updaterelations()
- for category, categories in next, relations do
- for name, relation in next, categories do
- local rn = relation.names
- local rv = relation.variable
- local rs = relation.suffixes
- if rn and rv then
- for i=1,#rn do
- local rni = lower(gsub(rn[i]," ",""))
- formats[rni] = rv
- if rs then
- suffixes[rni] = rs
- for i=1,#rs do
- local rsi = rs[i]
- suffixmap[rsi] = rni
- end
- end
- end
- end
- if rs then
- end
- end
- end
-end
-
-resolvers.updaterelations() -- push this in the metatable -> newindex
-
-local function simplified(t,k)
- return k and rawget(t,lower(gsub(k," ",""))) or nil
-end
-
-setmetatableindex(formats, simplified)
-setmetatableindex(suffixes, simplified)
-setmetatableindex(suffixmap, simplified)
-
--- A few accessors, mostly for command line tool.
-
-function resolvers.suffixofformat(str)
- local s = suffixes[str]
- return s and s[1] or ""
-end
-
-function resolvers.suffixofformat(str)
- return suffixes[str] or { }
-end
-
-for name, format in next, formats do
- dangerous[name] = true -- still needed ?
-end
-
--- because vf searching is somewhat dangerous, we want to prevent
--- too liberal searching esp because we do a lookup on the current
--- path anyway; only tex (or any) is safe
-
-dangerous.tex = nil
-
-
--- more helpers
-
-function resolvers.formatofvariable(str)
- return formats[str] or ''
-end
-
-function resolvers.formatofsuffix(str) -- of file
- return suffixmap[fileextname(str)] or 'tex' -- so many map onto tex (like mkiv, cld etc)
-end
-
-function resolvers.variableofformat(str)
- return formats[str] or ''
-end
-
-function resolvers.variableofformatorsuffix(str)
- local v = formats[str]
- if v then
- return v
- end
- v = suffixmap[fileextname(str)]
- if v then
- return formats[v]
- end
- return ''
-end
-
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['data-tmp'] = {
- version = 1.100,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
---[[ldx--
-This module deals with caching data. It sets up the paths and
-implements loaders and savers for tables. Best is to set the
-following variable. When not set, the usual paths will be
-checked. Personally I prefer the (users) temporary path.
-
-
-TEXMFCACHE=$TMP;$TEMP;$TMPDIR;$TEMPDIR;$HOME;$TEXMFVAR;$VARTEXMF;.
-
-
-Currently we do no locking when we write files. This is no real
-problem because most caching involves fonts and the chance of them
-being written at the same time is small. We also need to extend
-luatools with a recache feature.
---ldx]]--
-
-local format, lower, gsub, concat = string.format, string.lower, string.gsub, table.concat
-local serialize, serializetofile = table.serialize, table.tofile
-local mkdirs, isdir = dir.mkdirs, lfs.isdir
-
-local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
-local trace_cache = false trackers.register("resolvers.cache", function(v) trace_cache = v end)
-
-local report_caches = logs.reporter("resolvers","caches")
-local report_resolvers = logs.reporter("resolvers","caching")
-
-local resolvers = resolvers
-
--- intermezzo
-
-local directive_cleanup = false directives.register("system.compile.cleanup", function(v) directive_cleanup = v end)
-local directive_strip = true directives.register("system.compile.strip", function(v) directive_strip = v end)
-
-local compile = utilities.lua.compile
-
-function utilities.lua.compile(luafile,lucfile,cleanup,strip)
- if cleanup == nil then cleanup = directive_cleanup end
- if strip == nil then strip = directive_strip end
- return compile(luafile,lucfile,cleanup,strip)
-end
-
--- end of intermezzo
-
-caches = caches or { }
-local caches = caches
-
-caches.base = caches.base or "luatex-cache"
-caches.more = caches.more or "context"
-caches.direct = false -- true is faster but may need huge amounts of memory
-caches.tree = false
-caches.force = true
-caches.ask = false
-caches.relocate = false
-caches.defaults = { "TMPDIR", "TEMPDIR", "TMP", "TEMP", "HOME", "HOMEPATH" }
-
-local writable, readables, usedreadables = nil, { }, { }
-
--- we could use a metatable for writable and readable but not yet
-
-local function identify()
- -- Combining the loops makes it messy. First we check the format cache path
- -- and when the last component is not present we try to create it.
- local texmfcaches = resolvers.cleanpathlist("TEXMFCACHE")
- if texmfcaches then
- for k=1,#texmfcaches do
- local cachepath = texmfcaches[k]
- if cachepath ~= "" then
- cachepath = resolvers.resolve(cachepath)
- cachepath = resolvers.cleanpath(cachepath)
- cachepath = file.collapsepath(cachepath)
- local valid = isdir(cachepath)
- if valid then
- if file.is_readable(cachepath) then
- readables[#readables+1] = cachepath
- if not writable and file.is_writable(cachepath) then
- writable = cachepath
- end
- end
- elseif not writable and caches.force then
- local cacheparent = file.dirname(cachepath)
- if file.is_writable(cacheparent) and true then -- we go on anyway (needed for mojca's kind of paths)
- if not caches.ask or io.ask(format("\nShould I create the cache path %s?",cachepath), "no", { "yes", "no" }) == "yes" then
- mkdirs(cachepath)
- if isdir(cachepath) and file.is_writable(cachepath) then
- report_caches("created: %s",cachepath)
- writable = cachepath
- readables[#readables+1] = cachepath
- end
- end
- end
- end
- end
- end
- end
- -- As a last resort we check some temporary paths but this time we don't
- -- create them.
- local texmfcaches = caches.defaults
- if texmfcaches then
- for k=1,#texmfcaches do
- local cachepath = texmfcaches[k]
- cachepath = resolvers.expansion(cachepath) -- was getenv
- if cachepath ~= "" then
- cachepath = resolvers.resolve(cachepath)
- cachepath = resolvers.cleanpath(cachepath)
- local valid = isdir(cachepath)
- if valid and file.is_readable(cachepath) then
- if not writable and file.is_writable(cachepath) then
- readables[#readables+1] = cachepath
- writable = cachepath
- break
- end
- end
- end
- end
- end
- -- Some extra checking. If we have no writable or readable path then we simply
- -- quit.
- if not writable then
- report_caches("fatal error: there is no valid writable cache path defined")
- os.exit()
- elseif #readables == 0 then
- report_caches("fatal error: there is no valid readable cache path defined")
- os.exit()
- end
- -- why here
- writable = dir.expandname(resolvers.cleanpath(writable)) -- just in case
- -- moved here
- local base, more, tree = caches.base, caches.more, caches.tree or caches.treehash() -- we have only one writable tree
- if tree then
- caches.tree = tree
- writable = mkdirs(writable,base,more,tree)
- for i=1,#readables do
- readables[i] = file.join(readables[i],base,more,tree)
- end
- else
- writable = mkdirs(writable,base,more)
- for i=1,#readables do
- readables[i] = file.join(readables[i],base,more)
- end
- end
- -- end
- if trace_cache then
- for i=1,#readables do
- report_caches("using readable path '%s' (order %s)",readables[i],i)
- end
- report_caches("using writable path '%s'",writable)
- end
- identify = function()
- return writable, readables
- end
- return writable, readables
-end
-
-function caches.usedpaths()
- local writable, readables = identify()
- if #readables > 1 then
- local result = { }
- for i=1,#readables do
- local readable = readables[i]
- if usedreadables[i] or readable == writable then
- result[#result+1] = format("readable: '%s' (order %s)",readable,i)
- end
- end
- result[#result+1] = format("writable: '%s'",writable)
- return result
- else
- return writable
- end
-end
-
-function caches.configfiles()
- return concat(resolvers.instance.specification,";")
-end
-
-function caches.hashed(tree)
- tree = gsub(tree,"\\$","/")
- tree = gsub(tree,"/+$","")
- tree = lower(tree)
- local hash = md5.hex(tree)
- if trace_cache or trace_locating then
- report_caches("hashing tree %s, hash %s",tree,hash)
- end
- return hash
-end
-
-function caches.treehash()
- local tree = caches.configfiles()
- if not tree or tree == "" then
- return false
- else
- return caches.hashed(tree)
- end
-end
-
-local r_cache, w_cache = { }, { } -- normally w in in r but who cares
-
-local function getreadablepaths(...) -- we can optimize this as we have at most 2 tags
- local tags = { ... }
- local hash = concat(tags,"/")
- local done = r_cache[hash]
- if not done then
- local writable, readables = identify() -- exit if not found
- if #tags > 0 then
- done = { }
- for i=1,#readables do
- done[i] = file.join(readables[i],...)
- end
- else
- done = readables
- end
- r_cache[hash] = done
- end
- return done
-end
-
-local function getwritablepath(...)
- local tags = { ... }
- local hash = concat(tags,"/")
- local done = w_cache[hash]
- if not done then
- local writable, readables = identify() -- exit if not found
- if #tags > 0 then
- done = mkdirs(writable,...)
- else
- done = writable
- end
- w_cache[hash] = done
- end
- return done
-end
-
-caches.getreadablepaths = getreadablepaths
-caches.getwritablepath = getwritablepath
-
-function caches.getfirstreadablefile(filename,...)
- local rd = getreadablepaths(...)
- for i=1,#rd do
- local path = rd[i]
- local fullname = file.join(path,filename)
- if file.is_readable(fullname) then
- usedreadables[i] = true
- return fullname, path
- end
- end
- return caches.setfirstwritablefile(filename,...)
-end
-
-function caches.setfirstwritablefile(filename,...)
- local wr = getwritablepath(...)
- local fullname = file.join(wr,filename)
- return fullname, wr
-end
-
-function caches.define(category,subcategory) -- for old times sake
- return function()
- return getwritablepath(category,subcategory)
- end
-end
-
-function caches.setluanames(path,name)
- return path .. "/" .. name .. ".tma", path .. "/" .. name .. ".tmc"
-end
-
-function caches.loaddata(readables,name)
- if type(readables) == "string" then
- readables = { readables }
- end
- for i=1,#readables do
- local path = readables[i]
- local tmaname, tmcname = caches.setluanames(path,name)
- local loader = loadfile(tmcname) or loadfile(tmaname)
- if loader then
- loader = loader()
- collectgarbage("step")
- return loader
- end
- end
- return false
-end
-
-function caches.is_writable(filepath,filename)
- local tmaname, tmcname = caches.setluanames(filepath,filename)
- return file.is_writable(tmaname)
-end
-
-local saveoptions = { compact = true }
-
-function caches.savedata(filepath,filename,data,raw)
- local tmaname, tmcname = caches.setluanames(filepath,filename)
- local reduce, simplify = true, true
- if raw then
- reduce, simplify = false, false
- end
- data.cache_uuid = os.uuid()
- if caches.direct then
- file.savedata(tmaname,serialize(data,true,saveoptions))
- else
- serializetofile(tmaname,data,true,saveoptions)
- end
- utilities.lua.compile(tmaname,tmcname)
-end
-
--- moved from data-res:
-
-local content_state = { }
-
-function caches.contentstate()
- return content_state or { }
-end
-
-function caches.loadcontent(cachename,dataname)
- local name = caches.hashed(cachename)
- local full, path = caches.getfirstreadablefile(name ..".lua","trees")
- local filename = file.join(path,name)
- local blob = loadfile(filename .. ".luc") or loadfile(filename .. ".lua")
- if blob then
- local data = blob()
- if data and data.content then
- if data.type == dataname then
- if data.version == resolvers.cacheversion then
- content_state[#content_state+1] = data.uuid
- if trace_locating then
- report_resolvers("loading '%s' for '%s' from '%s'",dataname,cachename,filename)
- end
- return data.content
- else
- report_resolvers("skipping '%s' for '%s' from '%s' (version mismatch)",dataname,cachename,filename)
- end
- else
- report_resolvers("skipping '%s' for '%s' from '%s' (datatype mismatch)",dataname,cachename,filename)
- end
- elseif trace_locating then
- report_resolvers("skipping '%s' for '%s' from '%s' (no content)",dataname,cachename,filename)
- end
- elseif trace_locating then
- report_resolvers("skipping '%s' for '%s' from '%s' (invalid file)",dataname,cachename,filename)
- end
-end
-
-function caches.collapsecontent(content)
- for k, v in next, content do
- if type(v) == "table" and #v == 1 then
- content[k] = v[1]
- end
- end
-end
-
-function caches.savecontent(cachename,dataname,content)
- local name = caches.hashed(cachename)
- local full, path = caches.setfirstwritablefile(name ..".lua","trees")
- local filename = file.join(path,name) -- is full
- local luaname, lucname = filename .. ".lua", filename .. ".luc"
- if trace_locating then
- report_resolvers("preparing '%s' for '%s'",dataname,cachename)
- end
- local data = {
- type = dataname,
- root = cachename,
- version = resolvers.cacheversion,
- date = os.date("%Y-%m-%d"),
- time = os.date("%H:%M:%S"),
- content = content,
- uuid = os.uuid(),
- }
- local ok = io.savedata(luaname,serialize(data,true))
- if ok then
- if trace_locating then
- report_resolvers("category '%s', cachename '%s' saved in '%s'",dataname,cachename,luaname)
- end
- if utilities.lua.compile(luaname,lucname) then
- if trace_locating then
- report_resolvers("'%s' compiled to '%s'",dataname,lucname)
- end
- return true
- else
- if trace_locating then
- report_resolvers("compiling failed for '%s', deleting file '%s'",dataname,lucname)
- end
- os.remove(lucname)
- end
- elseif trace_locating then
- report_resolvers("unable to save '%s' in '%s' (access error)",dataname,luaname)
- end
-end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['data-met'] = {
- version = 1.100,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local find, format = string.find, string.format
-local sequenced = table.sequenced
-local addurlscheme, urlhashed = url.addscheme, url.hashed
-
-local trace_locating = false
-
-trackers.register("resolvers.locating", function(v) trace_methods = v end)
-trackers.register("resolvers.methods", function(v) trace_methods = v end)
-
-
-local report_methods = logs.reporter("resolvers","methods")
-
-local allocate = utilities.storage.allocate
-
-local resolvers = resolvers
-
-local registered = { }
-
-local function splitmethod(filename) -- todo: filetype in specification
- if not filename then
- return { scheme = "unknown", original = filename }
- end
- if type(filename) == "table" then
- return filename -- already split
- end
- filename = file.collapsepath(filename)
- if not find(filename,"://") then
- return { scheme = "file", path = filename, original = filename, filename = filename }
- end
- local specification = url.hashed(filename)
- if not specification.scheme or specification.scheme == "" then
- return { scheme = "file", path = filename, original = filename, filename = filename }
- else
- return specification
- end
-end
-
-resolvers.splitmethod = splitmethod -- bad name but ok
-
--- the second argument is always analyzed (saves time later on) and the original
--- gets passed as original but also as argument
-
-local function methodhandler(what,first,...) -- filename can be nil or false
- local method = registered[what]
- if method then
- local how, namespace = method.how, method.namespace
- if how == "uri" or how == "url" then
- local specification = splitmethod(first)
- local scheme = specification.scheme
- local resolver = namespace and namespace[scheme]
- if resolver then
- if trace_methods then
- report_methods("resolver: method=%s, how=%s, scheme=%s, argument=%s",what,how,scheme,first)
- end
- return resolver(specification,...)
- else
- resolver = namespace.default or namespace.file
- if resolver then
- if trace_methods then
- report_methods("resolver: method=%s, how=%s, default, argument=%s",what,how,first)
- end
- return resolver(specification,...)
- elseif trace_methods then
- report_methods("resolver: method=%s, how=%s, no handler",what,how)
- end
- end
- elseif how == "tag" then
- local resolver = namespace and namespace[first]
- if resolver then
- if trace_methods then
- report_methods("resolver: method=%s, how=%s, tag=%s",what,how,first)
- end
- return resolver(...)
- else
- resolver = namespace.default or namespace.file
- if resolver then
- if trace_methods then
- report_methods("resolver: method=%s, how=%s, default",what,how)
- end
- return resolver(...)
- elseif trace_methods then
- report_methods("resolver: method=%s, how=%s, unknown",what,how)
- end
- end
- end
- else
- report_methods("resolver: method=%s, unknown",what)
- end
-end
-
-resolvers.methodhandler = methodhandler
-
-function resolvers.registermethod(name,namespace,how)
- registered[name] = { how = how or "tag", namespace = namespace }
- namespace["byscheme"] = function(scheme,filename,...)
- if scheme == "file" then
- return methodhandler(name,filename,...)
- else
- return methodhandler(name,addurlscheme(filename,scheme),...)
- end
- end
-end
-
-local concatinators = allocate { notfound = file.join } -- concatinate paths
-local locators = allocate { notfound = function() end } -- locate databases
-local hashers = allocate { notfound = function() end } -- load databases
-local generators = allocate { notfound = function() end } -- generate databases
-
-resolvers.concatinators = concatinators
-resolvers.locators = locators
-resolvers.hashers = hashers
-resolvers.generators = generators
-
-local registermethod = resolvers.registermethod
-
-registermethod("concatinators",concatinators,"tag")
-registermethod("locators", locators, "uri")
-registermethod("hashers", hashers, "uri")
-registermethod("generators", generators, "uri")
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['data-res'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files",
-}
-
--- In practice we will work within one tds tree, but i want to keep
--- the option open to build tools that look at multiple trees, which is
--- why we keep the tree specific data in a table. We used to pass the
--- instance but for practical purposes we now avoid this and use a
--- instance variable. We always have one instance active (sort of global).
-
--- todo: cache:/// home:/// selfautoparent:/// (sometime end 2012)
-
-local format, gsub, find, lower, upper, match, gmatch = string.format, string.gsub, string.find, string.lower, string.upper, string.match, string.gmatch
-local concat, insert, sortedkeys = table.concat, table.insert, table.sortedkeys
-local next, type, rawget = next, type, rawget
-local os = os
-
-local P, S, R, C, Cc, Cs, Ct, Carg = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.Cc, lpeg.Cs, lpeg.Ct, lpeg.Carg
-local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
-
-local filedirname = file.dirname
-local filebasename = file.basename
-local fileextname = file.extname
-local filejoin = file.join
-local collapsepath = file.collapsepath
-local joinpath = file.joinpath
-local allocate = utilities.storage.allocate
-local setmetatableindex = table.setmetatableindex
-
-local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
-local trace_detail = false trackers.register("resolvers.details", function(v) trace_detail = v end)
-local trace_expansions = false trackers.register("resolvers.expansions", function(v) trace_expansions = v end)
-
-local report_resolving = logs.reporter("resolvers","resolving")
-
-local resolvers = resolvers
-
-local expandedpathfromlist = resolvers.expandedpathfromlist
-local checkedvariable = resolvers.checkedvariable
-local splitconfigurationpath = resolvers.splitconfigurationpath
-local methodhandler = resolvers.methodhandler
-
-local initializesetter = utilities.setters.initialize
-
-local ostype, osname, osenv, ossetenv, osgetenv = os.type, os.name, os.env, os.setenv, os.getenv
-
-resolvers.cacheversion = '1.0.1'
-resolvers.configbanner = ''
-resolvers.homedir = environment.homedir
-resolvers.criticalvars = allocate { "SELFAUTOLOC", "SELFAUTODIR", "SELFAUTOPARENT", "TEXMFCNF", "TEXMF", "TEXOS" }
-resolvers.luacnfname = 'texmfcnf.lua'
-resolvers.luacnfstate = "unknown"
-
--- The web2c tex binaries as well as kpse have built in paths for the configuration
--- files and there can be a depressing truckload of them. This is actually the weak
--- spot of a distribution. So we don't want:
---
--- resolvers.luacnfspec = '{$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,}/web2c}'
---
--- but instead use:
---
--- resolvers.luacnfspec = 'selfautoparent:{/texmf{-local,}{,/web2c}}'
---
--- which does not make texlive happy as there is a texmf-local tree one level up
--- (sigh), so we need this. We can assume web2c as mkiv does not run on older
--- texlives anyway.
---
--- texlive:
---
--- selfautodir:
--- selfautoparent:
--- selfautodir:share/texmf-local/web2c
--- selfautodir:share/texmf/web2c
--- selfautodir:texmf-local/web2c
--- selfautodir:texmf/web2c
--- selfautoparent:share/texmf-local/web2c
--- selfautoparent:share/texmf/web2c
--- selfautoparent:texmf-local/web2c
--- selfautoparent:texmf/web2c
---
--- minimals:
---
--- home:texmf/web2c
--- selfautoparent:texmf-local/web2c
--- selfautoparent:texmf-context/web2c
--- selfautoparent:texmf/web2c
-
-if environment.default_texmfcnf then
- -- unfortunately we now have quite some overkill in the spec (not so nice on a network)
- resolvers.luacnfspec = environment.default_texmfcnf
-else
- -- resolvers.luacnfspec = "selfautoparent:texmf{-local,-context,}/web2c"
- resolvers.luacnfspec = "{selfautoloc:,selfautodir:,selfautoparent:}{,/texmf{-local,}/web2c}"
-end
-
-resolvers.luacnfspec = 'home:texmf/web2c;' .. resolvers.luacnfspec
-
--- which (as we want users to use the web2c path) be can be simplified to this:
---
--- if environment and environment.ownpath and string.find(environment.ownpath,"[\\/]texlive[\\/]") then
--- resolvers.luacnfspec = 'selfautodir:/texmf-local/web2c,selfautoparent:/texmf-local/web2c,selfautoparent:/texmf/web2c'
--- else
--- resolvers.luacnfspec = 'selfautoparent:/texmf-local/web2c,selfautoparent:/texmf/web2c'
--- end
-
-
-
-local unset_variable = "unset"
-
-local formats = resolvers.formats
-local suffixes = resolvers.suffixes
-local dangerous = resolvers.dangerous
-local suffixmap = resolvers.suffixmap
-
-resolvers.defaultsuffixes = { "tex" } -- "mkiv", "cld" -- too tricky
-
-resolvers.instance = resolvers.instance or nil -- the current one (slow access)
-local instance = resolvers.instance or nil -- the current one (fast access)
-
--- An instance has an environment (coming from the outside, kept raw), variables
--- (coming from the configuration file), and expansions (variables with nested
--- variables replaced). One can push something into the outer environment and
--- its internal copy, but only the later one will be the raw unprefixed variant.
-
-function resolvers.setenv(key,value,raw)
- if instance then
- -- this one will be consulted first when we stay inside
- -- the current environment (prefixes are not resolved here)
- instance.environment[key] = value
- -- we feed back into the environment, and as this is used
- -- by other applications (via os.execute) we need to make
- -- sure that prefixes are resolve
- ossetenv(key,raw and value or resolvers.resolve(value))
- end
-end
-
--- Beware we don't want empty here as this one can be called early on
--- and therefore we use rawget.
-
-local function getenv(key)
- local value = rawget(instance.environment,key)
- if value and value ~= "" then
- return value
- else
- local e = osgetenv(key)
- return e ~= nil and e ~= "" and checkedvariable(e) or ""
- end
-end
-
-resolvers.getenv = getenv
-resolvers.env = getenv
-
--- We are going to use some metatable trickery where we backtrack from
--- expansion to variable to environment.
-
-local function resolve(k)
- return instance.expansions[k]
-end
-
-local dollarstripper = lpeg.stripper("$")
-local inhibitstripper = P("!")^0 * Cs(P(1)^0)
-local backslashswapper = lpeg.replacer("\\","/")
-
-local somevariable = P("$") / ""
-local somekey = C(R("az","AZ","09","__","--")^1)
-local somethingelse = P(";") * ((1-S("!{}/\\"))^1 * P(";") / "")
- + P(";") * (P(";") / "")
- + P(1)
-local variableexpander = Cs( (somevariable * (somekey/resolve) + somethingelse)^1 )
-
-local cleaner = P("\\") / "/" + P(";") * S("!{}/\\")^0 * P(";")^1 / ";"
-local variablecleaner = Cs((cleaner + P(1))^0)
-
-local somevariable = R("az","AZ","09","__","--")^1 / resolve
-local variable = (P("$")/"") * (somevariable + (P("{")/"") * somevariable * (P("}")/""))
-local variableresolver = Cs((variable + P(1))^0)
-
-local function expandedvariable(var)
- return lpegmatch(variableexpander,var) or var
-end
-
-function resolvers.newinstance() -- todo: all vars will become lowercase and alphanum only
-
- if trace_locating then
- report_resolving("creating instance")
- end
-
- local environment, variables, expansions, order = allocate(), allocate(), allocate(), allocate()
-
- local newinstance = {
- environment = environment,
- variables = variables,
- expansions = expansions,
- order = order,
- files = allocate(),
- setups = allocate(),
- found = allocate(),
- foundintrees = allocate(),
- hashes = allocate(),
- hashed = allocate(),
- specification = allocate(),
- lists = allocate(),
- data = allocate(), -- only for loading
- fakepaths = allocate(),
- remember = true,
- diskcache = true,
- renewcache = false,
- renewtree = false,
- loaderror = false,
- savelists = true,
- pattern = nil, -- lists
- force_suffixes = true,
- }
-
- setmetatableindex(variables,function(t,k)
- local v
- for i=1,#order do
- v = order[i][k]
- if v ~= nil then
- t[k] = v
- return v
- end
- end
- if v == nil then
- v = ""
- end
- t[k] = v
- return v
- end)
-
- setmetatableindex(environment, function(t,k)
- local v = osgetenv(k)
- if v == nil then
- v = variables[k]
- end
- if v ~= nil then
- v = checkedvariable(v) or ""
- end
- v = resolvers.repath(v) -- for taco who has a : separated osfontdir
- t[k] = v
- return v
- end)
-
- setmetatableindex(expansions, function(t,k)
- local v = environment[k]
- if type(v) == "string" then
- v = lpegmatch(variableresolver,v)
- v = lpegmatch(variablecleaner,v)
- end
- t[k] = v
- return v
- end)
-
- return newinstance
-
-end
-
-function resolvers.setinstance(someinstance) -- only one instance is active
- instance = someinstance
- resolvers.instance = someinstance
- return someinstance
-end
-
-function resolvers.reset()
- return resolvers.setinstance(resolvers.newinstance())
-end
-
-local function reset_hashes()
- instance.lists = { }
- instance.found = { }
-end
-
-local slash = P("/")
-
-local pathexpressionpattern = Cs (
- Cc("^") * (
- Cc("%") * S(".-")
- + slash^2 * P(-1) / "/.*"
- + slash^2 / "/.-/"
- + (1-slash) * P(-1) * Cc("/")
- + P(1)
- )^1 * Cc("$") -- yes or no $
-)
-
-local cache = { }
-
-local function makepathexpression(str)
- if str == "." then
- return "^%./$"
- else
- local c = cache[str]
- if not c then
- c = lpegmatch(pathexpressionpattern,str)
- cache[str] = c
- end
- return c
- end
-end
-
-local function reportcriticalvariables(cnfspec)
- if trace_locating then
- for i=1,#resolvers.criticalvars do
- local k = resolvers.criticalvars[i]
- local v = resolvers.getenv(k) or "unknown" -- this one will not resolve !
- report_resolving("variable '%s' set to '%s'",k,v)
- end
- report_resolving()
- if cnfspec then
- if type(cnfspec) == "table" then
- report_resolving("using configuration specification '%s'",concat(cnfspec,","))
- else
- report_resolving("using configuration specification '%s'",cnfspec)
- end
- end
- report_resolving()
- end
- reportcriticalvariables = function() end
-end
-
-local function identify_configuration_files()
- local specification = instance.specification
- if #specification == 0 then
- local cnfspec = getenv('TEXMFCNF')
- if cnfspec == "" then
- cnfspec = resolvers.luacnfspec
- resolvers.luacnfstate = "default"
- else
- resolvers.luacnfstate = "environment"
- end
- reportcriticalvariables(cnfspec)
- local cnfpaths = expandedpathfromlist(resolvers.splitpath(cnfspec))
- local luacnfname = resolvers.luacnfname
- for i=1,#cnfpaths do
- local filename = collapsepath(filejoin(cnfpaths[i],luacnfname))
- local realname = resolvers.resolve(filename)
- if lfs.isfile(realname) then
- specification[#specification+1] = filename
- if trace_locating then
- report_resolving("found configuration file '%s'",realname)
- end
- elseif trace_locating then
- report_resolving("unknown configuration file '%s'",realname)
- end
- end
- if trace_locating then
- report_resolving()
- end
- elseif trace_locating then
- report_resolving("configuration files already identified")
- end
-end
-
-local function load_configuration_files()
- local specification = instance.specification
- if #specification > 0 then
- local luacnfname = resolvers.luacnfname
- for i=1,#specification do
- local filename = specification[i]
- local pathname = filedirname(filename)
- local filename = filejoin(pathname,luacnfname)
- local realname = resolvers.resolve(filename) -- no shortcut
- local blob = loadfile(realname)
- if blob then
- local setups = instance.setups
- local data = blob()
- local parent = data and data.parent
- if parent then
- local filename = filejoin(pathname,parent)
- local realname = resolvers.resolve(filename) -- no shortcut
- local blob = loadfile(realname)
- if blob then
- local parentdata = blob()
- if parentdata then
- report_resolving("loading configuration file '%s'",filename)
- data = table.merged(parentdata,data)
- end
- end
- end
- data = data and data.content
- if data then
- if trace_locating then
- report_resolving("loading configuration file '%s'",filename)
- report_resolving()
- end
- local variables = data.variables or { }
- local warning = false
- for k, v in next, data do
- local variant = type(v)
- if variant == "table" then
- initializesetter(filename,k,v)
- elseif variables[k] == nil then
- if trace_locating and not warning then
- report_resolving("variables like '%s' in configuration file '%s' should move to the 'variables' subtable",
- k,resolvers.resolve(filename))
- warning = true
- end
- variables[k] = v
- end
- end
- setups[pathname] = variables
- if resolvers.luacnfstate == "default" then
- -- the following code is not tested
- local cnfspec = variables["TEXMFCNF"]
- if cnfspec then
- if trace_locating then
- report_resolving("reloading configuration due to TEXMF redefinition")
- end
- -- we push the value into the main environment (osenv) so
- -- that it takes precedence over the default one and therefore
- -- also over following definitions
- resolvers.setenv('TEXMFCNF',cnfspec) -- resolves prefixes
- -- we now identify and load the specified configuration files
- instance.specification = { }
- identify_configuration_files()
- load_configuration_files()
- -- we prevent further overload of the configuration variable
- resolvers.luacnfstate = "configuration"
- -- we quit the outer loop
- break
- end
- end
-
- else
- if trace_locating then
- report_resolving("skipping configuration file '%s' (no content)",filename)
- end
- setups[pathname] = { }
- instance.loaderror = true
- end
- elseif trace_locating then
- report_resolving("skipping configuration file '%s' (no valid format)",filename)
- end
- instance.order[#instance.order+1] = instance.setups[pathname]
- if instance.loaderror then
- break
- end
- end
- elseif trace_locating then
- report_resolving("warning: no lua configuration files found")
- end
-end
-
--- scheme magic ... database loading
-
-local function load_file_databases()
- instance.loaderror, instance.files = false, allocate()
- if not instance.renewcache then
- local hashes = instance.hashes
- for k=1,#hashes do
- local hash = hashes[k]
- resolvers.hashers.byscheme(hash.type,hash.name)
- if instance.loaderror then break end
- end
- end
-end
-
-local function locate_file_databases()
- -- todo: cache:// and tree:// (runtime)
- local texmfpaths = resolvers.expandedpathlist('TEXMF')
- if #texmfpaths > 0 then
- for i=1,#texmfpaths do
- local path = collapsepath(texmfpaths[i])
- local stripped = lpegmatch(inhibitstripper,path) -- the !! thing
- if stripped ~= "" then
- local runtime = stripped == path
- path = resolvers.cleanpath(path)
- local spec = resolvers.splitmethod(stripped)
- if runtime and (spec.noscheme or spec.scheme == "file") then
- stripped = "tree:///" .. stripped
- elseif spec.scheme == "cache" or spec.scheme == "file" then
- stripped = spec.path
- end
- if trace_locating then
- if runtime then
- report_resolving("locating list of '%s' (runtime) (%s)",path,stripped)
- else
- report_resolving("locating list of '%s' (cached)",path)
- end
- end
- methodhandler('locators',stripped)
- end
- end
- if trace_locating then
- report_resolving()
- end
- elseif trace_locating then
- report_resolving("no texmf paths are defined (using TEXMF)")
- end
-end
-
-local function generate_file_databases()
- local hashes = instance.hashes
- for k=1,#hashes do
- local hash = hashes[k]
- methodhandler('generators',hash.name)
- end
- if trace_locating then
- report_resolving()
- end
-end
-
-local function save_file_databases() -- will become cachers
- for i=1,#instance.hashes do
- local hash = instance.hashes[i]
- local cachename = hash.name
- if hash.cache then
- local content = instance.files[cachename]
- caches.collapsecontent(content)
- if trace_locating then
- report_resolving("saving tree '%s'",cachename)
- end
- caches.savecontent(cachename,"files",content)
- elseif trace_locating then
- report_resolving("not saving runtime tree '%s'",cachename)
- end
- end
-end
-
-function resolvers.renew(hashname)
- if hashname and hashname ~= "" then
- local expanded = resolvers.expansion(hashname) or ""
- if expanded ~= "" then
- if trace_locating then
- report_resolving("identifying tree '%s' from '%s'",expanded,hashname)
- end
- hashname = expanded
- else
- if trace_locating then
- report_resolving("identifying tree '%s'",hashname)
- end
- end
- local realpath = resolvers.resolve(hashname)
- if lfs.isdir(realpath) then
- if trace_locating then
- report_resolving("using path '%s'",realpath)
- end
- methodhandler('generators',hashname)
- -- could be shared
- local content = instance.files[hashname]
- caches.collapsecontent(content)
- if trace_locating then
- report_resolving("saving tree '%s'",hashname)
- end
- caches.savecontent(hashname,"files",content)
- -- till here
- else
- report_resolving("invalid path '%s'",realpath)
- end
- end
-end
-
-local function load_databases()
- locate_file_databases()
- if instance.diskcache and not instance.renewcache then
- load_file_databases()
- if instance.loaderror then
- generate_file_databases()
- save_file_databases()
- end
- else
- generate_file_databases()
- if instance.renewcache then
- save_file_databases()
- end
- end
-end
-
-function resolvers.appendhash(type,name,cache)
- -- safeguard ... tricky as it's actually a bug when seen twice
- if not instance.hashed[name] then
- if trace_locating then
- report_resolving("hash '%s' appended",name)
- end
- insert(instance.hashes, { type = type, name = name, cache = cache } )
- instance.hashed[name] = cache
- end
-end
-
-function resolvers.prependhash(type,name,cache)
- -- safeguard ... tricky as it's actually a bug when seen twice
- if not instance.hashed[name] then
- if trace_locating then
- report_resolving("hash '%s' prepended",name)
- end
- insert(instance.hashes, 1, { type = type, name = name, cache = cache } )
- instance.hashed[name] = cache
- end
+local function tagstostring(list)
+ if #list==0 then
+ return "no elements"
+ else
+ local t={}
+ for i=1,#list do
+ local li=list[i]
+ local ns,tg=li.ns,li.tg
+ if not ns or ns=="" then ns="*" end
+ if not tg or tg=="" then tg="*" end
+ t[i]=(tg=="@rt@" and "[root]") or format("%s:%s",ns,tg)
+ end
+ return concat(t," ")
+ end
+end
+xml.nodesettostring=nodesettostring
+local lpath
+local lshowoptions={ functions=false }
+local function lshow(parsed)
+ if type(parsed)=="string" then
+ parsed=lpath(parsed)
+ end
+ report_lpath("%s://%s => %s",parsed.protocol or xml.defaultprotocol,parsed.pattern,
+ table.serialize(parsed,false,lshowoptions))
end
-
-function resolvers.extendtexmfvariable(specification) -- crap, we could better prepend the hash
- local t = resolvers.splitpath(getenv('TEXMF'))
- insert(t,1,specification)
- local newspec = concat(t,";")
- if instance.environment["TEXMF"] then
- instance.environment["TEXMF"] = newspec
- elseif instance.variables["TEXMF"] then
- instance.variables["TEXMF"] = newspec
+xml.lshow=lshow
+local function add_comment(p,str)
+ local pc=p.comment
+ if not pc then
+ p.comment={ str }
+ else
+ pc[#pc+1]=str
+ end
+end
+lpath=function (pattern)
+ lpathcalls=lpathcalls+1
+ if type(pattern)=="table" then
+ return pattern
+ else
+ local parsed=cache[pattern]
+ if parsed then
+ lpathcached=lpathcached+1
else
- -- weird
- end
- reset_hashes()
-end
-
-function resolvers.splitexpansions()
- local ie = instance.expansions
- for k,v in next, ie do
- local t, tn, h, p = { }, 0, { }, splitconfigurationpath(v)
- for kk=1,#p do
- local vv = p[kk]
- if vv ~= "" and not h[vv] then
- tn = tn + 1
- t[tn] = vv
- h[vv] = true
- end
- end
- if #t > 1 then
- ie[k] = t
+ parsed=lpegmatch(pathparser,pattern)
+ if parsed then
+ parsed.pattern=pattern
+ local np=#parsed
+ if np==0 then
+ parsed={ pattern=pattern,register_self,state="parsing error" }
+ report_lpath("parsing error in pattern: %s",pattern)
+ lshow(parsed)
else
- ie[k] = t[1]
- end
+ local pi=parsed[1]
+ if pi.axis=="auto-child" then
+ if false then
+ add_comment(parsed,"auto-child replaced by auto-descendant-or-self")
+ parsed[1]=register_auto_descendant_or_self
+ else
+ add_comment(parsed,"auto-child replaced by auto-descendant")
+ parsed[1]=register_auto_descendant
+ end
+ elseif pi.axis=="initial-child" and np>1 and parsed[2].axis then
+ add_comment(parsed,"initial-child removed")
+ remove(parsed,1)
+ end
+ local np=#parsed
+ if np>1 then
+ local pnp=parsed[np]
+ if pnp.kind=="nodes" and pnp.nodetest==true then
+ local nodes=pnp.nodes
+ if nodes[1]==true and nodes[2]==false and nodes[3]==false then
+ add_comment(parsed,"redundant final wildcard filter removed")
+ remove(parsed,np)
+ end
+ end
+ end
+ end
+ else
+ parsed={ pattern=pattern }
+ end
+ cache[pattern]=parsed
+ if trace_lparse and not trace_lprofile then
+ lshow(parsed)
+ end
end
+ return parsed
+ end
end
-
--- end of split/join code
-
--- we used to have 'files' and 'configurations' so therefore the following
--- shared function
-
-function resolvers.datastate()
- return caches.contentstate()
+xml.lpath=lpath
+local profiled={} xml.profiled=profiled
+local function profiled_apply(list,parsed,nofparsed,order)
+ local p=profiled[parsed.pattern]
+ if p then
+ p.tested=p.tested+1
+ else
+ p={ tested=1,matched=0,finalized=0 }
+ profiled[parsed.pattern]=p
+ end
+ local collected=list
+ for i=1,nofparsed do
+ local pi=parsed[i]
+ local kind=pi.kind
+ if kind=="axis" then
+ collected=apply_axis[pi.axis](collected)
+ elseif kind=="nodes" then
+ collected=apply_nodes(collected,pi.nodetest,pi.nodes)
+ elseif kind=="expression" then
+ collected=apply_expression(collected,pi.evaluator,order)
+ elseif kind=="finalizer" then
+ collected=pi.finalizer(collected)
+ p.matched=p.matched+1
+ p.finalized=p.finalized+1
+ return collected
+ end
+ if not collected or #collected==0 then
+ local pn=i %s",(collected and #collected) or 0,pi.expression,pi.converted)
+ elseif kind=="finalizer" then
+ collected=pi.finalizer(collected)
+ report_lpath("% 10i : fi : %s : %s(%s)",(type(collected)=="table" and #collected) or 0,parsed.protocol or xml.defaultprotocol,pi.name,pi.arguments or "")
+ return collected
+ end
+ if not collected or #collected==0 then
+ local pn=i 0 then
- instance.lists, done = { }, { }
+local function selection(root,pattern,handle)
+ local collected=applylpath(root,pattern)
+ if collected then
+ if handle then
+ for c=1,#collected do
+ handle(collected[c])
+ end
+ else
+ return collected
end
+ end
end
-
-function resolvers.registerextrapath(paths,subpaths)
- local ep = instance.extra_paths or { }
- local oldn = #ep
- local newn = oldn
- if paths and paths ~= "" then
- if subpaths and subpaths ~= "" then
- for p in gmatch(paths,"[^,]+") do
- -- we gmatch each step again, not that fast, but used seldom
- for s in gmatch(subpaths,"[^,]+") do
- local ps = p .. "/" .. s
- if not done[ps] then
- newn = newn + 1
- ep[newn] = resolvers.cleanpath(ps)
- done[ps] = true
- end
- end
- end
+xml.traverse=traverse
+xml.selection=selection
+local function dofunction(collected,fnc,...)
+ if collected then
+ local f=functions[fnc]
+ if f then
+ for c=1,#collected do
+ f(collected[c],...)
+ end
+ else
+ report_lpath("unknown function %a",fnc)
+ end
+ end
+end
+finalizers.xml["function"]=dofunction
+finalizers.tex["function"]=dofunction
+expressions.text=function(e,n)
+ local rdt=e.__p__.dt
+ return rdt and rdt[n] or ""
+end
+expressions.name=function(e,n)
+ local found=false
+ n=tonumber(n) or 0
+ if n==0 then
+ found=type(e)=="table" and e
+ elseif n<0 then
+ local d,k=e.__p__.dt,e.ni
+ for i=k-1,1,-1 do
+ local di=d[i]
+ if type(di)=="table" then
+ if n==-1 then
+ found=di
+ break
else
- for p in gmatch(paths,"[^,]+") do
- if not done[p] then
- newn = newn + 1
- ep[newn] = resolvers.cleanpath(p)
- done[p] = true
- end
- end
- end
- elseif subpaths and subpaths ~= "" then
- for i=1,oldn do
- -- we gmatch each step again, not that fast, but used seldom
- for s in gmatch(subpaths,"[^,]+") do
- local ps = ep[i] .. "/" .. s
- if not done[ps] then
- newn = newn + 1
- ep[newn] = resolvers.cleanpath(ps)
- done[ps] = true
- end
- end
+ n=n+1
+ end
+ end
+ end
+ else
+ local d,k=e.__p__.dt,e.ni
+ for i=k+1,#d,1 do
+ local di=d[i]
+ if type(di)=="table" then
+ if n==1 then
+ found=di
+ break
+ else
+ n=n-1
end
+ end
end
- if newn > 0 then
- instance.extra_paths = ep -- register paths
- end
- if newn > oldn then
- instance.lists = { } -- erase the cache
- end
-end
-
-local function made_list(instance,list)
- local ep = instance.extra_paths
- if not ep or #ep == 0 then
- return list
+ end
+ if found then
+ local ns,tg=found.rn or found.ns or "",found.tg
+ if ns~="" then
+ return ns..":"..tg
else
- local done, new, newn = { }, { }, 0
- -- honour . .. ../.. but only when at the start
- for k=1,#list do
- local v = list[k]
- if not done[v] then
- if find(v,"^[%.%/]$") then
- done[v] = true
- newn = newn + 1
- new[newn] = v
- else
- break
- end
- end
- end
- -- first the extra paths
- for k=1,#ep do
- local v = ep[k]
- if not done[v] then
- done[v] = true
- newn = newn + 1
- new[newn] = v
- end
- end
- -- next the formal paths
- for k=1,#list do
- local v = list[k]
- if not done[v] then
- done[v] = true
- newn = newn + 1
- new[newn] = v
- end
- end
- return new
+ return tg
end
+ else
+ return ""
+ end
end
-
-function resolvers.cleanpathlist(str)
- local t = resolvers.expandedpathlist(str)
- if t then
- for i=1,#t do
- t[i] = collapsepath(resolvers.cleanpath(t[i]))
+expressions.tag=function(e,n)
+ if not e then
+ return ""
+ else
+ local found=false
+ n=tonumber(n) or 0
+ if n==0 then
+ found=(type(e)=="table") and e
+ elseif n<0 then
+ local d,k=e.__p__.dt,e.ni
+ for i=k-1,1,-1 do
+ local di=d[i]
+ if type(di)=="table" then
+ if n==-1 then
+ found=di
+ break
+ else
+ n=n+1
+ end
end
+ end
+ else
+ local d,k=e.__p__.dt,e.ni
+ for i=k+1,#d,1 do
+ local di=d[i]
+ if type(di)=="table" then
+ if n==1 then
+ found=di
+ break
+ else
+ n=n-1
+ end
+ end
+ end
+ end
+ return (found and found.tg) or ""
+ end
+end
+local dummy=function() end
+function xml.elements(root,pattern,reverse)
+ local collected=applylpath(root,pattern)
+ if not collected then
+ return dummy
+ elseif reverse then
+ local c=#collected+1
+ return function()
+ if c>1 then
+ c=c-1
+ local e=collected[c]
+ local r=e.__p__
+ return r,r.dt,e.ni
+ end
+ end
+ else
+ local n,c=#collected,0
+ return function()
+ if c1 then
+ c=c-1
+ return collected[c]
+ end
end
- return t
+ else
+ local n,c=#collected,0
+ return function()
+ if c"))^0
+local special=P("<")/"<"+P(">")/">"+P("&")/"&"
+local escaped=Cs(normal*(special*normal)^0)
+local normal=(1-S"&")^0
+local special=P("<")/"<"+P(">")/">"+P("&")/"&"
+local unescaped=Cs(normal*(special*normal)^0)
+local cleansed=Cs(((P("<")*(1-P(">"))^0*P(">"))/""+1)^0)
+xmlpatterns.escaped=escaped
+xmlpatterns.unescaped=unescaped
+xmlpatterns.cleansed=cleansed
+function xml.escaped (str) return lpegmatch(escaped,str) end
+function xml.unescaped(str) return lpegmatch(unescaped,str) end
+function xml.cleansed (str) return lpegmatch(cleansed,str) end
+function xml.fillin(root,pattern,str,check)
+ local e=xml.first(root,pattern)
+ if e then
+ local n=#e.dt
+ if not check or n==0 or (n==1 and e.dt[1]=="") then
+ e.dt={ str }
end
- return readable
+ end
end
--- name
--- name/name
-local function collect_files(names)
- local filelist, noffiles = { }, 0
- for k=1,#names do
- local fname = names[k]
- if trace_detail then
- report_resolving("checking name '%s'",fname)
- end
- local bname = filebasename(fname)
- local dname = filedirname(fname)
- if dname == "" or find(dname,"^%.") then
- dname = false
- else
-dname = gsub(dname,"*","%.*")
- dname = "/" .. dname .. "$"
- end
- local hashes = instance.hashes
- for h=1,#hashes do
- local hash = hashes[h]
- local blobpath = hash.name
- local files = blobpath and instance.files[blobpath]
- if files then
- if trace_detail then
- report_resolving("deep checking '%s' (%s)",blobpath,bname)
- end
- local blobfile = files[bname]
- if not blobfile then
- local rname = "remap:"..bname
- blobfile = files[rname]
- if blobfile then
- bname = files[rname]
- blobfile = files[bname]
- end
- end
- if blobfile then
- local blobroot = files.__path__ or blobpath
- if type(blobfile) == 'string' then
- if not dname or find(blobfile,dname) then
- local variant = hash.type
- -- local search = filejoin(blobpath,blobfile,bname)
- local search = filejoin(blobroot,blobfile,bname)
- local result = methodhandler('concatinators',hash.type,blobroot,blobfile,bname)
- if trace_detail then
- report_resolving("match: variant '%s', search '%s', result '%s'",variant,search,result)
- end
- noffiles = noffiles + 1
- filelist[noffiles] = { variant, search, result }
- end
- else
- for kk=1,#blobfile do
- local vv = blobfile[kk]
- if not dname or find(vv,dname) then
- local variant = hash.type
- -- local search = filejoin(blobpath,vv,bname)
- local search = filejoin(blobroot,vv,bname)
- local result = methodhandler('concatinators',hash.type,blobroot,vv,bname)
- if trace_detail then
- report_resolving("match: variant '%s', search '%s', result '%s'",variant,search,result)
- end
- noffiles = noffiles + 1
- filelist[noffiles] = { variant, search, result }
- end
- end
- end
- end
- elseif trace_locating then
- report_resolving("no match in '%s' (%s)",blobpath,bname)
- end
- end
- end
- return noffiles > 0 and filelist or nil
-end
+end -- of closure
-local fit = { }
+do -- create closure to overcome 200 locals limit
-function resolvers.registerintrees(filename,format,filetype,usedmethod,foundname)
- local foundintrees = instance.foundintrees
- if usedmethod == "direct" and filename == foundname and fit[foundname] then
- -- just an extra lookup after a test on presence
- else
- local t = {
- filename = filename,
- format = format ~= "" and format or nil,
- filetype = filetype ~= "" and filetype or nil,
- usedmethod = usedmethod,
- foundname = foundname,
- }
- fit[foundname] = t
- foundintrees[#foundintrees+1] = t
- end
-end
+package.loaded["lxml-aux"] = package.loaded["lxml-aux"] or true
--- split the next one up for readability (but this module needs a cleanup anyway)
+-- original size: 23804, stripped down to: 16817
-local function can_be_dir(name) -- can become local
- local fakepaths = instance.fakepaths
- if not fakepaths[name] then
- if lfs.isdir(name) then
- fakepaths[name] = 1 -- directory
- else
- fakepaths[name] = 2 -- no directory
+if not modules then modules={} end modules ['lxml-aux']={
+ version=1.001,
+ comment="this module is the basis for the lxml-* ones",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local trace_manipulations=false trackers.register("lxml.manipulations",function(v) trace_manipulations=v end)
+local report_xml=logs.reporter("xml")
+local xml=xml
+local xmlconvert,xmlcopy,xmlname=xml.convert,xml.copy,xml.name
+local xmlinheritedconvert=xml.inheritedconvert
+local xmlapplylpath=xml.applylpath
+local xmlfilter=xml.filter
+local type,setmetatable,getmetatable=type,setmetatable,getmetatable
+local insert,remove,fastcopy,concat=table.insert,table.remove,table.fastcopy,table.concat
+local gmatch,gsub,format,find,strip=string.gmatch,string.gsub,string.format,string.find,string.strip
+local utfbyte=utf.byte
+local function report(what,pattern,c,e)
+ report_xml("%s element %a, root %a, position %a, index %a, pattern %a",what,xmlname(e),xmlname(e.__p__),c,e.ni,pattern)
+end
+local function withelements(e,handle,depth)
+ if e and handle then
+ local edt=e.dt
+ if edt then
+ depth=depth or 0
+ for i=1,#edt do
+ local e=edt[i]
+ if type(e)=="table" then
+ handle(e,depth)
+ withelements(e,handle,depth+1)
end
+ end
end
- return fakepaths[name] == 1
+ end
end
-
-local preparetreepattern = Cs((P(".")/"%%." + P("-")/"%%-" + P(1))^0 * Cc("$"))
-
--- -- -- begin of main file search routing -- -- -- needs checking as previous has been patched
-
-local collect_instance_files
-
-local function find_analyze(filename,askedformat,allresults)
- local filetype, wantedfiles, ext = '', { }, fileextname(filename)
- -- too tricky as filename can be bla.1.2.3:
- --
- -- if not suffixmap[ext] then
- -- wantedfiles[#wantedfiles+1] = filename
- -- end
- wantedfiles[#wantedfiles+1] = filename
- if askedformat == "" then
- if ext == "" or not suffixmap[ext] then
- local defaultsuffixes = resolvers.defaultsuffixes
- for i=1,#defaultsuffixes do
- local forcedname = filename .. '.' .. defaultsuffixes[i]
- wantedfiles[#wantedfiles+1] = forcedname
- filetype = resolvers.formatofsuffix(forcedname)
- if trace_locating then
- report_resolving("forcing filetype '%s'",filetype)
- end
- end
- else
- filetype = resolvers.formatofsuffix(filename)
- if trace_locating then
- report_resolving("using suffix based filetype '%s'",filetype)
+xml.withelements=withelements
+function xml.withelement(e,n,handle)
+ if e and n~=0 and handle then
+ local edt=e.dt
+ if edt then
+ if n>0 then
+ for i=1,#edt do
+ local ei=edt[i]
+ if type(ei)=="table" then
+ if n==1 then
+ handle(ei)
+ return
+ else
+ n=n-1
end
+ end
end
- else
- if ext == "" or not suffixmap[ext] then
- local format_suffixes = suffixes[askedformat]
- if format_suffixes then
- for i=1,#format_suffixes do
- wantedfiles[#wantedfiles+1] = filename .. "." .. format_suffixes[i]
- end
+ elseif n<0 then
+ for i=#edt,1,-1 do
+ local ei=edt[i]
+ if type(ei)=="table" then
+ if n==-1 then
+ handle(ei)
+ return
+ else
+ n=n+1
end
+ end
end
- filetype = askedformat
- if trace_locating then
- report_resolving("using given filetype '%s'",filetype)
- end
+ end
end
- return filetype, wantedfiles
+ end
end
-
-local function find_direct(filename,allresults)
- if not dangerous[askedformat] and isreadable(filename) then
- if trace_detail then
- report_resolving("file '%s' found directly",filename)
- end
- return "direct", { filename }
+function xml.each(root,pattern,handle,reverse)
+ local collected=xmlapplylpath(root,pattern)
+ if collected then
+ if reverse then
+ for c=#collected,1,-1 do
+ handle(collected[c])
+ end
+ else
+ for c=1,#collected do
+ handle(collected[c])
+ end
end
+ return collected
+ end
end
-
-local function find_wildcard(filename,allresults)
- if find(filename,'%*') then
- if trace_locating then
- report_resolving("checking wildcard '%s'", filename)
- end
- local method, result = resolvers.findwildcardfiles(filename)
- if result then
- return "wildcard", result
- end
+function xml.processattributes(root,pattern,handle)
+ local collected=xmlapplylpath(root,pattern)
+ if collected and handle then
+ for c=1,#collected do
+ handle(collected[c].at)
end
+ end
+ return collected
end
-
-local function find_qualified(filename,allresults) -- this one will be split too
- if not file.is_qualified_path(filename) then
- return
+function xml.collect(root,pattern)
+ return xmlapplylpath(root,pattern)
+end
+function xml.collecttexts(root,pattern,flatten)
+ local collected=xmlapplylpath(root,pattern)
+ if collected and flatten then
+ local xmltostring=xml.tostring
+ for c=1,#collected do
+ collected[c]=xmltostring(collected[c].dt)
end
- if trace_locating then
- report_resolving("checking qualified name '%s'", filename)
+ end
+ return collected or {}
+end
+function xml.collect_tags(root,pattern,nonamespace)
+ local collected=xmlapplylpath(root,pattern)
+ if collected then
+ local t,n={},0
+ for c=1,#collected do
+ local e=collected[c]
+ local ns,tg=e.ns,e.tg
+ n=n+1
+ if nonamespace then
+ t[n]=tg
+ elseif ns=="" then
+ t[n]=tg
+ else
+ t[n]=ns..":"..tg
+ end
end
- if isreadable(filename) then
- if trace_detail then
- report_resolving("qualified file '%s' found", filename)
- end
- return "qualified", { filename }
+ return t
+ end
+end
+local no_root={ no_root=true }
+local function redo_ni(d)
+ for k=1,#d do
+ local dk=d[k]
+ if type(dk)=="table" then
+ dk.ni=k
end
- if trace_detail then
- report_resolving("locating qualified file '%s'", filename)
- end
- local forcedname, suffix = "", fileextname(filename)
- if suffix == "" then -- why
- local format_suffixes = askedformat == "" and resolvers.defaultsuffixes or suffixes[askedformat]
- if format_suffixes then
- for i=1,#format_suffixes do
- local s = format_suffixes[i]
- forcedname = filename .. "." .. s
- if isreadable(forcedname) then
- if trace_locating then
- report_resolving("no suffix, forcing format filetype '%s'", s)
- end
- return "qualified", { forcedname }
- end
- end
- end
+ end
+end
+local function xmltoelement(whatever,root)
+ if not whatever then
+ return nil
+ end
+ local element
+ if type(whatever)=="string" then
+ element=xmlinheritedconvert(whatever,root)
+ else
+ element=whatever
+ end
+ if element.error then
+ return whatever
+ end
+ if element then
+ end
+ return element
+end
+xml.toelement=xmltoelement
+local function copiedelement(element,newparent)
+ if type(element)=="string" then
+ return element
+ else
+ element=xmlcopy(element).dt
+ if newparent and type(element)=="table" then
+ element.__p__=newparent
end
- if suffix and suffix ~= "" then
- -- try to find in tree (no suffix manipulation), here we search for the
- -- matching last part of the name
- local basename = filebasename(filename)
- local pattern = lpegmatch(preparetreepattern,filename)
- -- messy .. to be sorted out
- local savedformat = askedformat
- local format = savedformat or ""
- if format == "" then
- askedformat = resolvers.formatofsuffix(suffix)
- end
- if not format then
- askedformat = "othertextfiles" -- kind of everything, maybe all
- end
- --
- if basename ~= filename then
- local resolved = collect_instance_files(basename,askedformat,allresults)
- if #resolved == 0 then
- local lowered = lower(basename)
- if filename ~= lowered then
- resolved = collect_instance_files(lowered,askedformat,allresults)
- end
- end
- resolvers.format = savedformat
- --
- if #resolved > 0 then
- local result = { }
- for r=1,#resolved do
- local rr = resolved[r]
- if find(rr,pattern) then
- result[#result+1] = rr
- end
- end
- if #result > 0 then
- return "qualified", result
- end
- end
+ return element
+ end
+end
+function xml.delete(root,pattern)
+ if not pattern or pattern=="" then
+ local p=root.__p__
+ if p then
+ if trace_manipulations then
+ report('deleting',"--",c,root)
+ end
+ local d=p.dt
+ remove(d,root.ni)
+ redo_ni(d)
+ end
+ else
+ local collected=xmlapplylpath(root,pattern)
+ if collected then
+ for c=1,#collected do
+ local e=collected[c]
+ local p=e.__p__
+ if p then
+ if trace_manipulations then
+ report('deleting',pattern,c,e)
+ end
+ local d=p.dt
+ remove(d,e.ni)
+ redo_ni(d)
end
- -- a real wildcard:
- --
- -- local filelist = collect_files({basename})
- -- result = { }
- -- for f=1,#filelist do
- -- local ff = filelist[f][3] or ""
- -- if find(ff,pattern) then
- -- result[#result+1], ok = ff, true
- -- end
- -- end
- -- if #result > 0 then
- -- return "qualified", result
- -- end
+ end
end
+ end
end
-
-local function check_subpath(fname)
- if isreadable(fname) then
- if trace_detail then
- report_resolving("found '%s' by deep scanning",fname)
+function xml.replace(root,pattern,whatever)
+ local element=root and xmltoelement(whatever,root)
+ local collected=element and xmlapplylpath(root,pattern)
+ if collected then
+ for c=1,#collected do
+ local e=collected[c]
+ local p=e.__p__
+ if p then
+ if trace_manipulations then
+ report('replacing',pattern,c,e)
end
- return fname
+ local d=p.dt
+ d[e.ni]=copiedelement(element,p)
+ redo_ni(d)
+ end
end
+ end
end
-
-local function find_intree(filename,filetype,wantedfiles,allresults)
- local typespec = resolvers.variableofformat(filetype)
- local pathlist = resolvers.expandedpathlist(typespec)
- local method = "intree"
- if pathlist and #pathlist > 0 then
- -- list search
- local filelist = collect_files(wantedfiles)
- local dirlist = { }
- if filelist then
- for i=1,#filelist do
- dirlist[i] = filedirname(filelist[i][3]) .. "/" -- was [2] .. gamble
- end
- end
- if trace_detail then
- report_resolving("checking filename '%s'",filename)
- end
- local result = { }
- for k=1,#pathlist do
- local path = pathlist[k]
- local pathname = lpegmatch(inhibitstripper,path)
- local doscan = path == pathname -- no ^!!
- if not find (pathname,'//$') then
- doscan = false -- we check directly on the path
- end
- local done = false
- -- using file list
- if filelist then -- database
- -- compare list entries with permitted pattern -- /xx /xx//
- local expression = makepathexpression(pathname)
- if trace_detail then
- report_resolving("using pattern '%s' for path '%s'",expression,pathname)
- end
- for k=1,#filelist do
- local fl = filelist[k]
- local f = fl[2]
- local d = dirlist[k]
- if find(d,expression) then
- -- todo, test for readable
- result[#result+1] = resolvers.resolve(fl[3]) -- no shortcut
- done = true
- if allresults then
- if trace_detail then
- report_resolving("match to '%s' in hash for file '%s' and path '%s', continue scanning",expression,f,d)
- end
- else
- if trace_detail then
- report_resolving("match to '%s' in hash for file '%s' and path '%s', quit scanning",expression,f,d)
- end
- break
- end
- elseif trace_detail then
- report_resolving("no match to '%s' in hash for file '%s' and path '%s'",expression,f,d)
- end
- end
- end
- if done then
- method = "database"
- else
- method = "filesystem" -- bonus, even when !! is specified
- pathname = gsub(pathname,"/+$","")
- pathname = resolvers.resolve(pathname)
- local scheme = url.hasscheme(pathname)
- if not scheme or scheme == "file" then
- local pname = gsub(pathname,"%.%*$",'')
- if not find(pname,"%*") then
- if can_be_dir(pname) then
- -- quick root scan first
- for k=1,#wantedfiles do
- local w = wantedfiles[k]
- local fname = check_subpath(filejoin(pname,w))
- if fname then
- result[#result+1] = fname
- done = true
- if not allresults then
- break
- end
- end
- end
- if not done and doscan then
- -- collect files in path (and cache the result)
- local files = resolvers.simplescanfiles(pname,false,true)
- for k=1,#wantedfiles do
- local w = wantedfiles[k]
- local subpath = files[w]
- if not subpath or subpath == "" then
- -- rootscan already done
- elseif type(subpath) == "string" then
- local fname = check_subpath(filejoin(pname,subpath,w))
- if fname then
- result[#result+1] = fname
- done = true
- if not allresults then
- break
- end
- end
- else
- for i=1,#subpath do
- local sp = subpath[i]
- if sp == "" then
- -- roottest already done
- else
- local fname = check_subpath(filejoin(pname,sp,w))
- if fname then
- result[#result+1] = fname
- done = true
- if not allresults then
- break
- end
- end
- end
- end
- if done and not allresults then
- break
- end
- end
- end
- end
- end
- else
- -- no access needed for non existing path, speedup (esp in large tree with lots of fake)
- end
- end
- end
- -- todo recursive scanning
- if done and not allresults then
- break
- end
- end
- if #result > 0 then
- return method, result
+local function wrap(e,wrapper)
+ local t={
+ rn=e.rn,
+ tg=e.tg,
+ ns=e.ns,
+ at=e.at,
+ dt=e.dt,
+ __p__=e,
+ }
+ setmetatable(t,getmetatable(e))
+ e.rn=wrapper.rn or e.rn or ""
+ e.tg=wrapper.tg or e.tg or ""
+ e.ns=wrapper.ns or e.ns or ""
+ e.at=fastcopy(wrapper.at)
+ e.dt={ t }
+end
+function xml.wrap(root,pattern,whatever)
+ if whatever then
+ local wrapper=xmltoelement(whatever,root)
+ local collected=xmlapplylpath(root,pattern)
+ if collected then
+ for c=1,#collected do
+ local e=collected[c]
+ if trace_manipulations then
+ report('wrapping',pattern,c,e)
end
+ wrap(e,wrapper)
+ end
+ end
+ else
+ wrap(root,xmltoelement(pattern))
+ end
+end
+local function inject_element(root,pattern,whatever,prepend)
+ local element=root and xmltoelement(whatever,root)
+ local collected=element and xmlapplylpath(root,pattern)
+ local function inject_e(e)
+ local r=e.__p__
+ local d,k,rri=r.dt,e.ni,r.ri
+ local edt=(rri and d[rri].dt) or (d and d[k] and d[k].dt)
+ if edt then
+ local be,af
+ local cp=copiedelement(element,e)
+ if prepend then
+ be,af=cp,edt
+ else
+ be,af=edt,cp
+ end
+ local bn=#be
+ for i=1,#af do
+ bn=bn+1
+ be[bn]=af[i]
+ end
+ if rri then
+ r.dt[rri].dt=be
+ else
+ d[k].dt=be
+ end
+ redo_ni(d)
+ end
+ end
+ if not collected then
+ elseif collected.tg then
+ inject_e(collected)
+ else
+ for c=1,#collected do
+ inject_e(collected[c])
+ end
+ end
+end
+local function insert_element(root,pattern,whatever,before)
+ local element=root and xmltoelement(whatever,root)
+ local collected=element and xmlapplylpath(root,pattern)
+ local function insert_e(e)
+ local r=e.__p__
+ local d,k=r.dt,e.ni
+ if not before then
+ k=k+1
+ end
+ insert(d,k,copiedelement(element,r))
+ redo_ni(d)
+ end
+ if not collected then
+ elseif collected.tg then
+ insert_e(collected)
+ else
+ for c=1,#collected do
+ insert_e(collected[c])
end
+ end
end
-
-local function find_onpath(filename,filetype,wantedfiles,allresults)
- if trace_detail then
- report_resolving("checking filename '%s', filetype '%s', wanted files '%s'",filename, filetype or '?',concat(wantedfiles," | "))
- end
- local result = { }
- for k=1,#wantedfiles do
- local fname = wantedfiles[k]
- if fname and isreadable(fname) then
- filename = fname
- result[#result+1] = filejoin('.',fname)
- if not allresults then
- break
- end
+xml.insert_element=insert_element
+xml.insertafter=insert_element
+xml.insertbefore=function(r,p,e) insert_element(r,p,e,true) end
+xml.injectafter=inject_element
+xml.injectbefore=function(r,p,e) inject_element(r,p,e,true) end
+local function include(xmldata,pattern,attribute,recursive,loaddata)
+ pattern=pattern or 'include'
+ loaddata=loaddata or io.loaddata
+ local collected=xmlapplylpath(xmldata,pattern)
+ if collected then
+ for c=1,#collected do
+ local ek=collected[c]
+ local name=nil
+ local ekdt=ek.dt
+ local ekat=ek.at
+ local epdt=ek.__p__.dt
+ if not attribute or attribute=="" then
+ name=(type(ekdt)=="table" and ekdt[1]) or ekdt
+ end
+ if not name then
+ for a in gmatch(attribute or "href","([^|]+)") do
+ name=ekat[a]
+ if name then break end
+ end
+ end
+ local data=(name and name~="" and loaddata(name)) or ""
+ if data=="" then
+ epdt[ek.ni]=""
+ elseif ekat["parse"]=="text" then
+ epdt[ek.ni]=xml.escaped(data)
+ else
+ local xi=xmlinheritedconvert(data,xmldata)
+ if not xi then
+ epdt[ek.ni]=""
+ else
+ if recursive then
+ include(xi,pattern,attribute,recursive,loaddata)
+ end
+ epdt[ek.ni]=xml.body(xi)
end
+ end
end
- if #result > 0 then
- return "onpath", result
- end
-end
-
-local function find_otherwise(filename,filetype,wantedfiles,allresults) -- other text files | any | whatever
- local filelist = collect_files(wantedfiles)
- local fl = filelist and filelist[1]
- if fl then
- return "otherwise", { resolvers.resolve(fl[3]) } -- filename
- end
-end
-
--- we could have a loop over the 6 functions but then we'd have to
--- always analyze
-
-collect_instance_files = function(filename,askedformat,allresults) -- uses nested
- askedformat = askedformat or ""
- filename = collapsepath(filename)
- if allresults then
- -- no need for caching, only used for tracing
- local filetype, wantedfiles = find_analyze(filename,askedformat)
- local results = {
- { find_direct (filename,true) },
- { find_wildcard (filename,true) },
- { find_qualified(filename,true) },
- { find_intree (filename,filetype,wantedfiles,true) },
- { find_onpath (filename,filetype,wantedfiles,true) },
- { find_otherwise(filename,filetype,wantedfiles,true) },
- }
- local result, status, done = { }, { }, { }
- for k, r in next, results do
- local method, list = r[1], r[2]
- if method and list then
- for i=1,#list do
- local c = collapsepath(list[i])
- if not done[c] then
- result[#result+1] = c
- done[c] = true
- end
- status[#status+1] = format("%-10s: %s",method,c)
- end
- end
- end
- if trace_detail then
- report_resolving("lookup status: %s",table.serialize(status,filename))
- end
- return result, status
+ end
+end
+xml.include=include
+local function stripelement(e,nolines,anywhere)
+ local edt=e.dt
+ if edt then
+ if anywhere then
+ local t,n={},0
+ for e=1,#edt do
+ local str=edt[e]
+ if type(str)~="string" then
+ n=n+1
+ t[n]=str
+ elseif str~="" then
+ if nolines then
+ str=gsub(str,"%s+"," ")
+ end
+ str=gsub(str,"^%s*(.-)%s*$","%1")
+ if str~="" then
+ n=n+1
+ t[n]=str
+ end
+ end
+ end
+ e.dt=t
else
- local method, result, stamp, filetype, wantedfiles
- if instance.remember then
- stamp = format("%s--%s", filename, askedformat)
- result = stamp and instance.found[stamp]
- if result then
- if trace_locating then
- report_resolving("remembered file '%s'",filename)
- end
- return result
- end
- end
- method, result = find_direct(filename)
- if not result then
- method, result = find_wildcard(filename)
- if not result then
- method, result = find_qualified(filename)
- if not result then
- filetype, wantedfiles = find_analyze(filename,askedformat)
- method, result = find_intree(filename,filetype,wantedfiles)
- if not result then
- method, result = find_onpath(filename,filetype,wantedfiles)
- if not result then
- method, result = find_otherwise(filename,filetype,wantedfiles)
- end
- end
- end
- end
- end
- if result and #result > 0 then
- local foundname = collapsepath(result[1])
- resolvers.registerintrees(filename,askedformat,filetype,method,foundname)
- result = { foundname }
+ if #edt>0 then
+ local str=edt[1]
+ if type(str)~="string" then
+ elseif str=="" then
+ remove(edt,1)
else
- result = { } -- maybe false
- end
- if stamp then
- if trace_locating then
- report_resolving("remembering file '%s'",filename)
- end
- instance.found[stamp] = result
- end
- return result
+ if nolines then
+ str=gsub(str,"%s+"," ")
+ end
+ str=gsub(str,"^%s+","")
+ if str=="" then
+ remove(edt,1)
+ else
+ edt[1]=str
+ end
+ end
+ end
+ local nedt=#edt
+ if nedt>0 then
+ local str=edt[nedt]
+ if type(str)~="string" then
+ elseif str=="" then
+ remove(edt)
+ else
+ if nolines then
+ str=gsub(str,"%s+"," ")
+ end
+ str=gsub(str,"%s+$","")
+ if str=="" then
+ remove(edt)
+ else
+ edt[nedt]=str
+ end
+ end
+ end
+ end
+ end
+ return e
+end
+xml.stripelement=stripelement
+function xml.strip(root,pattern,nolines,anywhere)
+ local collected=xmlapplylpath(root,pattern)
+ if collected then
+ for i=1,#collected do
+ stripelement(collected[i],nolines,anywhere)
+ end
+ end
+end
+local function renamespace(root,oldspace,newspace)
+ local ndt=#root.dt
+ for i=1,ndt or 0 do
+ local e=root[i]
+ if type(e)=="table" then
+ if e.ns==oldspace then
+ e.ns=newspace
+ if e.rn then
+ e.rn=newspace
+ end
+ end
+ local edt=e.dt
+ if edt then
+ renamespace(edt,oldspace,newspace)
+ end
+ end
+ end
+end
+xml.renamespace=renamespace
+function xml.remaptag(root,pattern,newtg)
+ local collected=xmlapplylpath(root,pattern)
+ if collected then
+ for c=1,#collected do
+ collected[c].tg=newtg
end
+ end
end
-
--- -- -- end of main file search routing -- -- --
-
-
-local function findfiles(filename,filetype,allresults)
- local result, status = collect_instance_files(filename,filetype or "",allresults)
- if not result or #result == 0 then
- local lowered = lower(filename)
- if filename ~= lowered then
- result, status = collect_instance_files(lowered,filetype or "",allresults)
- end
+function xml.remapnamespace(root,pattern,newns)
+ local collected=xmlapplylpath(root,pattern)
+ if collected then
+ for c=1,#collected do
+ collected[c].ns=newns
end
- return result or { }, status
+ end
end
-
-function resolvers.findfiles(filename,filetype)
- return findfiles(filename,filetype,true)
+function xml.checknamespace(root,pattern,newns)
+ local collected=xmlapplylpath(root,pattern)
+ if collected then
+ for c=1,#collected do
+ local e=collected[c]
+ if (not e.rn or e.rn=="") and e.ns=="" then
+ e.rn=newns
+ end
+ end
+ end
end
-
-function resolvers.findfile(filename,filetype)
- return findfiles(filename,filetype,false)[1] or ""
+function xml.remapname(root,pattern,newtg,newns,newrn)
+ local collected=xmlapplylpath(root,pattern)
+ if collected then
+ for c=1,#collected do
+ local e=collected[c]
+ e.tg,e.ns,e.rn=newtg,newns,newrn
+ end
+ end
end
-
-function resolvers.findpath(filename,filetype)
- return filedirname(findfiles(filename,filetype,false)[1] or "")
+function xml.cdatatotext(e)
+ local dt=e.dt
+ if #dt==1 then
+ local first=dt[1]
+ if first.tg=="@cd@" then
+ e.dt=first.dt
+ end
+ else
+ end
+end
+function xml.texttocdata(e)
+ local dt=e.dt
+ local s=xml.tostring(dt)
+ e.tg="@cd@"
+ e.special=true
+ e.ns=""
+ e.rn=""
+ e.dt={ s }
+ e.at=nil
+end
+function xml.elementtocdata(e)
+ local dt=e.dt
+ local s=xml.tostring(e)
+ e.tg="@cd@"
+ e.special=true
+ e.ns=""
+ e.rn=""
+ e.dt={ s }
+ e.at=nil
+end
+xml.builtinentities=table.tohash { "amp","quot","apos","lt","gt" }
+local entities=characters and characters.entities or nil
+local builtinentities=xml.builtinentities
+function xml.addentitiesdoctype(root,option)
+ if not entities then
+ require("char-ent")
+ entities=characters.entities
+ end
+ if entities and root and root.tg=="@rt@" and root.statistics then
+ local list={}
+ local hexify=option=="hexadecimal"
+ for k,v in table.sortedhash(root.statistics.entities.names) do
+ if not builtinentities[k] then
+ local e=entities[k]
+ if not e then
+ e=format("[%s]",k)
+ elseif hexify then
+ e=format("%05X;",utfbyte(k))
+ end
+ list[#list+1]=format(" ",k,e)
+ end
+ end
+ local dt=root.dt
+ local n=dt[1].tg=="@pi@" and 2 or 1
+ if #list>0 then
+ insert(dt,n,{ "\n" })
+ insert(dt,n,{
+ tg="@dt@",
+ dt={ format("Something [\n%s\n] ",concat(list)) },
+ ns="",
+ special=true,
+ })
+ insert(dt,n,{ "\n\n" })
+ else
+ end
+ end
+end
+xml.all=xml.each
+xml.insert=xml.insertafter
+xml.inject=xml.injectafter
+xml.after=xml.insertafter
+xml.before=xml.insertbefore
+xml.process=xml.each
+xml.obsolete=xml.obsolete or {}
+local obsolete=xml.obsolete
+xml.strip_whitespace=xml.strip obsolete.strip_whitespace=xml.strip
+xml.collect_elements=xml.collect obsolete.collect_elements=xml.collect
+xml.delete_element=xml.delete obsolete.delete_element=xml.delete
+xml.replace_element=xml.replace obsolete.replace_element=xml.replacet
+xml.each_element=xml.each obsolete.each_element=xml.each
+xml.process_elements=xml.process obsolete.process_elements=xml.process
+xml.insert_element_after=xml.insertafter obsolete.insert_element_after=xml.insertafter
+xml.insert_element_before=xml.insertbefore obsolete.insert_element_before=xml.insertbefore
+xml.inject_element_after=xml.injectafter obsolete.inject_element_after=xml.injectafter
+xml.inject_element_before=xml.injectbefore obsolete.inject_element_before=xml.injectbefore
+xml.process_attributes=xml.processattributes obsolete.process_attributes=xml.processattributes
+xml.collect_texts=xml.collecttexts obsolete.collect_texts=xml.collecttexts
+xml.inject_element=xml.inject obsolete.inject_element=xml.inject
+xml.remap_tag=xml.remaptag obsolete.remap_tag=xml.remaptag
+xml.remap_name=xml.remapname obsolete.remap_name=xml.remapname
+xml.remap_namespace=xml.remapnamespace obsolete.remap_namespace=xml.remapnamespace
+function xml.cdata(e)
+ if e then
+ local dt=e.dt
+ if dt and #dt==1 then
+ local first=dt[1]
+ return first.tg=="@cd@" and first.dt[1] or ""
+ end
+ end
+ return ""
end
-
-local function findgivenfiles(filename,allresults)
- local bname, result = filebasename(filename), { }
- local hashes = instance.hashes
- local noffound = 0
- for k=1,#hashes do
- local hash = hashes[k]
- local files = instance.files[hash.name] or { }
- local blist = files[bname]
- if not blist then
- local rname = "remap:"..bname
- blist = files[rname]
- if blist then
- bname = files[rname]
- blist = files[bname]
- end
- end
- if blist then
- if type(blist) == 'string' then
- local found = methodhandler('concatinators',hash.type,hash.name,blist,bname) or ""
- if found ~= "" then
- noffound = noffound + 1
- result[noffound] = resolvers.resolve(found)
- if not allresults then break end
- end
+function xml.finalizers.xml.cdata(collected)
+ if collected then
+ local e=collected[1]
+ if e then
+ local dt=e.dt
+ if dt and #dt==1 then
+ local first=dt[1]
+ return first.tg=="@cd@" and first.dt[1] or ""
+ end
+ end
+ end
+ return ""
+end
+function xml.insertcomment(e,str,n)
+ table.insert(e.dt,n or 1,{
+ tg="@cm@",
+ ns="",
+ special=true,
+ at={},
+ dt={ str },
+ })
+end
+function xml.setcdata(e,str)
+ e.dt={ {
+ tg="@cd@",
+ ns="",
+ special=true,
+ at={},
+ dt={ str },
+ } }
+end
+function xml.separate(x,pattern)
+ local collected=xmlapplylpath(x,pattern)
+ if collected then
+ for c=1,#collected do
+ local e=collected[c]
+ local d=e.dt
+ if d==x then
+ report_xml("warning: xml.separate changes root")
+ x=d
+ end
+ local t,n={ "\n" },1
+ local i,nd=1,#d
+ while i<=nd do
+ while i<=nd do
+ local di=d[i]
+ if type(di)=="string" then
+ if di=="\n" or find(di,"^%s+$") then
+ i=i+1
else
- for kk=1,#blist do
- local vv = blist[kk]
- local found = methodhandler('concatinators',hash.type,hash.name,vv,bname) or ""
- if found ~= "" then
- noffound = noffound + 1
- result[noffound] = resolvers.resolve(found)
- if not allresults then break end
- end
- end
+ d[i]=strip(di)
+ break
end
+ else
+ break
+ end
+ end
+ if i>nd then
+ break
+ end
+ t[n+1]="\n"
+ t[n+2]=d[i]
+ t[n+3]="\n"
+ n=n+3
+ i=i+1
+ end
+ t[n+1]="\n"
+ setmetatable(t,getmetatable(d))
+ e.dt=t
+ end
+ end
+ return x
+end
+local helpers=xml.helpers or {}
+xml.helpers=helpers
+local function normal(e,action)
+ local edt=e.dt
+ if edt then
+ for i=1,#edt do
+ local str=edt[i]
+ if type(str)=="string" and str~="" then
+ edt[i]=action(str)
+ end
+ end
+ end
+end
+local function recurse(e,action)
+ local edt=e.dt
+ if edt then
+ for i=1,#edt do
+ local str=edt[i]
+ if type(str)~="string" then
+ recurse(str,action,recursive)
+ elseif str~="" then
+ edt[i]=action(str)
+ end
+ end
+ end
+end
+function helpers.recursetext(collected,action,recursive)
+ if recursive then
+ for i=1,#collected do
+ recurse(collected[i],action)
+ end
+ else
+ for i=1,#collected do
+ normal(collected[i],action)
+ end
+ end
+end
+
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
+package.loaded["lxml-xml"] = package.loaded["lxml-xml"] or true
+
+-- original size: 10274, stripped down to: 7538
+
+if not modules then modules={} end modules ['lxml-xml']={
+ version=1.001,
+ comment="this module is the basis for the lxml-* ones",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local concat=table.concat
+local find,lower,upper=string.find,string.lower,string.upper
+local xml=xml
+local finalizers=xml.finalizers.xml
+local xmlfilter=xml.filter
+local xmltostring=xml.tostring
+local xmlserialize=xml.serialize
+local xmlcollected=xml.collected
+local xmlnewhandlers=xml.newhandlers
+local function first(collected)
+ return collected and collected[1]
+end
+local function last(collected)
+ return collected and collected[#collected]
+end
+local function all(collected)
+ return collected
+end
+local reverse=table.reversed
+local function attribute(collected,name)
+ if collected and #collected>0 then
+ local at=collected[1].at
+ return at and at[name]
+ end
+end
+local function att(id,name)
+ local at=id.at
+ return at and at[name]
+end
+local function count(collected)
+ return collected and #collected or 0
+end
+local function position(collected,n)
+ if not collected then
+ return 0
+ end
+ local nc=#collected
+ if nc==0 then
+ return 0
+ end
+ n=tonumber(n) or 0
+ if n<0 then
+ return collected[nc+n+1]
+ elseif n>0 then
+ return collected[n]
+ else
+ return collected[1].mi or 0
+ end
+end
+local function match(collected)
+ return collected and #collected>0 and collected[1].mi or 0
+end
+local function index(collected)
+ return collected and #collected>0 and collected[1].ni or 0
+end
+local function attributes(collected,arguments)
+ if collected and #collected>0 then
+ local at=collected[1].at
+ if arguments then
+ return at[arguments]
+ elseif next(at) then
+ return at
+ end
+ end
+end
+local function chainattribute(collected,arguments)
+ if collected and #collected>0 then
+ local e=collected[1]
+ while e do
+ local at=e.at
+ if at then
+ local a=at[arguments]
+ if a then
+ return a
end
+ else
+ break
+ end
+ e=e.__p__
end
+ end
+ return ""
+end
+local function raw(collected)
+ if collected and #collected>0 then
+ local e=collected[1] or collected
+ return e and xmltostring(e) or ""
+ else
+ return ""
+ end
+end
+local xmltexthandler=xmlnewhandlers {
+ name="string",
+ initialize=function()
+ result={}
return result
+ end,
+ finalize=function()
+ return concat(result)
+ end,
+ handle=function(...)
+ result[#result+1]=concat {... }
+ end,
+ escape=false,
+}
+local function xmltotext(root)
+ local dt=root.dt
+ if not dt then
+ return ""
+ end
+ local nt=#dt
+ if nt==0 then
+ return ""
+ elseif nt==1 and type(dt[1])=="string" then
+ return dt[1]
+ else
+ return xmlserialize(root,xmltexthandler) or ""
+ end
+end
+local function text(collected)
+ if collected then
+ local e=collected[1] or collected
+ return e and xmltotext(e) or ""
+ else
+ return ""
+ end
end
-
-function resolvers.findgivenfiles(filename)
- return findgivenfiles(filename,true)
+local function texts(collected)
+ if not collected then
+ return {}
+ end
+ local nc=#collected
+ if nc==0 then
+ return {}
+ end
+ local t,n={},0
+ for c=1,nc do
+ local e=collected[c]
+ if e and e.dt then
+ n=n+1
+ t[n]=e.dt
+ end
+ end
+ return t
end
-
-function resolvers.findgivenfile(filename)
- return findgivenfiles(filename,false)[1] or ""
+local function tag(collected,n)
+ if not collected then
+ return
+ end
+ local nc=#collected
+ if nc==0 then
+ return
+ end
+ local c
+ if n==0 or not n then
+ c=collected[1]
+ elseif n>1 then
+ c=collected[n]
+ else
+ c=collected[nc-n+1]
+ end
+ return c and c.tg
end
-
-local function doit(path,blist,bname,tag,variant,result,allresults)
- local done = false
- if blist and variant then
- local resolve = resolvers.resolve -- added
- if type(blist) == 'string' then
- -- make function and share code
- if find(lower(blist),path) then
- local full = methodhandler('concatinators',variant,tag,blist,bname) or ""
- result[#result+1] = resolve(full)
- done = true
- end
+local function name(collected,n)
+ if not collected then
+ return
+ end
+ local nc=#collected
+ if nc==0 then
+ return
+ end
+ local c
+ if n==0 or not n then
+ c=collected[1]
+ elseif n>1 then
+ c=collected[n]
+ else
+ c=collected[nc-n+1]
+ end
+ if not c then
+ elseif c.ns=="" then
+ return c.tg
+ else
+ return c.ns..":"..c.tg
+ end
+end
+local function tags(collected,nonamespace)
+ if not collected then
+ return
+ end
+ local nc=#collected
+ if nc==0 then
+ return
+ end
+ local t,n={},0
+ for c=1,nc do
+ local e=collected[c]
+ local ns,tg=e.ns,e.tg
+ n=n+1
+ if nonamespace or ns=="" then
+ t[n]=tg
+ else
+ t[n]=ns..":"..tg
+ end
+ end
+ return t
+end
+local function empty(collected,spacesonly)
+ if not collected then
+ return true
+ end
+ local nc=#collected
+ if nc==0 then
+ return true
+ end
+ for c=1,nc do
+ local e=collected[c]
+ if e then
+ local edt=e.dt
+ if edt then
+ local n=#edt
+ if n==1 then
+ local edk=edt[1]
+ local typ=type(edk)
+ if typ=="table" then
+ return false
+ elseif edk~="" then
+ return false
+ elseif spacesonly and not find(edk,"%S") then
+ return false
+ end
+ elseif n>1 then
+ return false
+ end
+ end
+ end
+ end
+ return true
+end
+finalizers.first=first
+finalizers.last=last
+finalizers.all=all
+finalizers.reverse=reverse
+finalizers.elements=all
+finalizers.default=all
+finalizers.attribute=attribute
+finalizers.att=att
+finalizers.count=count
+finalizers.position=position
+finalizers.match=match
+finalizers.index=index
+finalizers.attributes=attributes
+finalizers.chainattribute=chainattribute
+finalizers.text=text
+finalizers.texts=texts
+finalizers.tag=tag
+finalizers.name=name
+finalizers.tags=tags
+finalizers.empty=empty
+function xml.first(id,pattern)
+ return first(xmlfilter(id,pattern))
+end
+function xml.last(id,pattern)
+ return last(xmlfilter(id,pattern))
+end
+function xml.count(id,pattern)
+ return count(xmlfilter(id,pattern))
+end
+function xml.attribute(id,pattern,a,default)
+ return attribute(xmlfilter(id,pattern),a,default)
+end
+function xml.raw(id,pattern)
+ if pattern then
+ return raw(xmlfilter(id,pattern))
+ else
+ return raw(id)
+ end
+end
+function xml.text(id,pattern)
+ if pattern then
+ local collected=xmlfilter(id,pattern)
+ return collected and #collected>0 and xmltotext(collected[1]) or ""
+ elseif id then
+ return xmltotext(id) or ""
+ else
+ return ""
+ end
+end
+xml.content=text
+function xml.position(id,pattern,n)
+ return position(xmlfilter(id,pattern),n)
+end
+function xml.match(id,pattern)
+ return match(xmlfilter(id,pattern))
+end
+function xml.empty(id,pattern,spacesonly)
+ return empty(xmlfilter(id,pattern),spacesonly)
+end
+xml.all=xml.filter
+xml.index=xml.position
+xml.found=xml.filter
+local function totable(x)
+ local t={}
+ for e in xmlcollected(x[1] or x,"/*") do
+ t[e.tg]=xmltostring(e.dt) or ""
+ end
+ return next(t) and t or nil
+end
+xml.table=totable
+finalizers.table=totable
+local function textonly(e,t)
+ if e then
+ local edt=e.dt
+ if edt then
+ for i=1,#edt do
+ local e=edt[i]
+ if type(e)=="table" then
+ textonly(e,t)
else
- for kk=1,#blist do
- local vv = blist[kk]
- if find(lower(vv),path) then
- local full = methodhandler('concatinators',variant,tag,vv,bname) or ""
- result[#result+1] = resolve(full)
- done = true
- if not allresults then break end
- end
- end
+ t[#t+1]=e
end
+ end
end
- return done
+ end
+ return t
end
-
-
-local makewildcard = Cs(
- (P("^")^0 * P("/") * P(-1) + P(-1)) /".*"
- + (P("^")^0 * P("/") / "")^0 * (P("*")/".*" + P("-")/"%%-" + P(".")/"%%." + P("?")/"."+ P("\\")/"/" + P(1))^0
-)
-
-function resolvers.wildcardpattern(pattern)
- return lpegmatch(makewildcard,pattern) or pattern
-end
-
-local function findwildcardfiles(filename,allresults,result) -- todo: remap: and lpeg
- result = result or { }
- local base = filebasename(filename)
- local dirn = filedirname(filename)
- local path = lower(lpegmatch(makewildcard,dirn) or dirn)
- local name = lower(lpegmatch(makewildcard,base) or base)
- local files, done = instance.files, false
- if find(name,"%*") then
- local hashes = instance.hashes
- for k=1,#hashes do
- local hash = hashes[k]
- local hashname, hashtype = hash.name, hash.type
- for kk, hh in next, files[hashname] do
- if not find(kk,"^remap:") then
- if find(lower(kk),name) then
- if doit(path,hh,kk,hashname,hashtype,result,allresults) then done = true end
- if done and not allresults then break end
- end
- end
- end
+function xml.textonly(e)
+ return concat(textonly(e,{}))
+end
+function finalizers.lowerall(collected)
+ for c=1,#collected do
+ local e=collected[c]
+ if not e.special then
+ e.tg=lower(e.tg)
+ local eat=e.at
+ if eat then
+ local t={}
+ for k,v in next,eat do
+ t[lower(k)]=v
end
- else
- local hashes = instance.hashes
- for k=1,#hashes do
- local hash = hashes[k]
- local hashname, hashtype = hash.name, hash.type
- if doit(path,files[hashname][bname],bname,hashname,hashtype,result,allresults) then done = true end
- if done and not allresults then break end
+ e.at=t
+ end
+ end
+ end
+end
+function finalizers.upperall(collected)
+ for c=1,#collected do
+ local e=collected[c]
+ if not e.special then
+ e.tg=upper(e.tg)
+ local eat=e.at
+ if eat then
+ local t={}
+ for k,v in next,eat do
+ t[upper(k)]=v
end
+ e.at=t
+ end
end
- -- we can consider also searching the paths not in the database, but then
- -- we end up with a messy search (all // in all path specs)
- return result
+ end
end
-function resolvers.findwildcardfiles(filename,result)
- return findwildcardfiles(filename,true,result)
-end
-function resolvers.findwildcardfile(filename)
- return findwildcardfiles(filename,false)[1] or ""
-end
+end -- of closure
--- main user functions
+do -- create closure to overcome 200 locals limit
-function resolvers.automount()
- -- implemented later
-end
+package.loaded["trac-xml"] = package.loaded["trac-xml"] or true
-function resolvers.load(option)
- statistics.starttiming(instance)
- identify_configuration_files()
- load_configuration_files()
- if option ~= "nofiles" then
- load_databases()
- resolvers.automount()
- end
- statistics.stoptiming(instance)
- local files = instance.files
- return files and next(files) and true
-end
+-- original size: 6351, stripped down to: 4919
-function resolvers.loadtime()
- return statistics.elapsedtime(instance)
+if not modules then modules={} end modules ['trac-xml']={
+ version=1.001,
+ comment="companion to trac-log.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local formatters=string.formatters
+local reporters=logs.reporters
+local xmlserialize=xml.serialize
+local xmlcollected=xml.collected
+local xmltext=xml.text
+local xmlfirst=xml.first
+local function showhelp(specification,...)
+ local root=xml.convert(specification.helpinfo or "")
+ if not root then
+ return
+ end
+ local xs=xml.gethandlers("string")
+ xml.sethandlersfunction(xs,"short",function(e,handler) xmlserialize(e.dt,handler) end)
+ xml.sethandlersfunction(xs,"ref",function(e,handler) handler.handle("--"..e.at.name) end)
+ local wantedcategories=select("#",...)==0 and true or table.tohash {... }
+ local nofcategories=xml.count(root,"/application/flags/category")
+ local report=specification.report
+ for category in xmlcollected(root,"/application/flags/category") do
+ local categoryname=category.at.name or ""
+ if wantedcategories==true or wantedcategories[categoryname] then
+ if nofcategories>1 then
+ report("%s options:",categoryname)
+ report()
+ end
+ for subcategory in xmlcollected(category,"/subcategory") do
+ for flag in xmlcollected(subcategory,"/flag") do
+ local name=flag.at.name
+ local value=flag.at.value
+ local short=xmltext(xmlfirst(flag,"/short"))
+ if value then
+ report("--%-20s %s",formatters["%s=%s"](name,value),short)
+ else
+ report("--%-20s %s",name,short)
+ end
+ end
+ report()
+ end
+ end
+ end
+ for category in xmlcollected(root,"/application/examples/category") do
+ local title=xmltext(xmlfirst(category,"/title"))
+ if title and title~="" then
+ report()
+ report(title)
+ report()
+ end
+ for subcategory in xmlcollected(category,"/subcategory") do
+ for example in xmlcollected(subcategory,"/example") do
+ local command=xmltext(xmlfirst(example,"/command"))
+ local comment=xmltext(xmlfirst(example,"/comment"))
+ report(command)
+ end
+ report()
+ end
+ end
+ for comment in xmlcollected(root,"/application/comments/comment") do
+ local comment=xmltext(comment)
+ report()
+ report(comment)
+ report()
+ end
end
-
-local function report(str)
- if trace_locating then
- report_resolving(str) -- has already verbose
+local reporthelp=reporters.help
+local exporthelp=reporters.export
+local function xmlfound(t)
+ local helpinfo=t.helpinfo
+ if type(helpinfo)=="table" then
+ return false
+ end
+ if type(helpinfo)~="string" then
+ helpinfo="Warning: no helpinfo found."
+ t.helpinfo=helpinfo
+ return false
+ end
+ if string.find(helpinfo,".xml$") then
+ local ownscript=environment.ownscript
+ local helpdata=false
+ if ownscript then
+ local helpfile=file.join(file.pathpart(ownscript),helpinfo)
+ helpdata=io.loaddata(helpfile)
+ if helpdata=="" then
+ helpdata=false
+ end
+ end
+ if not helpdata then
+ local helpfile=resolvers.findfile(helpinfo,"tex")
+ helpdata=helpfile and io.loaddata(helpfile)
+ end
+ if helpdata and helpdata~="" then
+ helpinfo=helpdata
+ else
+ helpinfo=formatters["Warning: help file %a is not found."](helpinfo)
+ end
+ end
+ t.helpinfo=helpinfo
+ return string.find(t.helpinfo,"^<%?xml") and true or false
+end
+function reporters.help(t,...)
+ if xmlfound(t) then
+ showhelp(t,...)
+ else
+ reporthelp(t,...)
+ end
+end
+function reporters.export(t,methods,filename)
+ if not xmlfound(t) then
+ return exporthelp(t)
+ end
+ if not methods or methods=="" then
+ methods=environment.arguments["exporthelp"]
+ end
+ if not filename or filename=="" then
+ filename=environment.files[1]
+ end
+ dofile(resolvers.findfile("trac-exp.lua","tex"))
+ local exporters=logs.exporters
+ if not exporters or not methods then
+ return exporthelp(t)
+ end
+ if methods=="all" then
+ methods=table.keys(exporters)
+ elseif type(methods)=="string" then
+ methods=utilities.parsers.settings_to_array(methods)
+ else
+ return exporthelp(t)
+ end
+ if type(filename)~="string" or filename=="" then
+ filename=false
+ elseif file.pathpart(filename)=="" then
+ t.report("export file %a will not be saved on the current path (safeguard)",filename)
+ return
+ end
+ for i=1,#methods do
+ local method=methods[i]
+ local exporter=exporters[method]
+ if exporter then
+ local result=exporter(t,method)
+ if result and result~="" then
+ if filename then
+ local fullname=file.replacesuffix(filename,method)
+ t.report("saving export in %a",fullname)
+ io.savedata(fullname,result)
+ else
+ reporters.lines(t,result)
+ end
+ else
+ t.report("no output from exporter %a",method)
+ end
else
- print(str)
+ t.report("unknown exporter %a",method)
end
+ end
end
-function resolvers.dowithfilesandreport(command, files, ...) -- will move
- if files and #files > 0 then
- if trace_locating then
- report('') -- ?
- end
- if type(files) == "string" then
- files = { files }
- end
- for f=1,#files do
- local file = files[f]
- local result = command(file,...)
- if type(result) == 'string' then
- report(result)
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
+package.loaded["data-ini"] = package.loaded["data-ini"] or true
+
+-- original size: 7898, stripped down to: 5501
+
+if not modules then modules={} end modules ['data-ini']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files",
+}
+local gsub,find,gmatch,char=string.gsub,string.find,string.gmatch,string.char
+local next,type=next,type
+local filedirname,filebasename,filejoin=file.dirname,file.basename,file.join
+local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end)
+local trace_detail=false trackers.register("resolvers.details",function(v) trace_detail=v end)
+local trace_expansions=false trackers.register("resolvers.expansions",function(v) trace_expansions=v end)
+local report_initialization=logs.reporter("resolvers","initialization")
+local ostype,osname,ossetenv,osgetenv=os.type,os.name,os.setenv,os.getenv
+resolvers=resolvers or {}
+local resolvers=resolvers
+texconfig.kpse_init=false
+texconfig.shell_escape='t'
+if not (environment and environment.default_texmfcnf) and kpse and kpse.default_texmfcnf then
+ local default_texmfcnf=kpse.default_texmfcnf()
+ default_texmfcnf=gsub(default_texmfcnf,"$SELFAUTOLOC","selfautoloc:")
+ default_texmfcnf=gsub(default_texmfcnf,"$SELFAUTODIR","selfautodir:")
+ default_texmfcnf=gsub(default_texmfcnf,"$SELFAUTOPARENT","selfautoparent:")
+ default_texmfcnf=gsub(default_texmfcnf,"$HOME","home:")
+ environment.default_texmfcnf=default_texmfcnf
+end
+kpse={ original=kpse }
+setmetatable(kpse,{
+ __index=function(kp,name)
+ report_initialization("fatal error: kpse library is accessed (key: %s)",name)
+ os.exit()
+ end
+} )
+do
+ local osfontdir=osgetenv("OSFONTDIR")
+ if osfontdir and osfontdir~="" then
+ elseif osname=="windows" then
+ ossetenv("OSFONTDIR","c:/windows/fonts//")
+ elseif osname=="macosx" then
+ ossetenv("OSFONTDIR","$HOME/Library/Fonts//;/Library/Fonts//;/System/Library/Fonts//")
+ end
+end
+do
+ local homedir=osgetenv(ostype=="windows" and 'USERPROFILE' or 'HOME') or ''
+ if not homedir or homedir=="" then
+ homedir=char(127)
+ end
+ homedir=file.collapsepath(homedir)
+ ossetenv("HOME",homedir)
+ ossetenv("USERPROFILE",homedir)
+ environment.homedir=homedir
+end
+do
+ local args=environment.originalarguments or arg
+ if not environment.ownmain then
+ environment.ownmain=status and string.match(string.lower(status.banner),"this is ([%a]+)") or "luatex"
+ end
+ local ownbin=environment.ownbin or args[-2] or arg[-2] or args[-1] or arg[-1] or arg[0] or "luatex"
+ local ownpath=environment.ownpath or os.selfdir
+ ownbin=file.collapsepath(ownbin)
+ ownpath=file.collapsepath(ownpath)
+ if not ownpath or ownpath=="" or ownpath=="unset" then
+ ownpath=args[-1] or arg[-1]
+ ownpath=ownpath and filedirname(gsub(ownpath,"\\","/"))
+ if not ownpath or ownpath=="" then
+ ownpath=args[-0] or arg[-0]
+ ownpath=ownpath and filedirname(gsub(ownpath,"\\","/"))
+ end
+ local binary=ownbin
+ if not ownpath or ownpath=="" then
+ ownpath=ownpath and filedirname(binary)
+ end
+ if not ownpath or ownpath=="" then
+ if os.binsuffix~="" then
+ binary=file.replacesuffix(binary,os.binsuffix)
+ end
+ local path=osgetenv("PATH")
+ if path then
+ for p in gmatch(path,"[^"..io.pathseparator.."]+") do
+ local b=filejoin(p,binary)
+ if lfs.isfile(b) then
+ local olddir=lfs.currentdir()
+ if lfs.chdir(p) then
+ local pp=lfs.currentdir()
+ if trace_locating and p~=pp then
+ report_initialization("following symlink %a to %a",p,pp)
+ end
+ ownpath=pp
+ lfs.chdir(olddir)
else
- for i=1,#result do
- report(result[i]) -- could be unpack
- end
+ if trace_locating then
+ report_initialization("unable to check path %a",p)
+ end
+ ownpath=p
end
+ break
+ end
end
+ end
+ end
+ if not ownpath or ownpath=="" then
+ ownpath="."
+ report_initialization("forcing fallback to ownpath %a",ownpath)
+ elseif trace_locating then
+ report_initialization("using ownpath %a",ownpath)
end
+ end
+ environment.ownbin=ownbin
+ environment.ownpath=ownpath
+end
+resolvers.ownpath=environment.ownpath
+function resolvers.getownpath()
+ return environment.ownpath
+end
+do
+ local ownpath=environment.ownpath or dir.current()
+ if ownpath then
+ ossetenv('SELFAUTOLOC',file.collapsepath(ownpath))
+ ossetenv('SELFAUTODIR',file.collapsepath(ownpath.."/.."))
+ ossetenv('SELFAUTOPARENT',file.collapsepath(ownpath.."/../.."))
+ else
+ report_initialization("error: unable to locate ownpath")
+ os.exit()
+ end
+end
+local texos=environment.texos or osgetenv("TEXOS")
+local texmfos=environment.texmfos or osgetenv('SELFAUTODIR')
+if not texos or texos=="" then
+ texos=file.basename(texmfos)
+end
+ossetenv('TEXMFOS',texmfos)
+ossetenv('TEXOS',texos)
+ossetenv('SELFAUTOSYSTEM',os.platform)
+environment.texos=texos
+environment.texmfos=texmfos
+local texroot=environment.texroot or osgetenv("TEXROOT")
+if not texroot or texroot=="" then
+ texroot=osgetenv('SELFAUTOPARENT')
+ ossetenv('TEXROOT',texroot)
+end
+environment.texroot=file.collapsepath(texroot)
+if profiler then
+ directives.register("system.profile",function()
+ profiler.start("luatex-profile.log")
+ end)
+end
+if not resolvers.resolve then
+ function resolvers.resolve (s) return s end
+ function resolvers.unresolve(s) return s end
+ function resolvers.repath (s) return s end
end
--- obsolete
--- resolvers.varvalue = resolvers.variable -- output the value of variable $STRING.
--- resolvers.expandvar = resolvers.expansion -- output variable expansion of STRING.
+end -- of closure
-function resolvers.showpath(str) -- output search path for file type NAME
- return joinpath(resolvers.expandedpathlist(resolvers.formatofvariable(str)))
-end
+do -- create closure to overcome 200 locals limit
-function resolvers.registerfile(files, name, path)
- if files[name] then
- if type(files[name]) == 'string' then
- files[name] = { files[name], path }
- else
- files[name] = path
- end
- else
- files[name] = path
+package.loaded["data-exp"] = package.loaded["data-exp"] or true
+
+-- original size: 14643, stripped down to: 9517
+
+if not modules then modules={} end modules ['data-exp']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files",
+}
+local format,find,gmatch,lower,char,sub=string.format,string.find,string.gmatch,string.lower,string.char,string.sub
+local concat,sort=table.concat,table.sort
+local lpegmatch,lpegpatterns=lpeg.match,lpeg.patterns
+local Ct,Cs,Cc,P,C,S=lpeg.Ct,lpeg.Cs,lpeg.Cc,lpeg.P,lpeg.C,lpeg.S
+local type,next=type,next
+local ostype=os.type
+local collapsepath=file.collapsepath
+local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end)
+local trace_expansions=false trackers.register("resolvers.expansions",function(v) trace_expansions=v end)
+local report_expansions=logs.reporter("resolvers","expansions")
+local resolvers=resolvers
+local function f_first(a,b)
+ local t,n={},0
+ for s in gmatch(b,"[^,]+") do
+ n=n+1;t[n]=a..s
+ end
+ return concat(t,",")
+end
+local function f_second(a,b)
+ local t,n={},0
+ for s in gmatch(a,"[^,]+") do
+ n=n+1;t[n]=s..b
+ end
+ return concat(t,",")
+end
+local function f_both(a,b)
+ local t,n={},0
+ for sb in gmatch(b,"[^,]+") do
+ for sa in gmatch(a,"[^,]+") do
+ n=n+1;t[n]=sa..sb
+ end
+ end
+ return concat(t,",")
+end
+local left=P("{")
+local right=P("}")
+local var=P((1-S("{}" ))^0)
+local set=P((1-S("{},"))^0)
+local other=P(1)
+local l_first=Cs((Cc("{")*(C(set)*left*C(var)*right/f_first)*Cc("}")+other )^0 )
+local l_second=Cs((Cc("{")*(left*C(var)*right*C(set)/f_second)*Cc("}")+other )^0 )
+local l_both=Cs((Cc("{")*(left*C(var)*right*left*C(var)*right/f_both)*Cc("}")+other )^0 )
+local l_rest=Cs((left*var*(left/"")*var*(right/"")*var*right+other )^0 )
+local stripper_1=lpeg.stripper ("{}@")
+local replacer_1=lpeg.replacer { { ",}",",@}" },{ "{,","{@," },}
+local function splitpathexpr(str,newlist,validate)
+ if trace_expansions then
+ report_expansions("expanding variable %a",str)
+ end
+ local t,ok,done=newlist or {},false,false
+ local n=#t
+ str=lpegmatch(replacer_1,str)
+ repeat
+ local old=str
+ repeat
+ local old=str
+ str=lpegmatch(l_first,str)
+ until old==str
+ repeat
+ local old=str
+ str=lpegmatch(l_second,str)
+ until old==str
+ repeat
+ local old=str
+ str=lpegmatch(l_both,str)
+ until old==str
+ repeat
+ local old=str
+ str=lpegmatch(l_rest,str)
+ until old==str
+ until old==str
+ str=lpegmatch(stripper_1,str)
+ if validate then
+ for s in gmatch(str,"[^,]+") do
+ s=validate(s)
+ if s then
+ n=n+1
+ t[n]=s
+ end
+ end
+ else
+ for s in gmatch(str,"[^,]+") do
+ n=n+1
+ t[n]=s
+ end
+ end
+ if trace_expansions then
+ for k=1,#t do
+ report_expansions("% 4i: %s",k,t[k])
end
+ end
+ return t
end
-
-function resolvers.dowithpath(name,func)
- local pathlist = resolvers.expandedpathlist(name)
- for i=1,#pathlist do
- func("^"..resolvers.cleanpath(pathlist[i]))
+local function validate(s)
+ s=collapsepath(s)
+ return s~="" and not find(s,"^!*unset/*$") and s
+end
+resolvers.validatedpath=validate
+function resolvers.expandedpathfromlist(pathlist)
+ local newlist={}
+ for k=1,#pathlist do
+ splitpathexpr(pathlist[k],newlist,validate)
+ end
+ return newlist
+end
+local cleanup=lpeg.replacer {
+ { "!","" },
+ { "\\","/" },
+}
+function resolvers.cleanpath(str)
+ local doslashes=(P("\\")/"/"+1)^0
+ local donegation=(P("!")/"" )^0
+ local homedir=lpegmatch(Cs(donegation*doslashes),environment.homedir or "")
+ if homedir=="~" or homedir=="" or not lfs.isdir(homedir) then
+ if trace_expansions then
+ report_expansions("no home dir set, ignoring dependent paths")
+ end
+ function resolvers.cleanpath(str)
+ if not str or find(str,"~") then
+ return ""
+ else
+ return lpegmatch(cleanup,str)
+ end
+ end
+ else
+ local dohome=((P("~")+P("$HOME"))/homedir)^0
+ local cleanup=Cs(donegation*dohome*doslashes)
+ function resolvers.cleanpath(str)
+ return str and lpegmatch(cleanup,str) or ""
+ end
+ end
+ return resolvers.cleanpath(str)
+end
+local expandhome=P("~")/"$HOME"
+local dodouble=P('"')/""*(expandhome+(1-P('"')))^0*P('"')/""
+local dosingle=P("'")/""*(expandhome+(1-P("'")))^0*P("'")/""
+local dostring=(expandhome+1 )^0
+local stripper=Cs(
+ lpegpatterns.unspacer*(dosingle+dodouble+dostring)*lpegpatterns.unspacer
+)
+function resolvers.checkedvariable(str)
+ return type(str)=="string" and lpegmatch(stripper,str) or str
+end
+local cache={}
+local splitter=lpeg.tsplitat(";")
+local backslashswapper=lpeg.replacer("\\","/")
+local function splitconfigurationpath(str)
+ if str then
+ local found=cache[str]
+ if not found then
+ if str=="" then
+ found={}
+ else
+ local split=lpegmatch(splitter,lpegmatch(backslashswapper,str))
+ found={}
+ local noffound=0
+ for i=1,#split do
+ local s=split[i]
+ if not find(s,"^{*unset}*") then
+ noffound=noffound+1
+ found[noffound]=s
+ end
+ end
+ if trace_expansions then
+ report_expansions("splitting path specification %a",str)
+ for k=1,noffound do
+ report_expansions("% 4i: %s",k,found[k])
+ end
+ end
+ cache[str]=found
+ end
end
+ return found
+ end
end
-
-function resolvers.dowithvariable(name,func)
- func(expandedvariable(name))
+resolvers.splitconfigurationpath=splitconfigurationpath
+function resolvers.splitpath(str)
+ if type(str)=='table' then
+ return str
+ else
+ return splitconfigurationpath(str)
+ end
end
-
-function resolvers.locateformat(name)
- local barename = file.removesuffix(name) -- gsub(name,"%.%a+$","")
- local fmtname = caches.getfirstreadablefile(barename..".fmt","formats") or ""
- if fmtname == "" then
- fmtname = resolvers.findfile(barename..".fmt")
- fmtname = resolvers.cleanpath(fmtname)
- end
- if fmtname ~= "" then
- local barename = file.removesuffix(fmtname)
- local luaname, lucname, luiname = barename .. ".lua", barename .. ".luc", barename .. ".lui"
- if lfs.isfile(luiname) then
- return barename, luiname
- elseif lfs.isfile(lucname) then
- return barename, lucname
- elseif lfs.isfile(luaname) then
- return barename, luaname
+function resolvers.joinpath(str)
+ if type(str)=='table' then
+ return file.joinpath(str)
+ else
+ return str
+ end
+end
+local attributes,directory=lfs.attributes,lfs.dir
+local weird=P(".")^1+lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+local timer={}
+local scanned={}
+local nofscans=0
+local scancache={}
+local function scan(files,spec,path,n,m,r)
+ local full=(path=="" and spec) or (spec..path..'/')
+ local dirs={}
+ local nofdirs=0
+ for name in directory(full) do
+ if not lpegmatch(weird,name) then
+ local mode=attributes(full..name,'mode')
+ if mode=='file' then
+ n=n+1
+ local f=files[name]
+ if f then
+ if type(f)=='string' then
+ files[name]={ f,path }
+ else
+ f[#f+1]=path
+ end
+ else
+ files[name]=path
+ local lower=lower(name)
+ if name~=lower then
+ files["remap:"..lower]=name
+ r=r+1
+ end
+ end
+ elseif mode=='directory' then
+ m=m+1
+ nofdirs=nofdirs+1
+ if path~="" then
+ dirs[nofdirs]=path..'/'..name
+ else
+ dirs[nofdirs]=name
end
+ end
end
- return nil, nil
-end
-
-function resolvers.booleanvariable(str,default)
- local b = resolvers.expansion(str)
- if b == "" then
- return default
- else
- b = toboolean(b)
- return (b == nil and default) or b
+ end
+ if nofdirs>0 then
+ sort(dirs)
+ for i=1,nofdirs do
+ files,n,m,r=scan(files,spec,dirs[i],n,m,r)
end
+ end
+ scancache[sub(full,1,-2)]=files
+ return files,n,m,r
end
-
-function resolvers.dowithfilesintree(pattern,handle,before,after) -- will move, can be a nice iterator instead
- local instance = resolvers.instance
- local hashes = instance.hashes
- for i=1,#hashes do
- local hash = hashes[i]
- local blobtype = hash.type
- local blobpath = hash.name
- if blobpath then
- if before then
- before(blobtype,blobpath,pattern)
- end
- local files = instance.files[blobpath]
- local total, checked, done = 0, 0, 0
- if files then
- for k,v in next, files do
- total = total + 1
- if find(k,"^remap:") then
- k = files[k]
- v = k -- files[k] -- chained
- end
- if find(k,pattern) then
- if type(v) == "string" then
- checked = checked + 1
- if handle(blobtype,blobpath,v,k) then
- done = done + 1
- end
- else
- checked = checked + #v
- for i=1,#v do
- if handle(blobtype,blobpath,v[i],k) then
- done = done + 1
- end
- end
- end
- end
- end
- end
- if after then
- after(blobtype,blobpath,pattern,total,checked,done)
- end
+local fullcache={}
+function resolvers.scanfiles(path,branch,usecache)
+ statistics.starttiming(timer)
+ local realpath=resolvers.resolve(path)
+ if usecache then
+ local files=fullcache[realpath]
+ if files then
+ if trace_locating then
+ report_expansions("using caches scan of path %a, branch %a",path,branch or path)
+ end
+ return files
+ end
+ end
+ if trace_locating then
+ report_expansions("scanning path %a, branch %a",path,branch or path)
+ end
+ local files,n,m,r=scan({},realpath..'/',"",0,0,0)
+ files.__path__=path
+ files.__files__=n
+ files.__directories__=m
+ files.__remappings__=r
+ if trace_locating then
+ report_expansions("%s files found on %s directories with %s uppercase remappings",n,m,r)
+ end
+ if usecache then
+ scanned[#scanned+1]=realpath
+ fullcache[realpath]=files
+ end
+ nofscans=nofscans+1
+ statistics.stoptiming(timer)
+ return files
+end
+local function simplescan(files,spec,path)
+ local full=(path=="" and spec) or (spec..path..'/')
+ local dirs={}
+ local nofdirs=0
+ for name in directory(full) do
+ if not lpegmatch(weird,name) then
+ local mode=attributes(full..name,'mode')
+ if mode=='file' then
+ if not files[name] then
+ files[name]=path
+ end
+ elseif mode=='directory' then
+ nofdirs=nofdirs+1
+ if path~="" then
+ dirs[nofdirs]=path..'/'..name
+ else
+ dirs[nofdirs]=name
end
+ end
end
+ end
+ if nofdirs>0 then
+ sort(dirs)
+ for i=1,nofdirs do
+ files=simplescan(files,spec,dirs[i])
+ end
+ end
+ return files
+end
+local simplecache={}
+local nofsharedscans=0
+function resolvers.simplescanfiles(path,branch,usecache)
+ statistics.starttiming(timer)
+ local realpath=resolvers.resolve(path)
+ if usecache then
+ local files=simplecache[realpath]
+ if not files then
+ files=scancache[realpath]
+ if files then
+ nofsharedscans=nofsharedscans+1
+ end
+ end
+ if files then
+ if trace_locating then
+ report_expansions("using caches scan of path %a, branch %a",path,branch or path)
+ end
+ return files
+ end
+ end
+ if trace_locating then
+ report_expansions("scanning path %a, branch %a",path,branch or path)
+ end
+ local files=simplescan({},realpath..'/',"")
+ if trace_locating then
+ report_expansions("%s files found",table.count(files))
+ end
+ if usecache then
+ scanned[#scanned+1]=realpath
+ simplecache[realpath]=files
+ end
+ nofscans=nofscans+1
+ statistics.stoptiming(timer)
+ return files
+end
+function resolvers.scandata()
+ table.sort(scanned)
+ return {
+ n=nofscans,
+ shared=nofsharedscans,
+ time=statistics.elapsedtime(timer),
+ paths=scanned,
+ }
end
-
-resolvers.obsolete = resolvers.obsolete or { }
-local obsolete = resolvers.obsolete
-
-resolvers.find_file = resolvers.findfile obsolete.find_file = resolvers.findfile
-resolvers.find_files = resolvers.findfiles obsolete.find_files = resolvers.findfiles
end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['data-pre'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- It could be interesting to hook the resolver in the file
--- opener so that unresolved prefixes travel around and we
--- get more abstraction.
-
--- As we use this beforehand we will move this up in the chain
--- of loading.
-
-
-local resolvers = resolvers
-local prefixes = utilities.storage.allocate()
-resolvers.prefixes = prefixes
+package.loaded["data-env"] = package.loaded["data-env"] or true
-local gsub = string.gsub
-local cleanpath, findgivenfile, expansion = resolvers.cleanpath, resolvers.findgivenfile, resolvers.expansion
-local getenv = resolvers.getenv -- we can probably also use resolvers.expansion
-local P, Cs, lpegmatch = lpeg.P, lpeg.Cs, lpeg.match
+-- original size: 8762, stripped down to: 6484
--- getenv = function(...) return resolvers.getenv(...) end -- needs checking (definitions changes later on)
-
-prefixes.environment = function(str)
- return cleanpath(expansion(str))
+if not modules then modules={} end modules ['data-env']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files",
+}
+local lower,gsub=string.lower,string.gsub
+local resolvers=resolvers
+local allocate=utilities.storage.allocate
+local setmetatableindex=table.setmetatableindex
+local suffixonly=file.suffixonly
+local formats=allocate()
+local suffixes=allocate()
+local dangerous=allocate()
+local suffixmap=allocate()
+resolvers.formats=formats
+resolvers.suffixes=suffixes
+resolvers.dangerous=dangerous
+resolvers.suffixmap=suffixmap
+local luasuffixes=utilities.lua.suffixes
+local relations=allocate {
+ core={
+ ofm={
+ names={ "ofm","omega font metric","omega font metrics" },
+ variable='OFMFONTS',
+ suffixes={ 'ofm','tfm' },
+ },
+ ovf={
+ names={ "ovf","omega virtual font","omega virtual fonts" },
+ variable='OVFFONTS',
+ suffixes={ 'ovf','vf' },
+ },
+ tfm={
+ names={ "tfm","tex font metric","tex font metrics" },
+ variable='TFMFONTS',
+ suffixes={ 'tfm' },
+ },
+ vf={
+ names={ "vf","virtual font","virtual fonts" },
+ variable='VFFONTS',
+ suffixes={ 'vf' },
+ },
+ otf={
+ names={ "otf","opentype","opentype font","opentype fonts"},
+ variable='OPENTYPEFONTS',
+ suffixes={ 'otf' },
+ },
+ ttf={
+ names={ "ttf","truetype","truetype font","truetype fonts","truetype collection","truetype collections","truetype dictionary","truetype dictionaries" },
+ variable='TTFONTS',
+ suffixes={ 'ttf','ttc','dfont' },
+ },
+ afm={
+ names={ "afm","adobe font metric","adobe font metrics" },
+ variable="AFMFONTS",
+ suffixes={ "afm" },
+ },
+ pfb={
+ names={ "pfb","type1","type 1","type1 font","type 1 font","type1 fonts","type 1 fonts" },
+ variable='T1FONTS',
+ suffixes={ 'pfb','pfa' },
+ },
+ fea={
+ names={ "fea","font feature","font features","font feature file","font feature files" },
+ variable='FONTFEATURES',
+ suffixes={ 'fea' },
+ },
+ cid={
+ names={ "cid","cid map","cid maps","cid file","cid files" },
+ variable='FONTCIDMAPS',
+ suffixes={ 'cid','cidmap' },
+ },
+ fmt={
+ names={ "fmt","format","tex format" },
+ variable='TEXFORMATS',
+ suffixes={ 'fmt' },
+ },
+ mem={
+ names={ 'mem',"metapost format" },
+ variable='MPMEMS',
+ suffixes={ 'mem' },
+ },
+ mp={
+ names={ "mp" },
+ variable='MPINPUTS',
+ suffixes={ 'mp','mpvi','mpiv','mpii' },
+ },
+ tex={
+ names={ "tex" },
+ variable='TEXINPUTS',
+ suffixes={ 'tex',"mkvi","mkiv","mkii" },
+ },
+ icc={
+ names={ "icc","icc profile","icc profiles" },
+ variable='ICCPROFILES',
+ suffixes={ 'icc' },
+ },
+ texmfscripts={
+ names={ "texmfscript","texmfscripts","script","scripts" },
+ variable='TEXMFSCRIPTS',
+ suffixes={ 'rb','pl','py' },
+ },
+ lua={
+ names={ "lua" },
+ variable='LUAINPUTS',
+ suffixes={ luasuffixes.lua,luasuffixes.luc,luasuffixes.tma,luasuffixes.tmc },
+ },
+ lib={
+ names={ "lib" },
+ variable='CLUAINPUTS',
+ suffixes=os.libsuffix and { os.libsuffix } or { 'dll','so' },
+ },
+ bib={
+ names={ 'bib' },
+ suffixes={ 'bib' },
+ },
+ bst={
+ names={ 'bst' },
+ suffixes={ 'bst' },
+ },
+ fontconfig={
+ names={ 'fontconfig','fontconfig file','fontconfig files' },
+ variable='FONTCONFIG_PATH',
+ },
+ },
+ obsolete={
+ enc={
+ names={ "enc","enc files","enc file","encoding files","encoding file" },
+ variable='ENCFONTS',
+ suffixes={ 'enc' },
+ },
+ map={
+ names={ "map","map files","map file" },
+ variable='TEXFONTMAPS',
+ suffixes={ 'map' },
+ },
+ lig={
+ names={ "lig files","lig file","ligature file","ligature files" },
+ variable='LIGFONTS',
+ suffixes={ 'lig' },
+ },
+ opl={
+ names={ "opl" },
+ variable='OPLFONTS',
+ suffixes={ 'opl' },
+ },
+ ovp={
+ names={ "ovp" },
+ variable='OVPFONTS',
+ suffixes={ 'ovp' },
+ },
+ },
+ kpse={
+ base={
+ names={ 'base',"metafont format" },
+ variable='MFBASES',
+ suffixes={ 'base','bas' },
+ },
+ cmap={
+ names={ 'cmap','cmap files','cmap file' },
+ variable='CMAPFONTS',
+ suffixes={ 'cmap' },
+ },
+ cnf={
+ names={ 'cnf' },
+ suffixes={ 'cnf' },
+ },
+ web={
+ names={ 'web' },
+ suffixes={ 'web','ch' }
+ },
+ cweb={
+ names={ 'cweb' },
+ suffixes={ 'w','web','ch' },
+ },
+ gf={
+ names={ 'gf' },
+ suffixes={ 'gf' },
+ },
+ mf={
+ names={ 'mf' },
+ variable='MFINPUTS',
+ suffixes={ 'mf' },
+ },
+ mft={
+ names={ 'mft' },
+ suffixes={ 'mft' },
+ },
+ pk={
+ names={ 'pk' },
+ suffixes={ 'pk' },
+ },
+ },
+}
+resolvers.relations=relations
+function resolvers.updaterelations()
+ for category,categories in next,relations do
+ for name,relation in next,categories do
+ local rn=relation.names
+ local rv=relation.variable
+ local rs=relation.suffixes
+ if rn and rv then
+ for i=1,#rn do
+ local rni=lower(gsub(rn[i]," ",""))
+ formats[rni]=rv
+ if rs then
+ suffixes[rni]=rs
+ for i=1,#rs do
+ local rsi=rs[i]
+ suffixmap[rsi]=rni
+ end
+ end
+ end
+ end
+ if rs then
+ end
+ end
+ end
+end
+resolvers.updaterelations()
+local function simplified(t,k)
+ return k and rawget(t,lower(gsub(k," ",""))) or nil
end
-
-prefixes.relative = function(str,n) -- lfs.isfile
- if io.exists(str) then
- -- nothing
- elseif io.exists("./" .. str) then
- str = "./" .. str
- else
- local p = "../"
- for i=1,n or 2 do
- if io.exists(p .. str) then
- str = p .. str
- break
- else
- p = p .. "../"
- end
- end
- end
- return cleanpath(str)
+setmetatableindex(formats,simplified)
+setmetatableindex(suffixes,simplified)
+setmetatableindex(suffixmap,simplified)
+function resolvers.suffixofformat(str)
+ local s=suffixes[str]
+ return s and s[1] or ""
end
-
-prefixes.auto = function(str)
- local fullname = prefixes.relative(str)
- if not lfs.isfile(fullname) then
- fullname = prefixes.locate(str)
- end
- return fullname
+function resolvers.suffixofformat(str)
+ return suffixes[str] or {}
end
-
-prefixes.locate = function(str)
- local fullname = findgivenfile(str) or ""
- return cleanpath((fullname ~= "" and fullname) or str)
+for name,format in next,formats do
+ dangerous[name]=true
end
-
-prefixes.filename = function(str)
- local fullname = findgivenfile(str) or ""
- return cleanpath(file.basename((fullname ~= "" and fullname) or str)) -- no cleanpath needed here
+dangerous.tex=nil
+function resolvers.formatofvariable(str)
+ return formats[str] or ''
end
-
-prefixes.pathname = function(str)
- local fullname = findgivenfile(str) or ""
- return cleanpath(file.dirname((fullname ~= "" and fullname) or str))
+function resolvers.formatofsuffix(str)
+ return suffixmap[suffixonly(str)] or 'tex'
end
-
-prefixes.selfautoloc = function(str)
- return cleanpath(file.join(getenv('SELFAUTOLOC'),str))
+function resolvers.variableofformat(str)
+ return formats[str] or ''
end
-
-prefixes.selfautoparent = function(str)
- return cleanpath(file.join(getenv('SELFAUTOPARENT'),str))
+function resolvers.variableofformatorsuffix(str)
+ local v=formats[str]
+ if v then
+ return v
+ end
+ v=suffixmap[suffixonly(str)]
+ if v then
+ return formats[v]
+ end
+ return ''
end
-prefixes.selfautodir = function(str)
- return cleanpath(file.join(getenv('SELFAUTODIR'),str))
-end
-prefixes.home = function(str)
- return cleanpath(file.join(getenv('HOME'),str))
-end
+end -- of closure
-prefixes.env = prefixes.environment
-prefixes.rel = prefixes.relative
-prefixes.loc = prefixes.locate
-prefixes.kpse = prefixes.locate
-prefixes.full = prefixes.locate
-prefixes.file = prefixes.filename
-prefixes.path = prefixes.pathname
+do -- create closure to overcome 200 locals limit
-function resolvers.allprefixes(separator)
- local all = table.sortedkeys(prefixes)
- if separator then
- for i=1,#all do
- all[i] = all[i] .. ":"
+package.loaded["data-tmp"] = package.loaded["data-tmp"] or true
+
+-- original size: 14308, stripped down to: 10956
+
+if not modules then modules={} end modules ['data-tmp']={
+ version=1.100,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local format,lower,gsub,concat=string.format,string.lower,string.gsub,table.concat
+local serialize,serializetofile=table.serialize,table.tofile
+local mkdirs,isdir,isfile=dir.mkdirs,lfs.isdir,lfs.isfile
+local addsuffix,is_writable,is_readable=file.addsuffix,file.is_writable,file.is_readable
+local formatters=string.formatters
+local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end)
+local trace_cache=false trackers.register("resolvers.cache",function(v) trace_cache=v end)
+local report_caches=logs.reporter("resolvers","caches")
+local report_resolvers=logs.reporter("resolvers","caching")
+local resolvers=resolvers
+local directive_cleanup=false directives.register("system.compile.cleanup",function(v) directive_cleanup=v end)
+local directive_strip=false directives.register("system.compile.strip",function(v) directive_strip=v end)
+local compile=utilities.lua.compile
+function utilities.lua.compile(luafile,lucfile,cleanup,strip)
+ if cleanup==nil then cleanup=directive_cleanup end
+ if strip==nil then strip=directive_strip end
+ return compile(luafile,lucfile,cleanup,strip)
+end
+caches=caches or {}
+local caches=caches
+local luasuffixes=utilities.lua.suffixes
+caches.base=caches.base or "luatex-cache"
+caches.more=caches.more or "context"
+caches.direct=false
+caches.tree=false
+caches.force=true
+caches.ask=false
+caches.relocate=false
+caches.defaults={ "TMPDIR","TEMPDIR","TMP","TEMP","HOME","HOMEPATH" }
+local writable,readables,usedreadables=nil,{},{}
+local function identify()
+ local texmfcaches=resolvers.cleanpathlist("TEXMFCACHE")
+ if texmfcaches then
+ for k=1,#texmfcaches do
+ local cachepath=texmfcaches[k]
+ if cachepath~="" then
+ cachepath=resolvers.resolve(cachepath)
+ cachepath=resolvers.cleanpath(cachepath)
+ cachepath=file.collapsepath(cachepath)
+ local valid=isdir(cachepath)
+ if valid then
+ if is_readable(cachepath) then
+ readables[#readables+1]=cachepath
+ if not writable and is_writable(cachepath) then
+ writable=cachepath
+ end
+ end
+ elseif not writable and caches.force then
+ local cacheparent=file.dirname(cachepath)
+ if is_writable(cacheparent) and true then
+ if not caches.ask or io.ask(format("\nShould I create the cache path %s?",cachepath),"no",{ "yes","no" })=="yes" then
+ mkdirs(cachepath)
+ if isdir(cachepath) and is_writable(cachepath) then
+ report_caches("path %a created",cachepath)
+ writable=cachepath
+ readables[#readables+1]=cachepath
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ local texmfcaches=caches.defaults
+ if texmfcaches then
+ for k=1,#texmfcaches do
+ local cachepath=texmfcaches[k]
+ cachepath=resolvers.expansion(cachepath)
+ if cachepath~="" then
+ cachepath=resolvers.resolve(cachepath)
+ cachepath=resolvers.cleanpath(cachepath)
+ local valid=isdir(cachepath)
+ if valid and is_readable(cachepath) then
+ if not writable and is_writable(cachepath) then
+ readables[#readables+1]=cachepath
+ writable=cachepath
+ break
+ end
end
+ end
+ end
+ end
+ if not writable then
+ report_caches("fatal error: there is no valid writable cache path defined")
+ os.exit()
+ elseif #readables==0 then
+ report_caches("fatal error: there is no valid readable cache path defined")
+ os.exit()
+ end
+ writable=dir.expandname(resolvers.cleanpath(writable))
+ local base,more,tree=caches.base,caches.more,caches.tree or caches.treehash()
+ if tree then
+ caches.tree=tree
+ writable=mkdirs(writable,base,more,tree)
+ for i=1,#readables do
+ readables[i]=file.join(readables[i],base,more,tree)
+ end
+ else
+ writable=mkdirs(writable,base,more)
+ for i=1,#readables do
+ readables[i]=file.join(readables[i],base,more)
end
- return all
+ end
+ if trace_cache then
+ for i=1,#readables do
+ report_caches("using readable path %a (order %s)",readables[i],i)
+ end
+ report_caches("using writable path %a",writable)
+ end
+ identify=function()
+ return writable,readables
+ end
+ return writable,readables
end
-
-local function _resolve_(method,target)
- local action = prefixes[method]
- if action then
- return action(target)
- else
- return method .. ":" .. target
+function caches.usedpaths()
+ local writable,readables=identify()
+ if #readables>1 then
+ local result={}
+ for i=1,#readables do
+ local readable=readables[i]
+ if usedreadables[i] or readable==writable then
+ result[#result+1]=formatters["readable: %a (order %s)"](readable,i)
+ end
end
+ result[#result+1]=formatters["writable: %a"](writable)
+ return result
+ else
+ return writable
+ end
end
-
-local resolved, abstract = { }, { }
-
-function resolvers.resetresolve(str)
- resolved, abstract = { }, { }
+function caches.configfiles()
+ return concat(resolvers.instance.specification,";")
end
-
-local function resolve(str) -- use schemes, this one is then for the commandline only
- if type(str) == "table" then
- local t = { }
- for i=1,#str do
- t[i] = resolve(str[i])
- end
- return t
+function caches.hashed(tree)
+ tree=gsub(tree,"[\\/]+$","")
+ tree=lower(tree)
+ local hash=md5.hex(tree)
+ if trace_cache or trace_locating then
+ report_caches("hashing tree %a, hash %a",tree,hash)
+ end
+ return hash
+end
+function caches.treehash()
+ local tree=caches.configfiles()
+ if not tree or tree=="" then
+ return false
+ else
+ return caches.hashed(tree)
+ end
+end
+local r_cache,w_cache={},{}
+local function getreadablepaths(...)
+ local tags={... }
+ local hash=concat(tags,"/")
+ local done=r_cache[hash]
+ if not done then
+ local writable,readables=identify()
+ if #tags>0 then
+ done={}
+ for i=1,#readables do
+ done[i]=file.join(readables[i],...)
+ end
else
- local res = resolved[str]
- if not res then
- res = gsub(str,"([a-z][a-z]+):([^ \"\';,]*)",_resolve_) -- home:xx;selfautoparent:xx; etc (comma added)
- resolved[str] = res
- abstract[res] = str
- end
- return res
+ done=readables
end
+ r_cache[hash]=done
+ end
+ return done
end
-
-local function unresolve(str)
- return abstract[str] or str
+local function getwritablepath(...)
+ local tags={... }
+ local hash=concat(tags,"/")
+ local done=w_cache[hash]
+ if not done then
+ local writable,readables=identify()
+ if #tags>0 then
+ done=mkdirs(writable,...)
+ else
+ done=writable
+ end
+ w_cache[hash]=done
+ end
+ return done
end
-
-resolvers.resolve = resolve
-resolvers.unresolve = unresolve
-
-if os.uname then
-
- for k, v in next, os.uname() do
- if not prefixes[k] then
- prefixes[k] = function() return v end
- end
+caches.getreadablepaths=getreadablepaths
+caches.getwritablepath=getwritablepath
+function caches.getfirstreadablefile(filename,...)
+ local rd=getreadablepaths(...)
+ for i=1,#rd do
+ local path=rd[i]
+ local fullname=file.join(path,filename)
+ if is_readable(fullname) then
+ usedreadables[i]=true
+ return fullname,path
end
-
+ end
+ return caches.setfirstwritablefile(filename,...)
end
-
-if os.type == "unix" then
-
- local pattern
-
- local function makepattern(t,k,v)
- local colon = P(":")
- local p
- for k, v in table.sortedpairs(prefixes) do
- if p then
- p = P(k) + p
- else
- p = P(k)
- end
- end
- pattern = Cs((p * colon + colon/";" + P(1))^0)
- if t then
- t[k] = v
+function caches.setfirstwritablefile(filename,...)
+ local wr=getwritablepath(...)
+ local fullname=file.join(wr,filename)
+ return fullname,wr
+end
+function caches.define(category,subcategory)
+ return function()
+ return getwritablepath(category,subcategory)
+ end
+end
+function caches.setluanames(path,name)
+ return format("%s/%s.%s",path,name,luasuffixes.tma),format("%s/%s.%s",path,name,luasuffixes.tmc)
+end
+function caches.loaddata(readables,name)
+ if type(readables)=="string" then
+ readables={ readables }
+ end
+ for i=1,#readables do
+ local path=readables[i]
+ local tmaname,tmcname=caches.setluanames(path,name)
+ local loader=false
+ if isfile(tmcname) then
+ loader=loadfile(tmcname)
+ end
+ if not loader and isfile(tmaname) then
+ utilities.lua.compile(tmaname,tmcname)
+ if isfile(tmcname) then
+ loader=loadfile(tmcname)
+ end
+ if not loader then
+ loader=loadfile(tmaname)
+ end
+ end
+ if loader then
+ loader=loader()
+ collectgarbage("step")
+ return loader
+ end
+ end
+ return false
+end
+function caches.is_writable(filepath,filename)
+ local tmaname,tmcname=caches.setluanames(filepath,filename)
+ return is_writable(tmaname)
+end
+local saveoptions={ compact=true }
+function caches.savedata(filepath,filename,data,raw)
+ local tmaname,tmcname=caches.setluanames(filepath,filename)
+ local reduce,simplify=true,true
+ if raw then
+ reduce,simplify=false,false
+ end
+ data.cache_uuid=os.uuid()
+ if caches.direct then
+ file.savedata(tmaname,serialize(data,true,saveoptions))
+ else
+ serializetofile(tmaname,data,true,saveoptions)
+ end
+ utilities.lua.compile(tmaname,tmcname)
+end
+local content_state={}
+function caches.contentstate()
+ return content_state or {}
+end
+function caches.loadcontent(cachename,dataname)
+ local name=caches.hashed(cachename)
+ local full,path=caches.getfirstreadablefile(addsuffix(name,luasuffixes.lua),"trees")
+ local filename=file.join(path,name)
+ local blob=loadfile(addsuffix(filename,luasuffixes.luc)) or loadfile(addsuffix(filename,luasuffixes.lua))
+ if blob then
+ local data=blob()
+ if data and data.content then
+ if data.type==dataname then
+ if data.version==resolvers.cacheversion then
+ content_state[#content_state+1]=data.uuid
+ if trace_locating then
+ report_resolvers("loading %a for %a from %a",dataname,cachename,filename)
+ end
+ return data.content
+ else
+ report_resolvers("skipping %a for %a from %a (version mismatch)",dataname,cachename,filename)
end
+ else
+ report_resolvers("skipping %a for %a from %a (datatype mismatch)",dataname,cachename,filename)
+ end
+ elseif trace_locating then
+ report_resolvers("skipping %a for %a from %a (no content)",dataname,cachename,filename)
end
-
- makepattern()
-
- getmetatable(prefixes).__newindex = makepattern
-
- function resolvers.repath(str)
- return lpegmatch(pattern,str)
+ elseif trace_locating then
+ report_resolvers("skipping %a for %a from %a (invalid file)",dataname,cachename,filename)
+ end
+end
+function caches.collapsecontent(content)
+ for k,v in next,content do
+ if type(v)=="table" and #v==1 then
+ content[k]=v[1]
end
-
-else -- already the default:
-
- function resolvers.repath(str)
- return str
+ end
+end
+function caches.savecontent(cachename,dataname,content)
+ local name=caches.hashed(cachename)
+ local full,path=caches.setfirstwritablefile(addsuffix(name,luasuffixes.lua),"trees")
+ local filename=file.join(path,name)
+ local luaname=addsuffix(filename,luasuffixes.lua)
+ local lucname=addsuffix(filename,luasuffixes.luc)
+ if trace_locating then
+ report_resolvers("preparing %a for %a",dataname,cachename)
+ end
+ local data={
+ type=dataname,
+ root=cachename,
+ version=resolvers.cacheversion,
+ date=os.date("%Y-%m-%d"),
+ time=os.date("%H:%M:%S"),
+ content=content,
+ uuid=os.uuid(),
+ }
+ local ok=io.savedata(luaname,serialize(data,true))
+ if ok then
+ if trace_locating then
+ report_resolvers("category %a, cachename %a saved in %a",dataname,cachename,luaname)
end
-
+ if utilities.lua.compile(luaname,lucname) then
+ if trace_locating then
+ report_resolvers("%a compiled to %a",dataname,lucname)
+ end
+ return true
+ else
+ if trace_locating then
+ report_resolvers("compiling failed for %a, deleting file %a",dataname,lucname)
+ end
+ os.remove(lucname)
+ end
+ elseif trace_locating then
+ report_resolvers("unable to save %a in %a (access error)",dataname,luaname)
+ end
end
@@ -14237,1074 +12513,2555 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['data-inp'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local allocate = utilities.storage.allocate
-local resolvers = resolvers
-
-local methodhandler = resolvers.methodhandler
-local registermethod = resolvers.registermethod
-
-local finders = allocate { helpers = { }, notfound = function() end }
-local openers = allocate { helpers = { }, notfound = function() end }
-local loaders = allocate { helpers = { }, notfound = function() return false, nil, 0 end }
-
-registermethod("finders", finders, "uri")
-registermethod("openers", openers, "uri")
-registermethod("loaders", loaders, "uri")
-
-resolvers.finders = finders
-resolvers.openers = openers
-resolvers.loaders = loaders
+package.loaded["data-met"] = package.loaded["data-met"] or true
+-- original size: 4915, stripped down to: 3942
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['data-out'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
+if not modules then modules={} end modules ['data-met']={
+ version=1.100,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
}
-
-local allocate = utilities.storage.allocate
-local resolvers = resolvers
-
-local registermethod = resolvers.registermethod
-
-local savers = allocate { helpers = { } }
-
-resolvers.savers = savers
-
-registermethod("savers", savers, "uri")
+local find,format=string.find,string.format
+local sequenced=table.sequenced
+local addurlscheme,urlhashed=url.addscheme,url.hashed
+local trace_locating=false
+trackers.register("resolvers.locating",function(v) trace_methods=v end)
+trackers.register("resolvers.methods",function(v) trace_methods=v end)
+local report_methods=logs.reporter("resolvers","methods")
+local allocate=utilities.storage.allocate
+local resolvers=resolvers
+local registered={}
+local function splitmethod(filename)
+ if not filename then
+ return { scheme="unknown",original=filename }
+ end
+ if type(filename)=="table" then
+ return filename
+ end
+ filename=file.collapsepath(filename)
+ if not find(filename,"://") then
+ return { scheme="file",path=filename,original=filename,filename=filename }
+ end
+ local specification=url.hashed(filename)
+ if not specification.scheme or specification.scheme=="" then
+ return { scheme="file",path=filename,original=filename,filename=filename }
+ else
+ return specification
+ end
+end
+resolvers.splitmethod=splitmethod
+local function methodhandler(what,first,...)
+ local method=registered[what]
+ if method then
+ local how,namespace=method.how,method.namespace
+ if how=="uri" or how=="url" then
+ local specification=splitmethod(first)
+ local scheme=specification.scheme
+ local resolver=namespace and namespace[scheme]
+ if resolver then
+ if trace_methods then
+ report_methods("resolving, method %a, how %a, handler %a, argument %a",what,how,scheme,first)
+ end
+ return resolver(specification,...)
+ else
+ resolver=namespace.default or namespace.file
+ if resolver then
+ if trace_methods then
+ report_methods("resolving, method %a, how %a, handler %a, argument %a",what,how,"default",first)
+ end
+ return resolver(specification,...)
+ elseif trace_methods then
+ report_methods("resolving, method %a, how %a, handler %a, argument %a",what,how,"unset")
+ end
+ end
+ elseif how=="tag" then
+ local resolver=namespace and namespace[first]
+ if resolver then
+ if trace_methods then
+ report_methods("resolving, method %a, how %a, tag %a",what,how,first)
+ end
+ return resolver(...)
+ else
+ resolver=namespace.default or namespace.file
+ if resolver then
+ if trace_methods then
+ report_methods("resolving, method %a, how %a, tag %a",what,how,"default")
+ end
+ return resolver(...)
+ elseif trace_methods then
+ report_methods("resolving, method %a, how %a, tag %a",what,how,"unset")
+ end
+ end
+ end
+ else
+ report_methods("resolving, invalid method %a")
+ end
+end
+resolvers.methodhandler=methodhandler
+function resolvers.registermethod(name,namespace,how)
+ registered[name]={ how=how or "tag",namespace=namespace }
+ namespace["byscheme"]=function(scheme,filename,...)
+ if scheme=="file" then
+ return methodhandler(name,filename,...)
+ else
+ return methodhandler(name,addurlscheme(filename,scheme),...)
+ end
+ end
+end
+local concatinators=allocate { notfound=file.join }
+local locators=allocate { notfound=function() end }
+local hashers=allocate { notfound=function() end }
+local generators=allocate { notfound=function() end }
+resolvers.concatinators=concatinators
+resolvers.locators=locators
+resolvers.hashers=hashers
+resolvers.generators=generators
+local registermethod=resolvers.registermethod
+registermethod("concatinators",concatinators,"tag")
+registermethod("locators",locators,"uri")
+registermethod("hashers",hashers,"uri")
+registermethod("generators",generators,"uri")
end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['data-fil'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
-
-local report_files = logs.reporter("resolvers","files")
-
-local resolvers = resolvers
+package.loaded["data-res"] = package.loaded["data-res"] or true
-local finders, openers, loaders, savers = resolvers.finders, resolvers.openers, resolvers.loaders, resolvers.savers
-local locators, hashers, generators, concatinators = resolvers.locators, resolvers.hashers, resolvers.generators, resolvers.concatinators
+-- original size: 60821, stripped down to: 42503
-local checkgarbage = utilities.garbagecollector and utilities.garbagecollector.check
-
-function locators.file(specification)
- local name = specification.filename
- local realname = resolvers.resolve(name) -- no shortcut
- if realname and realname ~= '' and lfs.isdir(realname) then
+if not modules then modules={} end modules ['data-res']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files",
+}
+local gsub,find,lower,upper,match,gmatch=string.gsub,string.find,string.lower,string.upper,string.match,string.gmatch
+local concat,insert,sortedkeys=table.concat,table.insert,table.sortedkeys
+local next,type,rawget=next,type,rawget
+local os=os
+local P,S,R,C,Cc,Cs,Ct,Carg=lpeg.P,lpeg.S,lpeg.R,lpeg.C,lpeg.Cc,lpeg.Cs,lpeg.Ct,lpeg.Carg
+local lpegmatch,lpegpatterns=lpeg.match,lpeg.patterns
+local formatters=string.formatters
+local filedirname=file.dirname
+local filebasename=file.basename
+local suffixonly=file.suffixonly
+local filejoin=file.join
+local collapsepath=file.collapsepath
+local joinpath=file.joinpath
+local allocate=utilities.storage.allocate
+local settings_to_array=utilities.parsers.settings_to_array
+local setmetatableindex=table.setmetatableindex
+local luasuffixes=utilities.lua.suffixes
+local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end)
+local trace_detail=false trackers.register("resolvers.details",function(v) trace_detail=v end)
+local trace_expansions=false trackers.register("resolvers.expansions",function(v) trace_expansions=v end)
+local report_resolving=logs.reporter("resolvers","resolving")
+local resolvers=resolvers
+local expandedpathfromlist=resolvers.expandedpathfromlist
+local checkedvariable=resolvers.checkedvariable
+local splitconfigurationpath=resolvers.splitconfigurationpath
+local methodhandler=resolvers.methodhandler
+local initializesetter=utilities.setters.initialize
+local ostype,osname,osenv,ossetenv,osgetenv=os.type,os.name,os.env,os.setenv,os.getenv
+resolvers.cacheversion='1.0.1'
+resolvers.configbanner=''
+resolvers.homedir=environment.homedir
+resolvers.criticalvars=allocate { "SELFAUTOLOC","SELFAUTODIR","SELFAUTOPARENT","TEXMFCNF","TEXMF","TEXOS" }
+resolvers.luacnfname="texmfcnf.lua"
+resolvers.luacnfstate="unknown"
+if environment.default_texmfcnf then
+ resolvers.luacnfspec=environment.default_texmfcnf
+else
+ resolvers.luacnfspec="{selfautoloc:,selfautodir:,selfautoparent:}{,/texmf{-local,}/web2c}"
+end
+resolvers.luacnfspec='home:texmf/web2c;'..resolvers.luacnfspec
+local unset_variable="unset"
+local formats=resolvers.formats
+local suffixes=resolvers.suffixes
+local dangerous=resolvers.dangerous
+local suffixmap=resolvers.suffixmap
+resolvers.defaultsuffixes={ "tex" }
+resolvers.instance=resolvers.instance or nil
+local instance=resolvers.instance or nil
+function resolvers.setenv(key,value,raw)
+ if instance then
+ instance.environment[key]=value
+ ossetenv(key,raw and value or resolvers.resolve(value))
+ end
+end
+local function getenv(key)
+ local value=rawget(instance.environment,key)
+ if value and value~="" then
+ return value
+ else
+ local e=osgetenv(key)
+ return e~=nil and e~="" and checkedvariable(e) or ""
+ end
+end
+resolvers.getenv=getenv
+resolvers.env=getenv
+local function resolve(k)
+ return instance.expansions[k]
+end
+local dollarstripper=lpeg.stripper("$")
+local inhibitstripper=P("!")^0*Cs(P(1)^0)
+local backslashswapper=lpeg.replacer("\\","/")
+local somevariable=P("$")/""
+local somekey=C(R("az","AZ","09","__","--")^1)
+local somethingelse=P(";")*((1-S("!{}/\\"))^1*P(";")/"")+P(";")*(P(";")/"")+P(1)
+local variableexpander=Cs((somevariable*(somekey/resolve)+somethingelse)^1 )
+local cleaner=P("\\")/"/"+P(";")*S("!{}/\\")^0*P(";")^1/";"
+local variablecleaner=Cs((cleaner+P(1))^0)
+local somevariable=R("az","AZ","09","__","--")^1/resolve
+local variable=(P("$")/"")*(somevariable+(P("{")/"")*somevariable*(P("}")/""))
+local variableresolver=Cs((variable+P(1))^0)
+local function expandedvariable(var)
+ return lpegmatch(variableexpander,var) or var
+end
+function resolvers.newinstance()
+ if trace_locating then
+ report_resolving("creating instance")
+ end
+ local environment,variables,expansions,order=allocate(),allocate(),allocate(),allocate()
+ local newinstance={
+ environment=environment,
+ variables=variables,
+ expansions=expansions,
+ order=order,
+ files=allocate(),
+ setups=allocate(),
+ found=allocate(),
+ foundintrees=allocate(),
+ hashes=allocate(),
+ hashed=allocate(),
+ specification=allocate(),
+ lists=allocate(),
+ data=allocate(),
+ fakepaths=allocate(),
+ remember=true,
+ diskcache=true,
+ renewcache=false,
+ renewtree=false,
+ loaderror=false,
+ savelists=true,
+ pattern=nil,
+ force_suffixes=true,
+ }
+ setmetatableindex(variables,function(t,k)
+ local v
+ for i=1,#order do
+ v=order[i][k]
+ if v~=nil then
+ t[k]=v
+ return v
+ end
+ end
+ if v==nil then
+ v=""
+ end
+ t[k]=v
+ return v
+ end)
+ setmetatableindex(environment,function(t,k)
+ local v=osgetenv(k)
+ if v==nil then
+ v=variables[k]
+ end
+ if v~=nil then
+ v=checkedvariable(v) or ""
+ end
+ v=resolvers.repath(v)
+ t[k]=v
+ return v
+ end)
+ setmetatableindex(expansions,function(t,k)
+ local v=environment[k]
+ if type(v)=="string" then
+ v=lpegmatch(variableresolver,v)
+ v=lpegmatch(variablecleaner,v)
+ end
+ t[k]=v
+ return v
+ end)
+ return newinstance
+end
+function resolvers.setinstance(someinstance)
+ instance=someinstance
+ resolvers.instance=someinstance
+ return someinstance
+end
+function resolvers.reset()
+ return resolvers.setinstance(resolvers.newinstance())
+end
+local function reset_hashes()
+ instance.lists={}
+ instance.found={}
+end
+local slash=P("/")
+local pathexpressionpattern=Cs (
+ Cc("^")*(
+ Cc("%")*S(".-")+slash^2*P(-1)/"/.*"
++slash^2/"/[^/]*/*"+(1-slash)*P(-1)*Cc("/")+P(1)
+ )^1*Cc("$")
+)
+local cache={}
+local function makepathexpression(str)
+ if str=="." then
+ return "^%./$"
+ else
+ local c=cache[str]
+ if not c then
+ c=lpegmatch(pathexpressionpattern,str)
+ cache[str]=c
+ end
+ return c
+ end
+end
+local function reportcriticalvariables(cnfspec)
+ if trace_locating then
+ for i=1,#resolvers.criticalvars do
+ local k=resolvers.criticalvars[i]
+ local v=resolvers.getenv(k) or "unknown"
+ report_resolving("variable %a set to %a",k,v)
+ end
+ report_resolving()
+ if cnfspec then
+ report_resolving("using configuration specification %a",type(cnfspec)=="table" and concat(cnfspec,",") or cnfspec)
+ end
+ report_resolving()
+ end
+ reportcriticalvariables=function() end
+end
+local function identify_configuration_files()
+ local specification=instance.specification
+ if #specification==0 then
+ local cnfspec=getenv("TEXMFCNF")
+ if cnfspec=="" then
+ cnfspec=resolvers.luacnfspec
+ resolvers.luacnfstate="default"
+ else
+ resolvers.luacnfstate="environment"
+ end
+ reportcriticalvariables(cnfspec)
+ local cnfpaths=expandedpathfromlist(resolvers.splitpath(cnfspec))
+ local luacnfname=resolvers.luacnfname
+ for i=1,#cnfpaths do
+ local filename=collapsepath(filejoin(cnfpaths[i],luacnfname))
+ local realname=resolvers.resolve(filename)
+ if lfs.isfile(realname) then
+ specification[#specification+1]=filename
+ if trace_locating then
+ report_resolving("found configuration file %a",realname)
+ end
+ elseif trace_locating then
+ report_resolving("unknown configuration file %a",realname)
+ end
+ end
+ if trace_locating then
+ report_resolving()
+ end
+ elseif trace_locating then
+ report_resolving("configuration files already identified")
+ end
+end
+local function load_configuration_files()
+ local specification=instance.specification
+ if #specification>0 then
+ local luacnfname=resolvers.luacnfname
+ for i=1,#specification do
+ local filename=specification[i]
+ local pathname=filedirname(filename)
+ local filename=filejoin(pathname,luacnfname)
+ local realname=resolvers.resolve(filename)
+ local blob=loadfile(realname)
+ if blob then
+ local setups=instance.setups
+ local data=blob()
+ local parent=data and data.parent
+ if parent then
+ local filename=filejoin(pathname,parent)
+ local realname=resolvers.resolve(filename)
+ local blob=loadfile(realname)
+ if blob then
+ local parentdata=blob()
+ if parentdata then
+ report_resolving("loading configuration file %a",filename)
+ data=table.merged(parentdata,data)
+ end
+ end
+ end
+ data=data and data.content
+ if data then
+ if trace_locating then
+ report_resolving("loading configuration file %a",filename)
+ report_resolving()
+ end
+ local variables=data.variables or {}
+ local warning=false
+ for k,v in next,data do
+ local variant=type(v)
+ if variant=="table" then
+ initializesetter(filename,k,v)
+ elseif variables[k]==nil then
+ if trace_locating and not warning then
+ report_resolving("variables like %a in configuration file %a should move to the 'variables' subtable",
+ k,resolvers.resolve(filename))
+ warning=true
+ end
+ variables[k]=v
+ end
+ end
+ setups[pathname]=variables
+ if resolvers.luacnfstate=="default" then
+ local cnfspec=variables["TEXMFCNF"]
+ if cnfspec then
+ if trace_locating then
+ report_resolving("reloading configuration due to TEXMF redefinition")
+ end
+ resolvers.setenv("TEXMFCNF",cnfspec)
+ instance.specification={}
+ identify_configuration_files()
+ load_configuration_files()
+ resolvers.luacnfstate="configuration"
+ break
+ end
+ end
+ else
+ if trace_locating then
+ report_resolving("skipping configuration file %a (no content)",filename)
+ end
+ setups[pathname]={}
+ instance.loaderror=true
+ end
+ elseif trace_locating then
+ report_resolving("skipping configuration file %a (no valid format)",filename)
+ end
+ instance.order[#instance.order+1]=instance.setups[pathname]
+ if instance.loaderror then
+ break
+ end
+ end
+ elseif trace_locating then
+ report_resolving("warning: no lua configuration files found")
+ end
+end
+local function load_file_databases()
+ instance.loaderror,instance.files=false,allocate()
+ if not instance.renewcache then
+ local hashes=instance.hashes
+ for k=1,#hashes do
+ local hash=hashes[k]
+ resolvers.hashers.byscheme(hash.type,hash.name)
+ if instance.loaderror then break end
+ end
+ end
+end
+local function locate_file_databases()
+ local texmfpaths=resolvers.expandedpathlist("TEXMF")
+ if #texmfpaths>0 then
+ for i=1,#texmfpaths do
+ local path=collapsepath(texmfpaths[i])
+ path=gsub(path,"/+$","")
+ local stripped=lpegmatch(inhibitstripper,path)
+ if stripped~="" then
+ local runtime=stripped==path
+ path=resolvers.cleanpath(path)
+ local spec=resolvers.splitmethod(stripped)
+ if runtime and (spec.noscheme or spec.scheme=="file") then
+ stripped="tree:///"..stripped
+ elseif spec.scheme=="cache" or spec.scheme=="file" then
+ stripped=spec.path
+ end
if trace_locating then
- report_files("file locator '%s' found as '%s'",name,realname)
+ if runtime then
+ report_resolving("locating list of %a (runtime) (%s)",path,stripped)
+ else
+ report_resolving("locating list of %a (cached)",path)
+ end
end
- resolvers.appendhash('file',name,true) -- cache
+ methodhandler('locators',stripped)
+ end
+ end
+ if trace_locating then
+ report_resolving()
+ end
+ elseif trace_locating then
+ report_resolving("no texmf paths are defined (using TEXMF)")
+ end
+end
+local function generate_file_databases()
+ local hashes=instance.hashes
+ for k=1,#hashes do
+ local hash=hashes[k]
+ methodhandler('generators',hash.name)
+ end
+ if trace_locating then
+ report_resolving()
+ end
+end
+local function save_file_databases()
+ for i=1,#instance.hashes do
+ local hash=instance.hashes[i]
+ local cachename=hash.name
+ if hash.cache then
+ local content=instance.files[cachename]
+ caches.collapsecontent(content)
+ if trace_locating then
+ report_resolving("saving tree %a",cachename)
+ end
+ caches.savecontent(cachename,"files",content)
elseif trace_locating then
- report_files("file locator '%s' not found",name)
+ report_resolving("not saving runtime tree %a",cachename)
end
+ end
end
-
-function hashers.file(specification)
- local name = specification.filename
- local content = caches.loadcontent(name,'files')
- resolvers.registerfilehash(name,content,content==nil)
+function resolvers.renew(hashname)
+ if hashname and hashname~="" then
+ local expanded=resolvers.expansion(hashname) or ""
+ if expanded~="" then
+ if trace_locating then
+ report_resolving("identifying tree %a from %a",expanded,hashname)
+ end
+ hashname=expanded
+ else
+ if trace_locating then
+ report_resolving("identifying tree %a",hashname)
+ end
+ end
+ local realpath=resolvers.resolve(hashname)
+ if lfs.isdir(realpath) then
+ if trace_locating then
+ report_resolving("using path %a",realpath)
+ end
+ methodhandler('generators',hashname)
+ local content=instance.files[hashname]
+ caches.collapsecontent(content)
+ if trace_locating then
+ report_resolving("saving tree %a",hashname)
+ end
+ caches.savecontent(hashname,"files",content)
+ else
+ report_resolving("invalid path %a",realpath)
+ end
+ end
end
-
-function generators.file(specification)
- local path = specification.filename
- local content = resolvers.scanfiles(path,false,true) -- scan once
- resolvers.registerfilehash(path,content,true)
+local function load_databases()
+ locate_file_databases()
+ if instance.diskcache and not instance.renewcache then
+ load_file_databases()
+ if instance.loaderror then
+ generate_file_databases()
+ save_file_databases()
+ end
+ else
+ generate_file_databases()
+ if instance.renewcache then
+ save_file_databases()
+ end
+ end
end
-
-concatinators.file = file.join
-
-function finders.file(specification,filetype)
- local filename = specification.filename
- local foundname = resolvers.findfile(filename,filetype)
- if foundname and foundname ~= "" then
- if trace_locating then
- report_files("file finder: '%s' found",filename)
- end
- return foundname
+function resolvers.appendhash(type,name,cache)
+ if not instance.hashed[name] then
+ if trace_locating then
+ report_resolving("hash %a appended",name)
+ end
+ insert(instance.hashes,{ type=type,name=name,cache=cache } )
+ instance.hashed[name]=cache
+ end
+end
+function resolvers.prependhash(type,name,cache)
+ if not instance.hashed[name] then
+ if trace_locating then
+ report_resolving("hash %a prepended",name)
+ end
+ insert(instance.hashes,1,{ type=type,name=name,cache=cache } )
+ instance.hashed[name]=cache
+ end
+end
+function resolvers.extendtexmfvariable(specification)
+ local t=resolvers.splitpath(getenv("TEXMF"))
+ insert(t,1,specification)
+ local newspec=concat(t,",")
+ if instance.environment["TEXMF"] then
+ instance.environment["TEXMF"]=newspec
+ elseif instance.variables["TEXMF"] then
+ instance.variables["TEXMF"]=newspec
+ else
+ end
+ reset_hashes()
+end
+function resolvers.splitexpansions()
+ local ie=instance.expansions
+ for k,v in next,ie do
+ local t,tn,h,p={},0,{},splitconfigurationpath(v)
+ for kk=1,#p do
+ local vv=p[kk]
+ if vv~="" and not h[vv] then
+ tn=tn+1
+ t[tn]=vv
+ h[vv]=true
+ end
+ end
+ if #t>1 then
+ ie[k]=t
else
- if trace_locating then
- report_files("file finder: %s' not found",filename)
- end
- return finders.notfound()
+ ie[k]=t[1]
end
+ end
end
-
--- The default textopener will be overloaded later on.
-
-function openers.helpers.textopener(tag,filename,f)
- return {
- reader = function() return f:read () end,
- close = function() logs.show_close(filename) return f:close() end,
- }
+function resolvers.datastate()
+ return caches.contentstate()
end
-
-function openers.file(specification,filetype)
- local filename = specification.filename
- if filename and filename ~= "" then
- local f = io.open(filename,"r")
- if f then
- if trace_locating then
- report_files("file opener, '%s' opened",filename)
- end
- return openers.helpers.textopener("file",filename,f)
+function resolvers.variable(name)
+ local name=name and lpegmatch(dollarstripper,name)
+ local result=name and instance.variables[name]
+ return result~=nil and result or ""
+end
+function resolvers.expansion(name)
+ local name=name and lpegmatch(dollarstripper,name)
+ local result=name and instance.expansions[name]
+ return result~=nil and result or ""
+end
+function resolvers.unexpandedpathlist(str)
+ local pth=resolvers.variable(str)
+ local lst=resolvers.splitpath(pth)
+ return expandedpathfromlist(lst)
+end
+function resolvers.unexpandedpath(str)
+ return joinpath(resolvers.unexpandedpathlist(str))
+end
+local done={}
+function resolvers.resetextrapath()
+ local ep=instance.extra_paths
+ if not ep then
+ ep,done={},{}
+ instance.extra_paths=ep
+ elseif #ep>0 then
+ instance.lists,done={},{}
+ end
+end
+function resolvers.registerextrapath(paths,subpaths)
+ paths=settings_to_array(paths)
+ subpaths=settings_to_array(subpaths)
+ local ep=instance.extra_paths or {}
+ local oldn=#ep
+ local newn=oldn
+ local nofpaths=#paths
+ local nofsubpaths=#subpaths
+ if nofpaths>0 then
+ if nofsubpaths>0 then
+ for i=1,nofpaths do
+ local p=paths[i]
+ for j=1,nofsubpaths do
+ local s=subpaths[j]
+ local ps=p.."/"..s
+ if not done[ps] then
+ newn=newn+1
+ ep[newn]=resolvers.cleanpath(ps)
+ done[ps]=true
+ end
+ end
+ end
+ else
+ for i=1,nofpaths do
+ local p=paths[i]
+ if not done[p] then
+ newn=newn+1
+ ep[newn]=resolvers.cleanpath(p)
+ done[p]=true
+ end
+ end
+ end
+ elseif nofsubpaths>0 then
+ for i=1,oldn do
+ for j=1,nofsubpaths do
+ local s=subpaths[j]
+ local ps=ep[i].."/"..s
+ if not done[ps] then
+ newn=newn+1
+ ep[newn]=resolvers.cleanpath(ps)
+ done[ps]=true
+ end
+ end
+ end
+ end
+ if newn>0 then
+ instance.extra_paths=ep
+ end
+ if newn>oldn then
+ instance.lists={}
+ end
+end
+local function made_list(instance,list)
+ local ep=instance.extra_paths
+ if not ep or #ep==0 then
+ return list
+ else
+ local done,new,newn={},{},0
+ for k=1,#list do
+ local v=list[k]
+ if not done[v] then
+ if find(v,"^[%.%/]$") then
+ done[v]=true
+ newn=newn+1
+ new[newn]=v
+ else
+ break
end
+ end
end
- if trace_locating then
- report_files("file opener, '%s' not found",filename)
+ for k=1,#ep do
+ local v=ep[k]
+ if not done[v] then
+ done[v]=true
+ newn=newn+1
+ new[newn]=v
+ end
+ end
+ for k=1,#list do
+ local v=list[k]
+ if not done[v] then
+ done[v]=true
+ newn=newn+1
+ new[newn]=v
+ end
end
- return openers.notfound()
+ return new
+ end
end
-
-function loaders.file(specification,filetype)
- local filename = specification.filename
- if filename and filename ~= "" then
- local f = io.open(filename,"rb")
- if f then
- logs.show_load(filename)
- if trace_locating then
- report_files("file loader, '%s' loaded",filename)
- end
- local s = f:read("*a")
- if checkgarbage then
- checkgarbage(#s)
- end
- f:close()
- if s then
- return true, s, #s
- end
- end
+function resolvers.cleanpathlist(str)
+ local t=resolvers.expandedpathlist(str)
+ if t then
+ for i=1,#t do
+ t[i]=collapsepath(resolvers.cleanpath(t[i]))
end
- if trace_locating then
- report_files("file loader, '%s' not found",filename)
+ end
+ return t
+end
+function resolvers.expandpath(str)
+ return joinpath(resolvers.expandedpathlist(str))
+end
+function resolvers.expandedpathlist(str)
+ if not str then
+ return {}
+ elseif instance.savelists then
+ str=lpegmatch(dollarstripper,str)
+ local lists=instance.lists
+ local lst=lists[str]
+ if not lst then
+ local l=made_list(instance,resolvers.splitpath(resolvers.expansion(str)))
+ lst=expandedpathfromlist(l)
+ lists[str]=lst
end
- return loaders.notfound()
+ return lst
+ else
+ local lst=resolvers.splitpath(resolvers.expansion(str))
+ return made_list(instance,expandedpathfromlist(lst))
+ end
end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['data-con'] = {
- version = 1.100,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local format, lower, gsub = string.format, string.lower, string.gsub
-
-local trace_cache = false trackers.register("resolvers.cache", function(v) trace_cache = v end)
-local trace_containers = false trackers.register("resolvers.containers", function(v) trace_containers = v end)
-local trace_storage = false trackers.register("resolvers.storage", function(v) trace_storage = v end)
-
---[[ldx--
-Once we found ourselves defining similar cache constructs
-several times, containers were introduced. Containers are used
-to collect tables in memory and reuse them when possible based
-on (unique) hashes (to be provided by the calling function).
-
-Caching to disk is disabled by default. Version numbers are
-stored in the saved table which makes it possible to change the
-table structures without bothering about the disk cache.
-
-Examples of usage can be found in the font related code.
---ldx]]--
-
-containers = containers or { }
-local containers = containers
-containers.usecache = true
-
-local report_containers = logs.reporter("resolvers","containers")
-
-local function report(container,tag,name)
- if trace_cache or trace_containers then
- report_containers("container: %s, tag: %s, name: %s",container.subcategory,tag,name or 'invalid')
+function resolvers.expandedpathlistfromvariable(str)
+ str=lpegmatch(dollarstripper,str)
+ local tmp=resolvers.variableofformatorsuffix(str)
+ return resolvers.expandedpathlist(tmp~="" and tmp or str)
+end
+function resolvers.expandpathfromvariable(str)
+ return joinpath(resolvers.expandedpathlistfromvariable(str))
+end
+function resolvers.expandbraces(str)
+ local ori=str
+ local pth=expandedpathfromlist(resolvers.splitpath(ori))
+ return joinpath(pth)
+end
+function resolvers.registerfilehash(name,content,someerror)
+ if content then
+ instance.files[name]=content
+ else
+ instance.files[name]={}
+ if somerror==true then
+ instance.loaderror=someerror
end
+ end
end
-
-local allocated = { }
-
-local mt = {
- __index = function(t,k)
- if k == "writable" then
- local writable = caches.getwritablepath(t.category,t.subcategory) or { "." }
- t.writable = writable
- return writable
- elseif k == "readables" then
- local readables = caches.getreadablepaths(t.category,t.subcategory) or { "." }
- t.readables = readables
- return readables
- end
- end,
- __storage__ = true
-}
-
-function containers.define(category, subcategory, version, enabled)
- if category and subcategory then
- local c = allocated[category]
- if not c then
- c = { }
- allocated[category] = c
- end
- local s = c[subcategory]
- if not s then
- s = {
- category = category,
- subcategory = subcategory,
- storage = { },
- enabled = enabled,
- version = version or math.pi, -- after all, this is TeX
- trace = false,
- -- writable = caches.getwritablepath and caches.getwritablepath (category,subcategory) or { "." },
- -- readables = caches.getreadablepaths and caches.getreadablepaths(category,subcategory) or { "." },
- }
- setmetatable(s,mt)
- c[subcategory] = s
+local function isreadable(name)
+ local readable=lfs.isfile(name)
+ if trace_detail then
+ if readable then
+ report_resolving("file %a is readable",name)
+ else
+ report_resolving("file %a is not readable",name)
+ end
+ end
+ return readable
+end
+local function collect_files(names)
+ local filelist,noffiles={},0
+ for k=1,#names do
+ local fname=names[k]
+ if trace_detail then
+ report_resolving("checking name %a",fname)
+ end
+ local bname=filebasename(fname)
+ local dname=filedirname(fname)
+ if dname=="" or find(dname,"^%.") then
+ dname=false
+ else
+ dname=gsub(dname,"%*",".*")
+ dname="/"..dname.."$"
+ end
+ local hashes=instance.hashes
+ for h=1,#hashes do
+ local hash=hashes[h]
+ local blobpath=hash.name
+ local files=blobpath and instance.files[blobpath]
+ if files then
+ if trace_detail then
+ report_resolving("deep checking %a, base %a, pattern %a",blobpath,bname,dname)
+ end
+ local blobfile=files[bname]
+ if not blobfile then
+ local rname="remap:"..bname
+ blobfile=files[rname]
+ if blobfile then
+ bname=files[rname]
+ blobfile=files[bname]
+ end
+ end
+ if blobfile then
+ local blobroot=files.__path__ or blobpath
+ if type(blobfile)=='string' then
+ if not dname or find(blobfile,dname) then
+ local variant=hash.type
+ local search=filejoin(blobroot,blobfile,bname)
+ local result=methodhandler('concatinators',hash.type,blobroot,blobfile,bname)
+ if trace_detail then
+ report_resolving("match: variant %a, search %a, result %a",variant,search,result)
+ end
+ noffiles=noffiles+1
+ filelist[noffiles]={ variant,search,result }
+ end
+ else
+ for kk=1,#blobfile do
+ local vv=blobfile[kk]
+ if not dname or find(vv,dname) then
+ local variant=hash.type
+ local search=filejoin(blobroot,vv,bname)
+ local result=methodhandler('concatinators',hash.type,blobroot,vv,bname)
+ if trace_detail then
+ report_resolving("match: variant %a, search %a, result %a",variant,search,result)
+ end
+ noffiles=noffiles+1
+ filelist[noffiles]={ variant,search,result }
+ end
+ end
+ end
end
- return s
+ elseif trace_locating then
+ report_resolving("no match in %a (%s)",blobpath,bname)
+ end
end
+ end
+ return noffiles>0 and filelist or nil
end
-
-function containers.is_usable(container, name)
- return container.enabled and caches and caches.is_writable(container.writable, name)
+local fit={}
+function resolvers.registerintrees(filename,format,filetype,usedmethod,foundname)
+ local foundintrees=instance.foundintrees
+ if usedmethod=="direct" and filename==foundname and fit[foundname] then
+ else
+ local t={
+ filename=filename,
+ format=format~="" and format or nil,
+ filetype=filetype~="" and filetype or nil,
+ usedmethod=usedmethod,
+ foundname=foundname,
+ }
+ fit[foundname]=t
+ foundintrees[#foundintrees+1]=t
+ end
end
-
-function containers.is_valid(container, name)
- if name and name ~= "" then
- local storage = container.storage[name]
- return storage and storage.cache_version == container.version
+local function can_be_dir(name)
+ local fakepaths=instance.fakepaths
+ if not fakepaths[name] then
+ if lfs.isdir(name) then
+ fakepaths[name]=1
else
- return false
+ fakepaths[name]=2
end
+ end
+ return fakepaths[name]==1
end
-
-function containers.read(container,name)
- local storage = container.storage
- local stored = storage[name]
- if not stored and container.enabled and caches and containers.usecache then
- stored = caches.loaddata(container.readables,name)
- if stored and stored.cache_version == container.version then
- report(container,"loaded",name)
- else
- stored = nil
+local preparetreepattern=Cs((P(".")/"%%."+P("-")/"%%-"+P(1))^0*Cc("$"))
+local collect_instance_files
+local function find_analyze(filename,askedformat,allresults)
+ local filetype,wantedfiles,ext='',{},suffixonly(filename)
+ wantedfiles[#wantedfiles+1]=filename
+ if askedformat=="" then
+ if ext=="" or not suffixmap[ext] then
+ local defaultsuffixes=resolvers.defaultsuffixes
+ for i=1,#defaultsuffixes do
+ local forcedname=filename..'.'..defaultsuffixes[i]
+ wantedfiles[#wantedfiles+1]=forcedname
+ filetype=resolvers.formatofsuffix(forcedname)
+ if trace_locating then
+ report_resolving("forcing filetype %a",filetype)
end
- storage[name] = stored
- elseif stored then
- report(container,"reusing",name)
+ end
+ else
+ filetype=resolvers.formatofsuffix(filename)
+ if trace_locating then
+ report_resolving("using suffix based filetype %a",filetype)
+ end
end
- return stored
-end
-
-function containers.write(container, name, data)
- if data then
- data.cache_version = container.version
- if container.enabled and caches then
- local unique, shared = data.unique, data.shared
- data.unique, data.shared = nil, nil
- caches.savedata(container.writable, name, data)
- report(container,"saved",name)
- data.unique, data.shared = unique, shared
+ else
+ if ext=="" or not suffixmap[ext] then
+ local format_suffixes=suffixes[askedformat]
+ if format_suffixes then
+ for i=1,#format_suffixes do
+ wantedfiles[#wantedfiles+1]=filename.."."..format_suffixes[i]
end
- report(container,"stored",name)
- container.storage[name] = data
+ end
end
- return data
+ filetype=askedformat
+ if trace_locating then
+ report_resolving("using given filetype %a",filetype)
+ end
+ end
+ return filetype,wantedfiles
end
-
-function containers.content(container,name)
- return container.storage[name]
+local function find_direct(filename,allresults)
+ if not dangerous[askedformat] and isreadable(filename) then
+ if trace_detail then
+ report_resolving("file %a found directly",filename)
+ end
+ return "direct",{ filename }
+ end
end
-
-function containers.cleanname(name)
- return (gsub(lower(name),"[^%w%d]+","-"))
+local function find_wildcard(filename,allresults)
+ if find(filename,'%*') then
+ if trace_locating then
+ report_resolving("checking wildcard %a",filename)
+ end
+ local method,result=resolvers.findwildcardfiles(filename)
+ if result then
+ return "wildcard",result
+ end
+ end
+end
+local function find_qualified(filename,allresults,askedformat,alsostripped)
+ if not file.is_qualified_path(filename) then
+ return
+ end
+ if trace_locating then
+ report_resolving("checking qualified name %a",filename)
+ end
+ if isreadable(filename) then
+ if trace_detail then
+ report_resolving("qualified file %a found",filename)
+ end
+ return "qualified",{ filename }
+ end
+ if trace_detail then
+ report_resolving("locating qualified file %a",filename)
+ end
+ local forcedname,suffix="",suffixonly(filename)
+ if suffix=="" then
+ local format_suffixes=askedformat=="" and resolvers.defaultsuffixes or suffixes[askedformat]
+ if format_suffixes then
+ for i=1,#format_suffixes do
+ local s=format_suffixes[i]
+ forcedname=filename.."."..s
+ if isreadable(forcedname) then
+ if trace_locating then
+ report_resolving("no suffix, forcing format filetype %a",s)
+ end
+ return "qualified",{ forcedname }
+ end
+ end
+ end
+ end
+ if alsostripped and suffix and suffix~="" then
+ local basename=filebasename(filename)
+ local pattern=lpegmatch(preparetreepattern,filename)
+ local savedformat=askedformat
+ local format=savedformat or ""
+ if format=="" then
+ askedformat=resolvers.formatofsuffix(suffix)
+ end
+ if not format then
+ askedformat="othertextfiles"
+ end
+ if basename~=filename then
+ local resolved=collect_instance_files(basename,askedformat,allresults)
+ if #resolved==0 then
+ local lowered=lower(basename)
+ if filename~=lowered then
+ resolved=collect_instance_files(lowered,askedformat,allresults)
+ end
+ end
+ resolvers.format=savedformat
+ if #resolved>0 then
+ local result={}
+ for r=1,#resolved do
+ local rr=resolved[r]
+ if find(rr,pattern) then
+ result[#result+1]=rr
+ end
+ end
+ if #result>0 then
+ return "qualified",result
+ end
+ end
+ end
+ end
end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['data-use'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local format, lower, gsub, find = string.format, string.lower, string.gsub, string.find
-
-local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
-
-local report_mounts = logs.reporter("resolvers","mounts")
-
-local resolvers = resolvers
-
--- we will make a better format, maybe something xml or just text or lua
-
-resolvers.automounted = resolvers.automounted or { }
-
-function resolvers.automount(usecache)
- local mountpaths = resolvers.cleanpathlist(resolvers.expansion('TEXMFMOUNT'))
- if (not mountpaths or #mountpaths == 0) and usecache then
- mountpaths = caches.getreadablepaths("mount")
- end
- if mountpaths and #mountpaths > 0 then
- statistics.starttiming(resolvers.instance)
- for k=1,#mountpaths do
- local root = mountpaths[k]
- local f = io.open(root.."/url.tmi")
- if f then
- for line in f:lines() do
- if line then
- if find(line,"^[%%#%-]") then -- or %W
- -- skip
- elseif find(line,"^zip://") then
- if trace_locating then
- report_mounts("mounting %s",line)
- end
- table.insert(resolvers.automounted,line)
- resolvers.usezipfile(line)
+local function check_subpath(fname)
+ if isreadable(fname) then
+ if trace_detail then
+ report_resolving("found %a by deep scanning",fname)
+ end
+ return fname
+ end
+end
+local function find_intree(filename,filetype,wantedfiles,allresults)
+ local typespec=resolvers.variableofformat(filetype)
+ local pathlist=resolvers.expandedpathlist(typespec)
+ local method="intree"
+ if pathlist and #pathlist>0 then
+ local filelist=collect_files(wantedfiles)
+ local dirlist={}
+ if filelist then
+ for i=1,#filelist do
+ dirlist[i]=filedirname(filelist[i][3]).."/"
+ end
+ end
+ if trace_detail then
+ report_resolving("checking filename %a",filename)
+ end
+ local resolve=resolvers.resolve
+ local result={}
+ for k=1,#pathlist do
+ local path=pathlist[k]
+ local pathname=lpegmatch(inhibitstripper,path)
+ local doscan=path==pathname
+ if not find (pathname,'//$') then
+ doscan=false
+ end
+ local done=false
+ if filelist then
+ local expression=makepathexpression(pathname)
+ if trace_detail then
+ report_resolving("using pattern %a for path %a",expression,pathname)
+ end
+ for k=1,#filelist do
+ local fl=filelist[k]
+ local f=fl[2]
+ local d=dirlist[k]
+ if find(d,expression) or find(resolve(d),expression) then
+ result[#result+1]=resolve(fl[3])
+ done=true
+ if allresults then
+ if trace_detail then
+ report_resolving("match to %a in hash for file %a and path %a, continue scanning",expression,f,d)
+ end
+ else
+ if trace_detail then
+ report_resolving("match to %a in hash for file %a and path %a, quit scanning",expression,f,d)
+ end
+ break
+ end
+ elseif trace_detail then
+ report_resolving("no match to %a in hash for file %a and path %a",expression,f,d)
+ end
+ end
+ end
+ if done then
+ method="database"
+ else
+ method="filesystem"
+ pathname=gsub(pathname,"/+$","")
+ pathname=resolve(pathname)
+ local scheme=url.hasscheme(pathname)
+ if not scheme or scheme=="file" then
+ local pname=gsub(pathname,"%.%*$",'')
+ if not find(pname,"%*") then
+ if can_be_dir(pname) then
+ for k=1,#wantedfiles do
+ local w=wantedfiles[k]
+ local fname=check_subpath(filejoin(pname,w))
+ if fname then
+ result[#result+1]=fname
+ done=true
+ if not allresults then
+ break
+ end
+ end
+ end
+ if not done and doscan then
+ local files=resolvers.simplescanfiles(pname,false,true)
+ for k=1,#wantedfiles do
+ local w=wantedfiles[k]
+ local subpath=files[w]
+ if not subpath or subpath=="" then
+ elseif type(subpath)=="string" then
+ local fname=check_subpath(filejoin(pname,subpath,w))
+ if fname then
+ result[#result+1]=fname
+ done=true
+ if not allresults then
+ break
+ end
+ end
+ else
+ for i=1,#subpath do
+ local sp=subpath[i]
+ if sp=="" then
+ else
+ local fname=check_subpath(filejoin(pname,sp,w))
+ if fname then
+ result[#result+1]=fname
+ done=true
+ if not allresults then
+ break
+ end
end
+ end
+ end
+ if done and not allresults then
+ break
end
+ end
end
- f:close()
+ end
end
+ else
+ end
end
- statistics.stoptiming(resolvers.instance)
+ end
+ if done and not allresults then
+ break
+ end
end
-end
-
--- status info
-
-statistics.register("used config file", function() return caches.configfiles() end)
-statistics.register("used cache path", function() return caches.usedpaths() end)
-
--- experiment (code will move)
-
-function statistics.savefmtstatus(texname,formatbanner,sourcefile) -- texname == formatname
- local enginebanner = status.list().banner
- if formatbanner and enginebanner and sourcefile then
- local luvname = file.replacesuffix(texname,"luv")
- local luvdata = {
- enginebanner = enginebanner,
- formatbanner = formatbanner,
- sourcehash = md5.hex(io.loaddata(resolvers.findfile(sourcefile)) or "unknown"),
- sourcefile = sourcefile,
- }
- io.savedata(luvname,table.serialize(luvdata,true))
+ if #result>0 then
+ return method,result
end
+ end
end
-
-function statistics.checkfmtstatus(texname)
- local enginebanner = status.list().banner
- if enginebanner and texname then
- local luvname = file.replacesuffix(texname,"luv")
- if lfs.isfile(luvname) then
- local luv = dofile(luvname)
- if luv and luv.sourcefile then
- local sourcehash = md5.hex(io.loaddata(resolvers.findfile(luv.sourcefile)) or "unknown")
- local luvbanner = luv.enginebanner or "?"
- if luvbanner ~= enginebanner then
- return format("engine mismatch (luv: %s <> bin: %s)",luvbanner,enginebanner)
- end
- local luvhash = luv.sourcehash or "?"
- if luvhash ~= sourcehash then
- return format("source mismatch (luv: %s <> bin: %s)",luvhash,sourcehash)
- end
- else
- return "invalid status file"
- end
- else
- return "missing status file"
+local function find_onpath(filename,filetype,wantedfiles,allresults)
+ if trace_detail then
+ report_resolving("checking filename %a, filetype %a, wanted files %a",filename,filetype,concat(wantedfiles," | "))
+ end
+ local result={}
+ for k=1,#wantedfiles do
+ local fname=wantedfiles[k]
+ if fname and isreadable(fname) then
+ filename=fname
+ result[#result+1]=filejoin('.',fname)
+ if not allresults then
+ break
+ end
+ end
+ end
+ if #result>0 then
+ return "onpath",result
+ end
+end
+local function find_otherwise(filename,filetype,wantedfiles,allresults)
+ local filelist=collect_files(wantedfiles)
+ local fl=filelist and filelist[1]
+ if fl then
+ return "otherwise",{ resolvers.resolve(fl[3]) }
+ end
+end
+collect_instance_files=function(filename,askedformat,allresults)
+ askedformat=askedformat or ""
+ filename=collapsepath(filename)
+ if allresults then
+ local filetype,wantedfiles=find_analyze(filename,askedformat)
+ local results={
+ { find_direct (filename,true) },
+ { find_wildcard (filename,true) },
+ { find_qualified(filename,true,askedformat) },
+ { find_intree (filename,filetype,wantedfiles,true) },
+ { find_onpath (filename,filetype,wantedfiles,true) },
+ { find_otherwise(filename,filetype,wantedfiles,true) },
+ }
+ local result,status,done={},{},{}
+ for k,r in next,results do
+ local method,list=r[1],r[2]
+ if method and list then
+ for i=1,#list do
+ local c=collapsepath(list[i])
+ if not done[c] then
+ result[#result+1]=c
+ done[c]=true
+ end
+ status[#status+1]=formatters["%-10s: %s"](method,c)
+ end
+ end
+ end
+ if trace_detail then
+ report_resolving("lookup status: %s",table.serialize(status,filename))
+ end
+ return result,status
+ else
+ local method,result,stamp,filetype,wantedfiles
+ if instance.remember then
+ stamp=formatters["%s--%s"](filename,askedformat)
+ result=stamp and instance.found[stamp]
+ if result then
+ if trace_locating then
+ report_resolving("remembered file %a",filename)
end
+ return result
+ end
end
- return true
-end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['data-zip'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- partly redone .. needs testing
-
-local format, find, match = string.format, string.find, string.match
-
-local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
-
-local report_zip = logs.reporter("resolvers","zip")
-
--- zip:///oeps.zip?name=bla/bla.tex
--- zip:///oeps.zip?tree=tex/texmf-local
--- zip:///texmf.zip?tree=/tex/texmf
--- zip:///texmf.zip?tree=/tex/texmf-local
--- zip:///texmf-mine.zip?tree=/tex/texmf-projects
-
-local resolvers = resolvers
-
-zip = zip or { }
-local zip = zip
-
-zip.archives = zip.archives or { }
-local archives = zip.archives
-
-zip.registeredfiles = zip.registeredfiles or { }
-local registeredfiles = zip.registeredfiles
-
-local limited = false
-
-directives.register("system.inputmode", function(v)
- if not limited then
- local i_limiter = io.i_limiter(v)
- if i_limiter then
- zip.open = i_limiter.protect(zip.open)
- limited = true
+ method,result=find_direct(filename)
+ if not result then
+ method,result=find_wildcard(filename)
+ if not result then
+ method,result=find_qualified(filename,false,askedformat)
+ if not result then
+ filetype,wantedfiles=find_analyze(filename,askedformat)
+ method,result=find_intree(filename,filetype,wantedfiles)
+ if not result then
+ method,result=find_onpath(filename,filetype,wantedfiles)
+ if not result then
+ method,result=find_otherwise(filename,filetype,wantedfiles)
+ end
+ end
end
+ end
end
-end)
-
-local function validzip(str) -- todo: use url splitter
- if not find(str,"^zip://") then
- return "zip:///" .. str
+ if result and #result>0 then
+ local foundname=collapsepath(result[1])
+ resolvers.registerintrees(filename,askedformat,filetype,method,foundname)
+ result={ foundname }
else
- return str
+ result={}
end
-end
-
-function zip.openarchive(name)
- if not name or name == "" then
- return nil
- else
- local arch = archives[name]
- if not arch then
- local full = resolvers.findfile(name) or ""
- arch = (full ~= "" and zip.open(full)) or false
- archives[name] = arch
- end
- return arch
+ if stamp then
+ if trace_locating then
+ report_resolving("remembering file %a",filename)
+ end
+ instance.found[stamp]=result
end
+ return result
+ end
end
-
-function zip.closearchive(name)
- if not name or (name == "" and archives[name]) then
- zip.close(archives[name])
- archives[name] = nil
+local function findfiles(filename,filetype,allresults)
+ local result,status=collect_instance_files(filename,filetype or "",allresults)
+ if not result or #result==0 then
+ local lowered=lower(filename)
+ if filename~=lowered then
+ result,status=collect_instance_files(lowered,filetype or "",allresults)
end
+ end
+ return result or {},status
+end
+function resolvers.findfiles(filename,filetype)
+ return findfiles(filename,filetype,true)
+end
+function resolvers.findfile(filename,filetype)
+ return findfiles(filename,filetype,false)[1] or ""
+end
+function resolvers.findpath(filename,filetype)
+ return filedirname(findfiles(filename,filetype,false)[1] or "")
end
-
-function resolvers.locators.zip(specification)
- local archive = specification.filename
- local zipfile = archive and archive ~= "" and zip.openarchive(archive) -- tricky, could be in to be initialized tree
- if trace_locating then
- if zipfile then
- report_zip("locator, archive '%s' found",archive)
- else
- report_zip("locator, archive '%s' not found",archive)
+local function findgivenfiles(filename,allresults)
+ local bname,result=filebasename(filename),{}
+ local hashes=instance.hashes
+ local noffound=0
+ for k=1,#hashes do
+ local hash=hashes[k]
+ local files=instance.files[hash.name] or {}
+ local blist=files[bname]
+ if not blist then
+ local rname="remap:"..bname
+ blist=files[rname]
+ if blist then
+ bname=files[rname]
+ blist=files[bname]
+ end
+ end
+ if blist then
+ if type(blist)=='string' then
+ local found=methodhandler('concatinators',hash.type,hash.name,blist,bname) or ""
+ if found~="" then
+ noffound=noffound+1
+ result[noffound]=resolvers.resolve(found)
+ if not allresults then
+ break
+ end
+ end
+ else
+ for kk=1,#blist do
+ local vv=blist[kk]
+ local found=methodhandler('concatinators',hash.type,hash.name,vv,bname) or ""
+ if found~="" then
+ noffound=noffound+1
+ result[noffound]=resolvers.resolve(found)
+ if not allresults then break end
+ end
end
+ end
end
+ end
+ return result
end
-
-function resolvers.hashers.zip(specification)
- local archive = specification.filename
- if trace_locating then
- report_zip("loading file '%s'",archive)
- end
- resolvers.usezipfile(specification.original)
+function resolvers.findgivenfiles(filename)
+ return findgivenfiles(filename,true)
end
-
-function resolvers.concatinators.zip(zipfile,path,name) -- ok ?
- if not path or path == "" then
- return format('%s?name=%s',zipfile,name)
- else
- return format('%s?name=%s/%s',zipfile,path,name)
- end
+function resolvers.findgivenfile(filename)
+ return findgivenfiles(filename,false)[1] or ""
end
-
-function resolvers.finders.zip(specification)
- local original = specification.original
- local archive = specification.filename
- if archive then
- local query = url.query(specification.query)
- local queryname = query.name
- if queryname then
- local zfile = zip.openarchive(archive)
- if zfile then
- if trace_locating then
- report_zip("finder, archive '%s' found",archive)
- end
- local dfile = zfile:open(queryname)
- if dfile then
- dfile = zfile:close()
- if trace_locating then
- report_zip("finder, file '%s' found",queryname)
- end
- return specification.original
- elseif trace_locating then
- report_zip("finder, file '%s' not found",queryname)
- end
- elseif trace_locating then
- report_zip("finder, unknown archive '%s'",archive)
- end
+local function doit(path,blist,bname,tag,variant,result,allresults)
+ local done=false
+ if blist and variant then
+ local resolve=resolvers.resolve
+ if type(blist)=='string' then
+ if find(lower(blist),path) then
+ local full=methodhandler('concatinators',variant,tag,blist,bname) or ""
+ result[#result+1]=resolve(full)
+ done=true
+ end
+ else
+ for kk=1,#blist do
+ local vv=blist[kk]
+ if find(lower(vv),path) then
+ local full=methodhandler('concatinators',variant,tag,vv,bname) or ""
+ result[#result+1]=resolve(full)
+ done=true
+ if not allresults then break end
end
+ end
end
- if trace_locating then
- report_zip("finder, '%s' not found",original)
- end
- return resolvers.finders.notfound()
+ end
+ return done
end
-
-function resolvers.openers.zip(specification)
- local original = specification.original
- local archive = specification.filename
- if archive then
- local query = url.query(specification.query)
- local queryname = query.name
- if queryname then
- local zfile = zip.openarchive(archive)
- if zfile then
- if trace_locating then
- report_zip("opener, archive '%s' opened",archive)
- end
- local dfile = zfile:open(queryname)
- if dfile then
- if trace_locating then
- report_zip("opener, file '%s' found",queryname)
- end
- return resolvers.openers.helpers.textopener('zip',original,dfile)
- elseif trace_locating then
- report_zip("opener, file '%s' not found",queryname)
- end
- elseif trace_locating then
- report_zip("opener, unknown archive '%s'",archive)
- end
+local makewildcard=Cs(
+ (P("^")^0*P("/")*P(-1)+P(-1))/".*"+(P("^")^0*P("/")/"")^0*(P("*")/".*"+P("-")/"%%-"+P(".")/"%%."+P("?")/"."+P("\\")/"/"+P(1))^0
+)
+function resolvers.wildcardpattern(pattern)
+ return lpegmatch(makewildcard,pattern) or pattern
+end
+local function findwildcardfiles(filename,allresults,result)
+ result=result or {}
+ local base=filebasename(filename)
+ local dirn=filedirname(filename)
+ local path=lower(lpegmatch(makewildcard,dirn) or dirn)
+ local name=lower(lpegmatch(makewildcard,base) or base)
+ local files,done=instance.files,false
+ if find(name,"%*") then
+ local hashes=instance.hashes
+ for k=1,#hashes do
+ local hash=hashes[k]
+ local hashname,hashtype=hash.name,hash.type
+ for kk,hh in next,files[hashname] do
+ if not find(kk,"^remap:") then
+ if find(lower(kk),name) then
+ if doit(path,hh,kk,hashname,hashtype,result,allresults) then done=true end
+ if done and not allresults then break end
+ end
end
+ end
end
- if trace_locating then
- report_zip("opener, '%s' not found",original)
+ else
+ local hashes=instance.hashes
+ for k=1,#hashes do
+ local hash=hashes[k]
+ local hashname,hashtype=hash.name,hash.type
+ if doit(path,files[hashname][bname],bname,hashname,hashtype,result,allresults) then done=true end
+ if done and not allresults then break end
end
- return resolvers.openers.notfound()
+ end
+ return result
end
-
-function resolvers.loaders.zip(specification)
- local original = specification.original
- local archive = specification.filename
- if archive then
- local query = url.query(specification.query)
- local queryname = query.name
- if queryname then
- local zfile = zip.openarchive(archive)
- if zfile then
- if trace_locating then
- report_zip("loader, archive '%s' opened",archive)
- end
- local dfile = zfile:open(queryname)
- if dfile then
- logs.show_load(original)
- if trace_locating then
- report_zip("loader, file '%s' loaded",original)
- end
- local s = dfile:read("*all")
- dfile:close()
- return true, s, #s
- elseif trace_locating then
- report_zip("loader, file '%s' not found",queryname)
- end
- elseif trace_locating then
- report_zip("loader, unknown archive '%s'",archive)
- end
- end
- end
+function resolvers.findwildcardfiles(filename,result)
+ return findwildcardfiles(filename,true,result)
+end
+function resolvers.findwildcardfile(filename)
+ return findwildcardfiles(filename,false)[1] or ""
+end
+function resolvers.automount()
+end
+function resolvers.load(option)
+ statistics.starttiming(instance)
+ identify_configuration_files()
+ load_configuration_files()
+ if option~="nofiles" then
+ load_databases()
+ resolvers.automount()
+ end
+ statistics.stoptiming(instance)
+ local files=instance.files
+ return files and next(files) and true
+end
+function resolvers.loadtime()
+ return statistics.elapsedtime(instance)
+end
+local function report(str)
+ if trace_locating then
+ report_resolving(str)
+ else
+ print(str)
+ end
+end
+function resolvers.dowithfilesandreport(command,files,...)
+ if files and #files>0 then
if trace_locating then
- report_zip("loader, '%s' not found",original)
+ report('')
end
- return resolvers.openers.notfound()
-end
-
--- zip:///somefile.zip
--- zip:///somefile.zip?tree=texmf-local -> mount
-
-function resolvers.usezipfile(archive)
- local specification = resolvers.splitmethod(archive) -- to be sure
- local archive = specification.filename
- if archive and not registeredfiles[archive] then
- local z = zip.openarchive(archive)
- if z then
- local instance = resolvers.instance
- local tree = url.query(specification.query).tree or ""
- if trace_locating then
- report_zip("registering, registering archive '%s'",archive)
- end
- statistics.starttiming(instance)
- resolvers.prependhash('zip',archive)
- resolvers.extendtexmfvariable(archive) -- resets hashes too
- registeredfiles[archive] = z
- instance.files[archive] = resolvers.registerzipfile(z,tree)
- statistics.stoptiming(instance)
- elseif trace_locating then
- report_zip("registering, unknown archive '%s'",archive)
+ if type(files)=="string" then
+ files={ files }
+ end
+ for f=1,#files do
+ local file=files[f]
+ local result=command(file,...)
+ if type(result)=='string' then
+ report(result)
+ else
+ for i=1,#result do
+ report(result[i])
end
- elseif trace_locating then
- report_zip("registering, '%s' not found",archive)
+ end
end
+ end
end
-
-function resolvers.registerzipfile(z,tree)
- local files, filter = { }, ""
- if tree == "" then
- filter = "^(.+)/(.-)$"
+function resolvers.showpath(str)
+ return joinpath(resolvers.expandedpathlist(resolvers.formatofvariable(str)))
+end
+function resolvers.registerfile(files,name,path)
+ if files[name] then
+ if type(files[name])=='string' then
+ files[name]={ files[name],path }
else
- filter = format("^%s/(.+)/(.-)$",tree)
+ files[name]=path
end
- if trace_locating then
- report_zip("registering, using filter '%s'",filter)
- end
- local register, n = resolvers.registerfile, 0
- for i in z:files() do
- local path, name = match(i.filename,filter)
- if path then
- if name and name ~= '' then
- register(files, name, path)
- n = n + 1
+ else
+ files[name]=path
+ end
+end
+function resolvers.dowithpath(name,func)
+ local pathlist=resolvers.expandedpathlist(name)
+ for i=1,#pathlist do
+ func("^"..resolvers.cleanpath(pathlist[i]))
+ end
+end
+function resolvers.dowithvariable(name,func)
+ func(expandedvariable(name))
+end
+function resolvers.locateformat(name)
+ local engine=environment.ownmain or "luatex"
+ local barename=file.removesuffix(name)
+ local fullname=file.addsuffix(barename,"fmt")
+ local fmtname=caches.getfirstreadablefile(fullname,"formats",engine) or ""
+ if fmtname=="" then
+ fmtname=resolvers.findfile(fullname)
+ fmtname=resolvers.cleanpath(fmtname)
+ end
+ if fmtname~="" then
+ local barename=file.removesuffix(fmtname)
+ local luaname=file.addsuffix(barename,luasuffixes.lua)
+ local lucname=file.addsuffix(barename,luasuffixes.luc)
+ local luiname=file.addsuffix(barename,luasuffixes.lui)
+ if lfs.isfile(luiname) then
+ return barename,luiname
+ elseif lfs.isfile(lucname) then
+ return barename,lucname
+ elseif lfs.isfile(luaname) then
+ return barename,luaname
+ end
+ end
+ return nil,nil
+end
+function resolvers.booleanvariable(str,default)
+ local b=resolvers.expansion(str)
+ if b=="" then
+ return default
+ else
+ b=toboolean(b)
+ return (b==nil and default) or b
+ end
+end
+function resolvers.dowithfilesintree(pattern,handle,before,after)
+ local instance=resolvers.instance
+ local hashes=instance.hashes
+ for i=1,#hashes do
+ local hash=hashes[i]
+ local blobtype=hash.type
+ local blobpath=hash.name
+ if blobpath then
+ if before then
+ before(blobtype,blobpath,pattern)
+ end
+ local files=instance.files[blobpath]
+ local total,checked,done=0,0,0
+ if files then
+ for k,v in table.sortedhash(files) do
+ total=total+1
+ if find(k,"^remap:") then
+ elseif find(k,pattern) then
+ if type(v)=="string" then
+ checked=checked+1
+ if handle(blobtype,blobpath,v,k) then
+ done=done+1
+ end
else
- -- directory
+ checked=checked+#v
+ for i=1,#v do
+ if handle(blobtype,blobpath,v[i],k) then
+ done=done+1
+ end
+ end
end
- else
- register(files, i.filename, '')
- n = n + 1
+ end
end
+ end
+ if after then
+ after(blobtype,blobpath,pattern,total,checked,done)
+ end
end
- report_zip("registering, %s files registered",n)
- return files
+ end
end
+resolvers.obsolete=resolvers.obsolete or {}
+local obsolete=resolvers.obsolete
+resolvers.find_file=resolvers.findfile obsolete.find_file=resolvers.findfile
+resolvers.find_files=resolvers.findfiles obsolete.find_files=resolvers.findfiles
end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['data-tre'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- \input tree://oeps1/**/oeps.tex
+package.loaded["data-pre"] = package.loaded["data-pre"] or true
-local find, gsub, format = string.find, string.gsub, string.format
+-- original size: 6430, stripped down to: 4219
-local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
-
-local report_trees = logs.reporter("resolvers","trees")
-
-local resolvers = resolvers
-
-local done, found, notfound = { }, { }, resolvers.finders.notfound
-
-function resolvers.finders.tree(specification)
- local spec = specification.filename
- local fnd = found[spec]
- if fnd == nil then
- if spec ~= "" then
- local path, name = file.dirname(spec), file.basename(spec)
- if path == "" then path = "." end
- local hash = done[path]
- if not hash then
- local pattern = path .. "/*" -- we will use the proper splitter
- hash = dir.glob(pattern)
- done[path] = hash
- end
- local pattern = "/" .. gsub(name,"([%.%-%+])", "%%%1") .. "$"
- for k=1,#hash do
- local v = hash[k]
- if find(v,pattern) then
- found[spec] = v
- return v
- end
- end
- end
- fnd = notfound() -- false
- found[spec] = fnd
+if not modules then modules={} end modules ['data-pre']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local resolvers=resolvers
+local prefixes=utilities.storage.allocate()
+resolvers.prefixes=prefixes
+local cleanpath,findgivenfile,expansion=resolvers.cleanpath,resolvers.findgivenfile,resolvers.expansion
+local getenv=resolvers.getenv
+local P,S,R,C,Cs,lpegmatch=lpeg.P,lpeg.S,lpeg.R,lpeg.C,lpeg.Cs,lpeg.match
+local joinpath,basename,dirname=file.join,file.basename,file.dirname
+local getmetatable,rawset,type=getmetatable,rawset,type
+prefixes.environment=function(str)
+ return cleanpath(expansion(str))
+end
+prefixes.relative=function(str,n)
+ if io.exists(str) then
+ elseif io.exists("./"..str) then
+ str="./"..str
+ else
+ local p="../"
+ for i=1,n or 2 do
+ if io.exists(p..str) then
+ str=p..str
+ break
+ else
+ p=p.."../"
+ end
+ end
+ end
+ return cleanpath(str)
+end
+prefixes.auto=function(str)
+ local fullname=prefixes.relative(str)
+ if not lfs.isfile(fullname) then
+ fullname=prefixes.locate(str)
+ end
+ return fullname
+end
+prefixes.locate=function(str)
+ local fullname=findgivenfile(str) or ""
+ return cleanpath((fullname~="" and fullname) or str)
+end
+prefixes.filename=function(str)
+ local fullname=findgivenfile(str) or ""
+ return cleanpath(basename((fullname~="" and fullname) or str))
+end
+prefixes.pathname=function(str)
+ local fullname=findgivenfile(str) or ""
+ return cleanpath(dirname((fullname~="" and fullname) or str))
+end
+prefixes.selfautoloc=function(str)
+ return cleanpath(joinpath(getenv('SELFAUTOLOC'),str))
+end
+prefixes.selfautoparent=function(str)
+ return cleanpath(joinpath(getenv('SELFAUTOPARENT'),str))
+end
+prefixes.selfautodir=function(str)
+ return cleanpath(joinpath(getenv('SELFAUTODIR'),str))
+end
+prefixes.home=function(str)
+ return cleanpath(joinpath(getenv('HOME'),str))
+end
+local function toppath()
+ local inputstack=resolvers.inputstack
+ if not inputstack then
+ return "."
+ end
+ local pathname=dirname(inputstack[#inputstack] or "")
+ if pathname=="" then
+ return "."
+ else
+ return pathname
+ end
+end
+resolvers.toppath=toppath
+prefixes.toppath=function(str)
+ return cleanpath(joinpath(toppath(),str))
+end
+prefixes.env=prefixes.environment
+prefixes.rel=prefixes.relative
+prefixes.loc=prefixes.locate
+prefixes.kpse=prefixes.locate
+prefixes.full=prefixes.locate
+prefixes.file=prefixes.filename
+prefixes.path=prefixes.pathname
+function resolvers.allprefixes(separator)
+ local all=table.sortedkeys(prefixes)
+ if separator then
+ for i=1,#all do
+ all[i]=all[i]..":"
end
- return fnd
+ end
+ return all
end
-
-function resolvers.locators.tree(specification)
- local name = specification.filename
- local realname = resolvers.resolve(name) -- no shortcut
- if realname and realname ~= '' and lfs.isdir(realname) then
- if trace_locating then
- report_trees("locator '%s' found",realname)
- end
- resolvers.appendhash('tree',name,false) -- don't cache
- elseif trace_locating then
- report_trees("locator '%s' not found",name)
+local function _resolve_(method,target)
+ local action=prefixes[method]
+ if action then
+ return action(target)
+ else
+ return method..":"..target
+ end
+end
+local resolved,abstract={},{}
+function resolvers.resetresolve(str)
+ resolved,abstract={},{}
+end
+local pattern=Cs((C(R("az")^2)*P(":")*C((1-S(" \"\';,"))^1)/_resolve_+P(1))^0)
+local function resolve(str)
+ if type(str)=="table" then
+ local t={}
+ for i=1,#str do
+ t[i]=resolve(str[i])
+ end
+ return t
+ else
+ local res=resolved[str]
+ if not res then
+ res=lpegmatch(pattern,str)
+ resolved[str]=res
+ abstract[res]=str
end
+ return res
+ end
end
-
-function resolvers.hashers.tree(specification)
- local name = specification.filename
- if trace_locating then
- report_trees("analysing '%s'",name)
+local function unresolve(str)
+ return abstract[str] or str
+end
+resolvers.resolve=resolve
+resolvers.unresolve=unresolve
+if type(os.uname)=="function" then
+ for k,v in next,os.uname() do
+ if not prefixes[k] then
+ prefixes[k]=function() return v end
end
- resolvers.methodhandler("hashers",name)
-
- resolvers.generators.file(specification)
+ end
+end
+if os.type=="unix" then
+ local pattern
+ local function makepattern(t,k,v)
+ if t then
+ rawset(t,k,v)
+ end
+ local colon=P(":")
+ for k,v in table.sortedpairs(prefixes) do
+ if p then
+ p=P(k)+p
+ else
+ p=P(k)
+ end
+ end
+ pattern=Cs((p*colon+colon/";"+P(1))^0)
+ end
+ makepattern()
+ getmetatable(prefixes).__newindex=makepattern
+ function resolvers.repath(str)
+ return lpegmatch(pattern,str)
+ end
+else
+ function resolvers.repath(str)
+ return str
+ end
end
-
-resolvers.concatinators.tree = resolvers.concatinators.file
-resolvers.generators.tree = resolvers.generators.file
-resolvers.openers.tree = resolvers.openers.file
-resolvers.loaders.tree = resolvers.loaders.file
end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['data-crl'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
+package.loaded["data-inp"] = package.loaded["data-inp"] or true
+
+-- original size: 910, stripped down to: 823
--- this one is replaced by data-sch.lua --
+if not modules then modules={} end modules ['data-inp']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local allocate=utilities.storage.allocate
+local resolvers=resolvers
+local methodhandler=resolvers.methodhandler
+local registermethod=resolvers.registermethod
+local finders=allocate { helpers={},notfound=function() end }
+local openers=allocate { helpers={},notfound=function() end }
+local loaders=allocate { helpers={},notfound=function() return false,nil,0 end }
+registermethod("finders",finders,"uri")
+registermethod("openers",openers,"uri")
+registermethod("loaders",loaders,"uri")
+resolvers.finders=finders
+resolvers.openers=openers
+resolvers.loaders=loaders
-local gsub = string.gsub
-local resolvers = resolvers
+end -- of closure
-local finders, openers, loaders = resolvers.finders, resolvers.openers, resolvers.loaders
+do -- create closure to overcome 200 locals limit
-resolvers.curl = resolvers.curl or { }
-local curl = resolvers.curl
+package.loaded["data-out"] = package.loaded["data-out"] or true
-local cached = { }
+-- original size: 530, stripped down to: 475
-local function runcurl(specification)
- local original = specification.original
- -- local scheme = specification.scheme
- local cleanname = gsub(original,"[^%a%d%.]+","-")
- local cachename = caches.setfirstwritablefile(cleanname,"curl")
- if not cached[original] then
- if not io.exists(cachename) then
- cached[original] = cachename
- local command = "curl --silent --create-dirs --output " .. cachename .. " " .. original
- os.spawn(command)
- end
- if io.exists(cachename) then
- cached[original] = cachename
- else
- cached[original] = ""
- end
- end
- return cached[original]
-end
+if not modules then modules={} end modules ['data-out']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local allocate=utilities.storage.allocate
+local resolvers=resolvers
+local registermethod=resolvers.registermethod
+local savers=allocate { helpers={} }
+resolvers.savers=savers
+registermethod("savers",savers,"uri")
--- old code: we could be cleaner using specification (see schemes)
-local function finder(specification,filetype)
- return resolvers.methodhandler("finders",runcurl(specification),filetype)
-end
+end -- of closure
-local opener = openers.file
-local loader = loaders.file
+do -- create closure to overcome 200 locals limit
-local function install(scheme)
- finders[scheme] = finder
- openers[scheme] = opener
- loaders[scheme] = loader
-end
+package.loaded["data-fil"] = package.loaded["data-fil"] or true
-resolvers.curl.install = install
+-- original size: 3801, stripped down to: 3231
-install('http')
-install('https')
-install('ftp')
+if not modules then modules={} end modules ['data-fil']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end)
+local report_files=logs.reporter("resolvers","files")
+local resolvers=resolvers
+local finders,openers,loaders,savers=resolvers.finders,resolvers.openers,resolvers.loaders,resolvers.savers
+local locators,hashers,generators,concatinators=resolvers.locators,resolvers.hashers,resolvers.generators,resolvers.concatinators
+local checkgarbage=utilities.garbagecollector and utilities.garbagecollector.check
+function locators.file(specification)
+ local name=specification.filename
+ local realname=resolvers.resolve(name)
+ if realname and realname~='' and lfs.isdir(realname) then
+ if trace_locating then
+ report_files("file locator %a found as %a",name,realname)
+ end
+ resolvers.appendhash('file',name,true)
+ elseif trace_locating then
+ report_files("file locator %a not found",name)
+ end
+end
+function hashers.file(specification)
+ local name=specification.filename
+ local content=caches.loadcontent(name,'files')
+ resolvers.registerfilehash(name,content,content==nil)
+end
+function generators.file(specification)
+ local path=specification.filename
+ local content=resolvers.scanfiles(path,false,true)
+ resolvers.registerfilehash(path,content,true)
+end
+concatinators.file=file.join
+function finders.file(specification,filetype)
+ local filename=specification.filename
+ local foundname=resolvers.findfile(filename,filetype)
+ if foundname and foundname~="" then
+ if trace_locating then
+ report_files("file finder: %a found",filename)
+ end
+ return foundname
+ else
+ if trace_locating then
+ report_files("file finder: %a not found",filename)
+ end
+ return finders.notfound()
+ end
+end
+function openers.helpers.textopener(tag,filename,f)
+ return {
+ reader=function() return f:read () end,
+ close=function() logs.show_close(filename) return f:close() end,
+ }
+end
+function openers.file(specification,filetype)
+ local filename=specification.filename
+ if filename and filename~="" then
+ local f=io.open(filename,"r")
+ if f then
+ if trace_locating then
+ report_files("file opener: %a opened",filename)
+ end
+ return openers.helpers.textopener("file",filename,f)
+ end
+ end
+ if trace_locating then
+ report_files("file opener: %a not found",filename)
+ end
+ return openers.notfound()
+end
+function loaders.file(specification,filetype)
+ local filename=specification.filename
+ if filename and filename~="" then
+ local f=io.open(filename,"rb")
+ if f then
+ logs.show_load(filename)
+ if trace_locating then
+ report_files("file loader: %a loaded",filename)
+ end
+ local s=f:read("*a")
+ if checkgarbage then
+ checkgarbage(#s)
+ end
+ f:close()
+ if s then
+ return true,s,#s
+ end
+ end
+ end
+ if trace_locating then
+ report_files("file loader: %a not found",filename)
+ end
+ return loaders.notfound()
+end
end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['data-lua'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
+package.loaded["data-con"] = package.loaded["data-con"] or true
--- some loading stuff ... we might move this one to slot 2 depending
--- on the developments (the loaders must not trigger kpse); we could
--- of course use a more extensive lib path spec
+-- original size: 4940, stripped down to: 3580
-local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
+if not modules then modules={} end modules ['data-con']={
+ version=1.100,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local format,lower,gsub=string.format,string.lower,string.gsub
+local trace_cache=false trackers.register("resolvers.cache",function(v) trace_cache=v end)
+local trace_containers=false trackers.register("resolvers.containers",function(v) trace_containers=v end)
+local trace_storage=false trackers.register("resolvers.storage",function(v) trace_storage=v end)
+containers=containers or {}
+local containers=containers
+containers.usecache=true
+local report_containers=logs.reporter("resolvers","containers")
+local allocated={}
+local mt={
+ __index=function(t,k)
+ if k=="writable" then
+ local writable=caches.getwritablepath(t.category,t.subcategory) or { "." }
+ t.writable=writable
+ return writable
+ elseif k=="readables" then
+ local readables=caches.getreadablepaths(t.category,t.subcategory) or { "." }
+ t.readables=readables
+ return readables
+ end
+ end,
+ __storage__=true
+}
+function containers.define(category,subcategory,version,enabled)
+ if category and subcategory then
+ local c=allocated[category]
+ if not c then
+ c={}
+ allocated[category]=c
+ end
+ local s=c[subcategory]
+ if not s then
+ s={
+ category=category,
+ subcategory=subcategory,
+ storage={},
+ enabled=enabled,
+ version=version or math.pi,
+ trace=false,
+ }
+ setmetatable(s,mt)
+ c[subcategory]=s
+ end
+ return s
+ end
+end
+function containers.is_usable(container,name)
+ return container.enabled and caches and caches.is_writable(container.writable,name)
+end
+function containers.is_valid(container,name)
+ if name and name~="" then
+ local storage=container.storage[name]
+ return storage and storage.cache_version==container.version
+ else
+ return false
+ end
+end
+function containers.read(container,name)
+ local storage=container.storage
+ local stored=storage[name]
+ if not stored and container.enabled and caches and containers.usecache then
+ stored=caches.loaddata(container.readables,name)
+ if stored and stored.cache_version==container.version then
+ if trace_cache or trace_containers then
+ report_containers("action %a, category %a, name %a","load",container.subcategory,name)
+ end
+ else
+ stored=nil
+ end
+ storage[name]=stored
+ elseif stored then
+ if trace_cache or trace_containers then
+ report_containers("action %a, category %a, name %a","reuse",container.subcategory,name)
+ end
+ end
+ return stored
+end
+function containers.write(container,name,data)
+ if data then
+ data.cache_version=container.version
+ if container.enabled and caches then
+ local unique,shared=data.unique,data.shared
+ data.unique,data.shared=nil,nil
+ caches.savedata(container.writable,name,data)
+ if trace_cache or trace_containers then
+ report_containers("action %a, category %a, name %a","save",container.subcategory,name)
+ end
+ data.unique,data.shared=unique,shared
+ end
+ if trace_cache or trace_containers then
+ report_containers("action %a, category %a, name %a","store",container.subcategory,name)
+ end
+ container.storage[name]=data
+ end
+ return data
+end
+function containers.content(container,name)
+ return container.storage[name]
+end
+function containers.cleanname(name)
+ return (gsub(lower(name),"[^%w%d]+","-"))
+end
-local report_libraries = logs.reporter("resolvers","libraries")
-local gsub, insert = string.gsub, table.insert
-local unpack = unpack or table.unpack
+end -- of closure
-local resolvers, package = resolvers, package
+do -- create closure to overcome 200 locals limit
-local libformats = { 'luatexlibs', 'tex', 'texmfscripts', 'othertextfiles' } -- 'luainputs'
-local clibformats = { 'lib' }
+package.loaded["data-use"] = package.loaded["data-use"] or true
-local _path_, libpaths, _cpath_, clibpaths
+-- original size: 3913, stripped down to: 2998
-function package.libpaths()
- if not _path_ or package.path ~= _path_ then
- _path_ = package.path
- libpaths = file.splitpath(_path_,";")
- end
- return libpaths
+if not modules then modules={} end modules ['data-use']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local format,lower,gsub,find=string.format,string.lower,string.gsub,string.find
+local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end)
+local report_mounts=logs.reporter("resolvers","mounts")
+local resolvers=resolvers
+resolvers.automounted=resolvers.automounted or {}
+function resolvers.automount(usecache)
+ local mountpaths=resolvers.cleanpathlist(resolvers.expansion('TEXMFMOUNT'))
+ if (not mountpaths or #mountpaths==0) and usecache then
+ mountpaths=caches.getreadablepaths("mount")
+ end
+ if mountpaths and #mountpaths>0 then
+ statistics.starttiming(resolvers.instance)
+ for k=1,#mountpaths do
+ local root=mountpaths[k]
+ local f=io.open(root.."/url.tmi")
+ if f then
+ for line in f:lines() do
+ if line then
+ if find(line,"^[%%#%-]") then
+ elseif find(line,"^zip://") then
+ if trace_locating then
+ report_mounts("mounting %a",line)
+ end
+ table.insert(resolvers.automounted,line)
+ resolvers.usezipfile(line)
+ end
+ end
+ end
+ f:close()
+ end
+ end
+ statistics.stoptiming(resolvers.instance)
+ end
+end
+statistics.register("used config file",function() return caches.configfiles() end)
+statistics.register("used cache path",function() return caches.usedpaths() end)
+function statistics.savefmtstatus(texname,formatbanner,sourcefile)
+ local enginebanner=status.list().banner
+ if formatbanner and enginebanner and sourcefile then
+ local luvname=file.replacesuffix(texname,"luv")
+ local luvdata={
+ enginebanner=enginebanner,
+ formatbanner=formatbanner,
+ sourcehash=md5.hex(io.loaddata(resolvers.findfile(sourcefile)) or "unknown"),
+ sourcefile=sourcefile,
+ }
+ io.savedata(luvname,table.serialize(luvdata,true))
+ end
end
-
-function package.clibpaths()
- if not _cpath_ or package.cpath ~= _cpath_ then
- _cpath_ = package.cpath
- clibpaths = file.splitpath(_cpath_,";")
+function statistics.checkfmtstatus(texname)
+ local enginebanner=status.list().banner
+ if enginebanner and texname then
+ local luvname=file.replacesuffix(texname,"luv")
+ if lfs.isfile(luvname) then
+ local luv=dofile(luvname)
+ if luv and luv.sourcefile then
+ local sourcehash=md5.hex(io.loaddata(resolvers.findfile(luv.sourcefile)) or "unknown")
+ local luvbanner=luv.enginebanner or "?"
+ if luvbanner~=enginebanner then
+ return format("engine mismatch (luv: %s <> bin: %s)",luvbanner,enginebanner)
+ end
+ local luvhash=luv.sourcehash or "?"
+ if luvhash~=sourcehash then
+ return format("source mismatch (luv: %s <> bin: %s)",luvhash,sourcehash)
+ end
+ else
+ return "invalid status file"
+ end
+ else
+ return "missing status file"
end
- return clibpaths
+ end
+ return true
end
-local function thepath(...)
- local t = { ... } t[#t+1] = "?.lua"
- local path = file.join(unpack(t))
- if trace_locating then
- report_libraries("! appending '%s' to 'package.path'",path)
- end
- return path
-end
-local p_libpaths, a_libpaths = { }, { }
+end -- of closure
-function package.appendtolibpath(...)
- insert(a_libpath,thepath(...))
-end
+do -- create closure to overcome 200 locals limit
-function package.prependtolibpath(...)
- insert(p_libpaths,1,thepath(...))
-end
+package.loaded["data-zip"] = package.loaded["data-zip"] or true
--- beware, we need to return a loadfile result !
+-- original size: 8489, stripped down to: 6757
-local function loaded(libpaths,name,simple)
- for i=1,#libpaths do -- package.path, might become option
- local libpath = libpaths[i]
- local resolved = gsub(libpath,"%?",simple)
- if trace_locating then -- more detail
- report_libraries("! checking for '%s' on 'package.path': '%s' => '%s'",simple,libpath,resolved)
- end
- if file.is_readable(resolved) then
- if trace_locating then
- report_libraries("! lib '%s' located via 'package.path': '%s'",name,resolved)
- end
- return loadfile(resolved)
- end
+if not modules then modules={} end modules ['data-zip']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local format,find,match=string.format,string.find,string.match
+local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end)
+local report_zip=logs.reporter("resolvers","zip")
+local resolvers=resolvers
+zip=zip or {}
+local zip=zip
+zip.archives=zip.archives or {}
+local archives=zip.archives
+zip.registeredfiles=zip.registeredfiles or {}
+local registeredfiles=zip.registeredfiles
+local limited=false
+directives.register("system.inputmode",function(v)
+ if not limited then
+ local i_limiter=io.i_limiter(v)
+ if i_limiter then
+ zip.open=i_limiter.protect(zip.open)
+ limited=true
+ end
+ end
+end)
+local function validzip(str)
+ if not find(str,"^zip://") then
+ return "zip:///"..str
+ else
+ return str
+ end
+end
+function zip.openarchive(name)
+ if not name or name=="" then
+ return nil
+ else
+ local arch=archives[name]
+ if not arch then
+ local full=resolvers.findfile(name) or ""
+ arch=(full~="" and zip.open(full)) or false
+ archives[name]=arch
end
+ return arch
+ end
end
-
-package.loaders[2] = function(name) -- was [#package.loaders+1]
- if file.suffix(name) == "" then
- name = file.addsuffix(name,"lua") -- maybe a list
- if trace_locating then -- mode detail
- report_libraries("! locating '%s' with forced suffix",name)
- end
+function zip.closearchive(name)
+ if not name or (name=="" and archives[name]) then
+ zip.close(archives[name])
+ archives[name]=nil
+ end
+end
+function resolvers.locators.zip(specification)
+ local archive=specification.filename
+ local zipfile=archive and archive~="" and zip.openarchive(archive)
+ if trace_locating then
+ if zipfile then
+ report_zip("locator: archive %a found",archive)
else
- if trace_locating then -- mode detail
- report_libraries("! locating '%s'",name)
- end
+ report_zip("locator: archive %a not found",archive)
end
- for i=1,#libformats do
- local format = libformats[i]
- local resolved = resolvers.findfile(name,format) or ""
- if trace_locating then -- mode detail
- report_libraries("! checking for '%s' using 'libformat path': '%s'",name,format)
- end
- if resolved ~= "" then
- if trace_locating then
- report_libraries("! lib '%s' located via environment: '%s'",name,resolved)
- end
- return loadfile(resolved)
- end
- end
- -- libpaths
- local libpaths, clibpaths = package.libpaths(), package.clibpaths()
- local simple = gsub(name,"%.lua$","")
- local simple = gsub(simple,"%.","/")
- local resolved = loaded(p_libpaths,name,simple) or loaded(libpaths,name,simple) or loaded(a_libpaths,name,simple)
- if resolved then
- return resolved
- end
- --
- local libname = file.addsuffix(simple,os.libsuffix)
- for i=1,#clibformats do
- -- better have a dedicated loop
- local format = clibformats[i]
- local paths = resolvers.expandedpathlistfromvariable(format)
- for p=1,#paths do
- local path = paths[p]
- local resolved = file.join(path,libname)
- if trace_locating then -- mode detail
- report_libraries("! checking for '%s' using 'clibformat path': '%s'",libname,path)
- end
- if file.is_readable(resolved) then
- if trace_locating then
- report_libraries("! lib '%s' located via 'clibformat': '%s'",libname,resolved)
- end
- return package.loadlib(resolved,name)
- end
+ end
+end
+function resolvers.hashers.zip(specification)
+ local archive=specification.filename
+ if trace_locating then
+ report_zip("loading file %a",archive)
+ end
+ resolvers.usezipfile(specification.original)
+end
+function resolvers.concatinators.zip(zipfile,path,name)
+ if not path or path=="" then
+ return format('%s?name=%s',zipfile,name)
+ else
+ return format('%s?name=%s/%s',zipfile,path,name)
+ end
+end
+function resolvers.finders.zip(specification)
+ local original=specification.original
+ local archive=specification.filename
+ if archive then
+ local query=url.query(specification.query)
+ local queryname=query.name
+ if queryname then
+ local zfile=zip.openarchive(archive)
+ if zfile then
+ if trace_locating then
+ report_zip("finder: archive %a found",archive)
+ end
+ local dfile=zfile:open(queryname)
+ if dfile then
+ dfile=zfile:close()
+ if trace_locating then
+ report_zip("finder: file %a found",queryname)
+ end
+ return specification.original
+ elseif trace_locating then
+ report_zip("finder: file %a not found",queryname)
end
+ elseif trace_locating then
+ report_zip("finder: unknown archive %a",archive)
+ end
end
- for i=1,#clibpaths do -- package.path, might become option
- local libpath = clibpaths[i]
- local resolved = gsub(libpath,"?",simple)
- if trace_locating then -- more detail
- report_libraries("! checking for '%s' on 'package.cpath': '%s'",simple,libpath)
- end
- if file.is_readable(resolved) then
- if trace_locating then
- report_libraries("! lib '%s' located via 'package.cpath': '%s'",name,resolved)
- end
- return package.loadlib(resolved,name)
+ end
+ if trace_locating then
+ report_zip("finder: %a not found",original)
+ end
+ return resolvers.finders.notfound()
+end
+function resolvers.openers.zip(specification)
+ local original=specification.original
+ local archive=specification.filename
+ if archive then
+ local query=url.query(specification.query)
+ local queryname=query.name
+ if queryname then
+ local zfile=zip.openarchive(archive)
+ if zfile then
+ if trace_locating then
+ report_zip("opener; archive %a opened",archive)
+ end
+ local dfile=zfile:open(queryname)
+ if dfile then
+ if trace_locating then
+ report_zip("opener: file %a found",queryname)
+ end
+ return resolvers.openers.helpers.textopener('zip',original,dfile)
+ elseif trace_locating then
+ report_zip("opener: file %a not found",queryname)
end
+ elseif trace_locating then
+ report_zip("opener: unknown archive %a",archive)
+ end
end
- -- just in case the distribution is messed up
- if trace_loading then -- more detail
- report_libraries("! checking for '%s' using 'luatexlibs': '%s'",name)
- end
- local resolved = resolvers.findfile(file.basename(name),'luatexlibs') or ""
- if resolved ~= "" then
+ end
+ if trace_locating then
+ report_zip("opener: %a not found",original)
+ end
+ return resolvers.openers.notfound()
+end
+function resolvers.loaders.zip(specification)
+ local original=specification.original
+ local archive=specification.filename
+ if archive then
+ local query=url.query(specification.query)
+ local queryname=query.name
+ if queryname then
+ local zfile=zip.openarchive(archive)
+ if zfile then
if trace_locating then
- report_libraries("! lib '%s' located by basename via environment: '%s'",name,resolved)
+ report_zip("loader: archive %a opened",archive)
+ end
+ local dfile=zfile:open(queryname)
+ if dfile then
+ logs.show_load(original)
+ if trace_locating then
+ report_zip("loader; file %a loaded",original)
+ end
+ local s=dfile:read("*all")
+ dfile:close()
+ return true,s,#s
+ elseif trace_locating then
+ report_zip("loader: file %a not found",queryname)
end
- return loadfile(resolved)
+ elseif trace_locating then
+ report_zip("loader; unknown archive %a",archive)
+ end
end
- if trace_locating then
- report_libraries('? unable to locate lib: %s',name)
+ end
+ if trace_locating then
+ report_zip("loader: %a not found",original)
+ end
+ return resolvers.openers.notfound()
+end
+function resolvers.usezipfile(archive)
+ local specification=resolvers.splitmethod(archive)
+ local archive=specification.filename
+ if archive and not registeredfiles[archive] then
+ local z=zip.openarchive(archive)
+ if z then
+ local instance=resolvers.instance
+ local tree=url.query(specification.query).tree or ""
+ if trace_locating then
+ report_zip("registering: archive %a",archive)
+ end
+ statistics.starttiming(instance)
+ resolvers.prependhash('zip',archive)
+ resolvers.extendtexmfvariable(archive)
+ registeredfiles[archive]=z
+ instance.files[archive]=resolvers.registerzipfile(z,tree)
+ statistics.stoptiming(instance)
+ elseif trace_locating then
+ report_zip("registering: unknown archive %a",archive)
+ end
+ elseif trace_locating then
+ report_zip("registering: archive %a not found",archive)
+ end
+end
+function resolvers.registerzipfile(z,tree)
+ local files,filter={},""
+ if tree=="" then
+ filter="^(.+)/(.-)$"
+ else
+ filter=format("^%s/(.+)/(.-)$",tree)
+ end
+ if trace_locating then
+ report_zip("registering: using filter %a",filter)
+ end
+ local register,n=resolvers.registerfile,0
+ for i in z:files() do
+ local path,name=match(i.filename,filter)
+ if path then
+ if name and name~='' then
+ register(files,name,path)
+ n=n+1
+ else
+ end
+ else
+ register(files,i.filename,'')
+ n=n+1
end
--- return "unable to locate " .. name
+ end
+ report_zip("registering: %s files registered",n)
+ return files
end
-resolvers.loadlualib = require
--- -- -- --
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
-package.obsolete = package.obsolete or { }
+package.loaded["data-tre"] = package.loaded["data-tre"] or true
-package.append_libpath = appendtolibpath -- will become obsolete
-package.prepend_libpath = prependtolibpath -- will become obsolete
+-- original size: 2508, stripped down to: 2074
-package.obsolete.append_libpath = appendtolibpath -- will become obsolete
-package.obsolete.prepend_libpath = prependtolibpath -- will become obsolete
+if not modules then modules={} end modules ['data-tre']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local find,gsub,format=string.find,string.gsub,string.format
+local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end)
+local report_trees=logs.reporter("resolvers","trees")
+local resolvers=resolvers
+local done,found,notfound={},{},resolvers.finders.notfound
+function resolvers.finders.tree(specification)
+ local spec=specification.filename
+ local fnd=found[spec]
+ if fnd==nil then
+ if spec~="" then
+ local path,name=file.dirname(spec),file.basename(spec)
+ if path=="" then path="." end
+ local hash=done[path]
+ if not hash then
+ local pattern=path.."/*"
+ hash=dir.glob(pattern)
+ done[path]=hash
+ end
+ local pattern="/"..gsub(name,"([%.%-%+])","%%%1").."$"
+ for k=1,#hash do
+ local v=hash[k]
+ if find(v,pattern) then
+ found[spec]=v
+ return v
+ end
+ end
+ end
+ fnd=notfound()
+ found[spec]=fnd
+ end
+ return fnd
+end
+function resolvers.locators.tree(specification)
+ local name=specification.filename
+ local realname=resolvers.resolve(name)
+ if realname and realname~='' and lfs.isdir(realname) then
+ if trace_locating then
+ report_trees("locator %a found",realname)
+ end
+ resolvers.appendhash('tree',name,false)
+ elseif trace_locating then
+ report_trees("locator %a not found",name)
+ end
+end
+function resolvers.hashers.tree(specification)
+ local name=specification.filename
+ if trace_locating then
+ report_trees("analysing %a",name)
+ end
+ resolvers.methodhandler("hashers",name)
+ resolvers.generators.file(specification)
+end
+resolvers.concatinators.tree=resolvers.concatinators.file
+resolvers.generators.tree=resolvers.generators.file
+resolvers.openers.tree=resolvers.openers.file
+resolvers.loaders.tree=resolvers.loaders.file
end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['data-aux'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local find = string.find
-local type, next = type, next
-
-local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
+package.loaded["data-sch"] = package.loaded["data-sch"] or true
-local resolvers = resolvers
+-- original size: 6202, stripped down to: 5149
-local report_scripts = logs.reporter("resolvers","scripts")
-
-function resolvers.updatescript(oldname,newname) -- oldname -> own.name, not per se a suffix
- local scriptpath = "scripts/context/lua"
- newname = file.addsuffix(newname,"lua")
- local oldscript = resolvers.cleanpath(oldname)
- if trace_locating then
- report_scripts("to be replaced old script %s", oldscript)
- end
- local newscripts = resolvers.findfiles(newname) or { }
- if #newscripts == 0 then
- if trace_locating then
- report_scripts("unable to locate new script")
- end
+if not modules then modules={} end modules ['data-sch']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local load=load
+local gsub,concat,format=string.gsub,table.concat,string.format
+local finders,openers,loaders=resolvers.finders,resolvers.openers,resolvers.loaders
+local trace_schemes=false trackers.register("resolvers.schemes",function(v) trace_schemes=v end)
+local report_schemes=logs.reporter("resolvers","schemes")
+local http=require("socket.http")
+local ltn12=require("ltn12")
+local resolvers=resolvers
+local schemes=resolvers.schemes or {}
+resolvers.schemes=schemes
+local cleaners={}
+schemes.cleaners=cleaners
+local threshold=24*60*60
+directives.register("schemes.threshold",function(v) threshold=tonumber(v) or threshold end)
+function cleaners.none(specification)
+ return specification.original
+end
+function cleaners.strip(specification)
+ return (gsub(specification.original,"[^%a%d%.]+","-"))
+end
+function cleaners.md5(specification)
+ return file.addsuffix(md5.hex(specification.original),file.suffix(specification.path))
+end
+local cleaner=cleaners.strip
+directives.register("schemes.cleanmethod",function(v) cleaner=cleaners[v] or cleaners.strip end)
+function resolvers.schemes.cleanname(specification)
+ local hash=cleaner(specification)
+ if trace_schemes then
+ report_schemes("hashing %a to %a",specification.original,hash)
+ end
+ return hash
+end
+local cached,loaded,reused,thresholds,handlers={},{},{},{},{}
+local function runcurl(name,cachename)
+ local command="curl --silent --create-dirs --output "..cachename.." "..name
+ os.spawn(command)
+end
+local function fetch(specification)
+ local original=specification.original
+ local scheme=specification.scheme
+ local cleanname=schemes.cleanname(specification)
+ local cachename=caches.setfirstwritablefile(cleanname,"schemes")
+ if not cached[original] then
+ statistics.starttiming(schemes)
+ if not io.exists(cachename) or (os.difftime(os.time(),lfs.attributes(cachename).modification)>(thresholds[protocol] or threshold)) then
+ cached[original]=cachename
+ local handler=handlers[scheme]
+ if handler then
+ if trace_schemes then
+ report_schemes("fetching %a, protocol %a, method %a",original,scheme,"built-in")
+ end
+ logs.flush()
+ handler(specification,cachename)
+ else
+ if trace_schemes then
+ report_schemes("fetching %a, protocol %a, method %a",original,scheme,"curl")
+ end
+ logs.flush()
+ runcurl(original,cachename)
+ end
+ end
+ if io.exists(cachename) then
+ cached[original]=cachename
+ if trace_schemes then
+ report_schemes("using cached %a, protocol %a, cachename %a",original,scheme,cachename)
+ end
else
- for i=1,#newscripts do
- local newscript = resolvers.cleanpath(newscripts[i])
- if trace_locating then
- report_scripts("checking new script %s", newscript)
- end
- if oldscript == newscript then
- if trace_locating then
- report_scripts("old and new script are the same")
- end
- elseif not find(newscript,scriptpath) then
- if trace_locating then
- report_scripts("new script should come from %s",scriptpath)
- end
- elseif not (find(oldscript,file.removesuffix(newname).."$") or find(oldscript,newname.."$")) then
- if trace_locating then
- report_scripts("invalid new script name")
- end
- else
- local newdata = io.loaddata(newscript)
- if newdata then
- if trace_locating then
- report_scripts("old script content replaced by new content")
- end
- io.savedata(oldscript,newdata)
- break
- elseif trace_locating then
- report_scripts("unable to load new script")
- end
- end
- end
+ cached[original]=""
+ if trace_schemes then
+ report_schemes("using missing %a, protocol %a",original,scheme)
+ end
+ end
+ loaded[scheme]=loaded[scheme]+1
+ statistics.stoptiming(schemes)
+ else
+ if trace_schemes then
+ report_schemes("reusing %a, protocol %a",original,scheme)
+ end
+ reused[scheme]=reused[scheme]+1
+ end
+ return cached[original]
+end
+local function finder(specification,filetype)
+ return resolvers.methodhandler("finders",fetch(specification),filetype)
+end
+local opener=openers.file
+local loader=loaders.file
+local function install(scheme,handler,newthreshold)
+ handlers [scheme]=handler
+ loaded [scheme]=0
+ reused [scheme]=0
+ finders [scheme]=finder
+ openers [scheme]=opener
+ loaders [scheme]=loader
+ thresholds[scheme]=newthreshold or threshold
+end
+schemes.install=install
+local function http_handler(specification,cachename)
+ local tempname=cachename..".tmp"
+ local f=io.open(tempname,"wb")
+ local status,message=http.request {
+ url=specification.original,
+ sink=ltn12.sink.file(f)
+ }
+ if not status then
+ os.remove(tempname)
+ else
+ os.remove(cachename)
+ os.rename(tempname,cachename)
+ end
+ return cachename
+end
+install('http',http_handler)
+install('https')
+install('ftp')
+statistics.register("scheme handling time",function()
+ local l,r,nl,nr={},{},0,0
+ for k,v in table.sortedhash(loaded) do
+ if v>0 then
+ nl=nl+1
+ l[nl]=k..":"..v
+ end
+ end
+ for k,v in table.sortedhash(reused) do
+ if v>0 then
+ nr=nr+1
+ r[nr]=k..":"..v
+ end
+ end
+ local n=nl+nr
+ if n>0 then
+ l=nl>0 and concat(l) or "none"
+ r=nr>0 and concat(r) or "none"
+ return format("%s seconds, %s processed, threshold %s seconds, loaded: %s, reused: %s",
+ statistics.elapsedtime(schemes),n,threshold,l,r)
+ else
+ return nil
+ end
+end)
+local httprequest=http.request
+local toquery=url.toquery
+local function fetchstring(url,data)
+ local q=data and toquery(data)
+ if q then
+ url=url.."?"..q
+ end
+ local reply=httprequest(url)
+ return reply
+end
+schemes.fetchstring=fetchstring
+function schemes.fetchtable(url,data)
+ local reply=fetchstring(url,data)
+ if reply then
+ local s=load("return "..reply)
+ if s then
+ return s()
end
+ end
end
@@ -15312,78 +15069,198 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['data-tmf'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local resolvers = resolvers
+package.loaded["data-lua"] = package.loaded["data-lua"] or true
-local report_tds = logs.reporter("resolvers","tds")
+-- original size: 4861, stripped down to: 3693
--- = <<
--- ? ??
--- < +=
--- > =+
+if not modules then modules={} end modules ['data-lua']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local resolvers,package=resolvers,package
+local gsub=string.gsub
+local concat=table.concat
+local addsuffix=file.addsuffix
+local P,S,Cs,lpegmatch=lpeg.P,lpeg.S,lpeg.Cs,lpeg.match
+local libsuffixes={ 'tex','lua' }
+local clibsuffixes={ 'lib' }
+local libformats={ 'TEXINPUTS','LUAINPUTS' }
+local clibformats={ 'CLUAINPUTS' }
+local helpers=package.helpers
+trackers.register("resolvers.libraries",function(v) helpers.trace=v end)
+trackers.register("resolvers.locating",function(v) helpers.trace=v end)
+helpers.report=logs.reporter("resolvers","libraries")
+local pattern=Cs(P("!")^0/""*(P("/")*P(-1)/"/"+P("/")^1/"/"+1)^0)
+local function cleanpath(path)
+ return resolvers.resolve(lpegmatch(pattern,path))
+end
+helpers.cleanpath=cleanpath
+local loadedaslib=helpers.loadedaslib
+local loadedbylua=helpers.loadedbylua
+local loadedbypath=helpers.loadedbypath
+local notloaded=helpers.notloaded
+local getlibpaths=package.libpaths
+local getclibpaths=package.clibpaths
+function helpers.libpaths(libhash)
+ local libpaths={}
+ for i=1,#libformats do
+ local paths=resolvers.expandedpathlistfromvariable(libformats[i])
+ for i=1,#paths do
+ local path=cleanpath(paths[i])
+ if not libhash[path] then
+ libpaths[#libpaths+1]=path
+ libhash[path]=true
+ end
+ end
+ end
+ return libpaths
+end
+function helpers.clibpaths(clibhash)
+ local clibpaths={}
+ for i=1,#clibformats do
+ local paths=resolvers.expandedpathlistfromvariable(clibformats[i])
+ for i=1,#paths do
+ local path=cleanpath(paths[i])
+ if not clibhash[path] then
+ clibpaths[#clibpaths+1]=path
+ clibhash[path]=true
+ end
+ end
+ end
+ return clibpaths
+end
+local function loadedbyformat(name,rawname,suffixes,islib)
+ local trace=helpers.trace
+ local report=helpers.report
+ if trace then
+ report("locating %a as %a using formats %a",rawname,name,suffixes)
+ end
+ for i=1,#suffixes do
+ local format=suffixes[i]
+ local resolved=resolvers.findfile(name,format) or ""
+ if trace then
+ report("checking %a using format %a",name,format)
+ end
+ if resolved~="" then
+ if trace then
+ report("lib %a located on %a",name,resolved)
+ end
+ if islib then
+ return true,loadedaslib(resolved,rawname)
+ else
+ return true,loadfile(resolved)
+ end
+ end
+ end
+end
+helpers.loadedbyformat=loadedbyformat
+local pattern=Cs((((1-S("\\/"))^0*(S("\\/")^1/"/"))^0*(P(".")^1/"/"+P(1))^1)*-1)
+local function lualibfile(name)
+ return lpegmatch(pattern,name) or name
+end
+helpers.lualibfile=lualibfile
+function helpers.loaded(name)
+ local thename=lualibfile(name)
+ local luaname=addsuffix(thename,"lua")
+ local libname=addsuffix(thename,os.libsuffix)
+ local libpaths=getlibpaths()
+ local clibpaths=getclibpaths()
+ local done,result=loadedbyformat(luaname,name,libsuffixes,false)
+ if done then
+ return result
+ end
+ local done,result=loadedbyformat(libname,name,clibsuffixes,true)
+ if done then
+ return result
+ end
+ local done,result=loadedbypath(luaname,name,libpaths,false,"lua")
+ if done then
+ return result
+ end
+ local done,result=loadedbypath(luaname,name,clibpaths,false,"lua")
+ if done then
+ return result
+ end
+ local done,result=loadedbypath(libname,name,clibpaths,true,"lib")
+ if done then
+ return result
+ end
+ local done,result=loadedbylua(name)
+ if done then
+ return result
+ end
+ return notloaded(name)
+end
+resolvers.loadlualib=require
-function resolvers.load_tree(tree,resolve)
- if type(tree) == "string" and tree ~= "" then
- local getenv, setenv = resolvers.getenv, resolvers.setenv
+end -- of closure
- -- later might listen to the raw osenv var as well
- local texos = "texmf-" .. os.platform
+do -- create closure to overcome 200 locals limit
- local oldroot = environment.texroot
- local newroot = file.collapsepath(tree)
+package.loaded["data-aux"] = package.loaded["data-aux"] or true
- local newtree = file.join(newroot,texos)
- local newpath = file.join(newtree,"bin")
+-- original size: 2394, stripped down to: 2005
- if not lfs.isdir(newtree) then
- report_tds("no '%s' under tree %s",texos,tree)
- os.exit()
+if not modules then modules={} end modules ['data-aux']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local find=string.find
+local type,next=type,next
+local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end)
+local resolvers=resolvers
+local report_scripts=logs.reporter("resolvers","scripts")
+function resolvers.updatescript(oldname,newname)
+ local scriptpath="scripts/context/lua"
+ newname=file.addsuffix(newname,"lua")
+ local oldscript=resolvers.cleanpath(oldname)
+ if trace_locating then
+ report_scripts("to be replaced old script %a",oldscript)
+ end
+ local newscripts=resolvers.findfiles(newname) or {}
+ if #newscripts==0 then
+ if trace_locating then
+ report_scripts("unable to locate new script")
+ end
+ else
+ for i=1,#newscripts do
+ local newscript=resolvers.cleanpath(newscripts[i])
+ if trace_locating then
+ report_scripts("checking new script %a",newscript)
+ end
+ if oldscript==newscript then
+ if trace_locating then
+ report_scripts("old and new script are the same")
end
- if not lfs.isdir(newpath) then
- report_tds("no '%s/bin' under tree %s",texos,tree)
- os.exit()
+ elseif not find(newscript,scriptpath) then
+ if trace_locating then
+ report_scripts("new script should come from %a",scriptpath)
end
-
- local texmfos = newtree
-
- environment.texroot = newroot
- environment.texos = texos
- environment.texmfos = texmfos
-
- -- Beware, we need to obey the relocatable autoparent so we
- -- set TEXMFCNF to its raw value. This is somewhat tricky when
- -- we run a mkii job from within. Therefore, in mtxrun, there
- -- is a resolve applied when we're in mkii/kpse mode or when
- -- --resolve is passed to mtxrun. Maybe we should also set the
- -- local AUTOPARENT etc. although these are alwasy set new.
-
- if resolve then
- -- resolvers.luacnfspec = resolvers.joinpath(resolvers.resolve(resolvers.expandedpathfromlist(resolvers.splitpath(resolvers.luacnfspec))))
- resolvers.luacnfspec = resolvers.resolve(resolvers.luacnfspec)
+ elseif not (find(oldscript,file.removesuffix(newname).."$") or find(oldscript,newname.."$")) then
+ if trace_locating then
+ report_scripts("invalid new script name")
+ end
+ else
+ local newdata=io.loaddata(newscript)
+ if newdata then
+ if trace_locating then
+ report_scripts("old script content replaced by new content")
+ end
+ io.savedata(oldscript,newdata)
+ break
+ elseif trace_locating then
+ report_scripts("unable to load new script")
end
-
- setenv('SELFAUTOPARENT', newroot)
- setenv('SELFAUTODIR', newtree)
- setenv('SELFAUTOLOC', newpath)
- setenv('TEXROOT', newroot)
- setenv('TEXOS', texos)
- setenv('TEXMFOS', texmfos)
- setenv('TEXMFCNF', resolvers.luacnfspec,true) -- already resolved
- setenv('PATH', newpath .. io.pathseparator .. getenv('PATH'))
-
- report_tds("changing from root '%s' to '%s'",oldroot,newroot)
- report_tds("prepending '%s' to PATH",newpath)
- report_tds("setting TEXMFCNF to '%s'",resolvers.luacnfspec)
- report_tds()
+ end
end
+ end
end
@@ -15391,81 +15268,132 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['data-lst'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
+package.loaded["data-tmf"] = package.loaded["data-tmf"] or true
+
+-- original size: 2600, stripped down to: 1627
+
+if not modules then modules={} end modules ['data-tmf']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
}
+local resolvers=resolvers
+local report_tds=logs.reporter("resolvers","tds")
+function resolvers.load_tree(tree,resolve)
+ if type(tree)=="string" and tree~="" then
+ local getenv,setenv=resolvers.getenv,resolvers.setenv
+ local texos="texmf-"..os.platform
+ local oldroot=environment.texroot
+ local newroot=file.collapsepath(tree)
+ local newtree=file.join(newroot,texos)
+ local newpath=file.join(newtree,"bin")
+ if not lfs.isdir(newtree) then
+ report_tds("no %a under tree %a",texos,tree)
+ os.exit()
+ end
+ if not lfs.isdir(newpath) then
+ report_tds("no '%s/bin' under tree %a",texos,tree)
+ os.exit()
+ end
+ local texmfos=newtree
+ environment.texroot=newroot
+ environment.texos=texos
+ environment.texmfos=texmfos
+ if resolve then
+ resolvers.luacnfspec=resolvers.resolve(resolvers.luacnfspec)
+ end
+ setenv('SELFAUTOPARENT',newroot)
+ setenv('SELFAUTODIR',newtree)
+ setenv('SELFAUTOLOC',newpath)
+ setenv('TEXROOT',newroot)
+ setenv('TEXOS',texos)
+ setenv('TEXMFOS',texmfos)
+ setenv('TEXMFCNF',resolvers.luacnfspec,true)
+ setenv('PATH',newpath..io.pathseparator..getenv('PATH'))
+ report_tds("changing from root %a to %a",oldroot,newroot)
+ report_tds("prepending %a to PATH",newpath)
+ report_tds("setting TEXMFCNF to %a",resolvers.luacnfspec)
+ report_tds()
+ end
+end
--- used in mtxrun, can be loaded later .. todo
-local find, concat, upper, format = string.find, table.concat, string.upper, string.format
-local fastcopy, sortedpairs = table.fastcopy, table.sortedpairs
+end -- of closure
-resolvers.listers = resolvers.listers or { }
+do -- create closure to overcome 200 locals limit
-local resolvers = resolvers
+package.loaded["data-lst"] = package.loaded["data-lst"] or true
-local report_lists = logs.reporter("resolvers","lists")
+-- original size: 2654, stripped down to: 2301
+if not modules then modules={} end modules ['data-lst']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local find,concat,upper,format=string.find,table.concat,string.upper,string.format
+local fastcopy,sortedpairs=table.fastcopy,table.sortedpairs
+resolvers.listers=resolvers.listers or {}
+local resolvers=resolvers
+local report_lists=logs.reporter("resolvers","lists")
local function tabstr(str)
- if type(str) == 'table' then
- return concat(str," | ")
- else
- return str
- end
+ if type(str)=='table' then
+ return concat(str," | ")
+ else
+ return str
+ end
end
-
function resolvers.listers.variables(pattern)
- local instance = resolvers.instance
- local environment = instance.environment
- local variables = instance.variables
- local expansions = instance.expansions
- local pattern = upper(pattern or "")
- local configured = { }
- local order = instance.order
- for i=1,#order do
- for k, v in next, order[i] do
- if v ~= nil and configured[k] == nil then
- configured[k] = v
- end
- end
- end
- local env = fastcopy(environment)
- local var = fastcopy(variables)
- local exp = fastcopy(expansions)
- for key, value in sortedpairs(configured) do
- if key ~= "" and (pattern == "" or find(upper(key),pattern)) then
- report_lists(key)
- report_lists(" env: %s",tabstr(rawget(environment,key)) or "unset")
- report_lists(" var: %s",tabstr(configured[key]) or "unset")
- report_lists(" exp: %s",tabstr(expansions[key]) or "unset")
- report_lists(" res: %s",tabstr(resolvers.resolve(expansions[key])) or "unset")
- end
- end
- instance.environment = fastcopy(env)
- instance.variables = fastcopy(var)
- instance.expansions = fastcopy(exp)
-end
-
-function resolvers.listers.configurations(report)
- local configurations = resolvers.instance.specification
- local report = report or texio.write_nl
- for i=1,#configurations do
- report(format("file : %s",resolvers.resolve(configurations[i])))
- end
- report("")
- local list = resolvers.expandedpathfromlist(resolvers.splitpath(resolvers.luacnfspec))
- for i=1,#list do
- local li = resolvers.resolve(list[i])
- if lfs.isdir(li) then
- report(format("path - %s",li))
- else
- report(format("path + %s",li))
- end
+ local instance=resolvers.instance
+ local environment=instance.environment
+ local variables=instance.variables
+ local expansions=instance.expansions
+ local pattern=upper(pattern or "")
+ local configured={}
+ local order=instance.order
+ for i=1,#order do
+ for k,v in next,order[i] do
+ if v~=nil and configured[k]==nil then
+ configured[k]=v
+ end
+ end
+ end
+ local env=fastcopy(environment)
+ local var=fastcopy(variables)
+ local exp=fastcopy(expansions)
+ for key,value in sortedpairs(configured) do
+ if key~="" and (pattern=="" or find(upper(key),pattern)) then
+ report_lists(key)
+ report_lists(" env: %s",tabstr(rawget(environment,key)) or "unset")
+ report_lists(" var: %s",tabstr(configured[key]) or "unset")
+ report_lists(" exp: %s",tabstr(expansions[key]) or "unset")
+ report_lists(" res: %s",tabstr(resolvers.resolve(expansions[key])) or "unset")
+ end
+ end
+ instance.environment=fastcopy(env)
+ instance.variables=fastcopy(var)
+ instance.expansions=fastcopy(exp)
+end
+local report_resolved=logs.reporter("system","resolved")
+function resolvers.listers.configurations()
+ local configurations=resolvers.instance.specification
+ for i=1,#configurations do
+ report_resolved("file : %s",resolvers.resolve(configurations[i]))
+ end
+ report_resolved("")
+ local list=resolvers.expandedpathfromlist(resolvers.splitpath(resolvers.luacnfspec))
+ for i=1,#list do
+ local li=resolvers.resolve(list[i])
+ if lfs.isdir(li) then
+ report_resolved("path - %s",li)
+ else
+ report_resolved("path + %s",li)
end
+ end
end
@@ -15473,279 +15401,407 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['luat-sta'] = {
- version = 1.001,
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
+package.loaded["util-lib"] = package.loaded["util-lib"] or true
--- this code is used in the updater
+-- original size: 8911, stripped down to: 4216
-local gmatch, match = string.gmatch, string.match
-local type = type
+if not modules then modules={} end modules ['util-lib']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files",
+}
+local gsub,find=string.gsub,string.find
+local pathpart,nameonly,joinfile=file.pathpart,file.nameonly,file.join
+local findfile,findfiles=resolvers and resolvers.findfile,resolvers and resolvers.findfiles
+local loaded=package.loaded
+local report_swiglib=logs.reporter("swiglib")
+local trace_swiglib=false trackers.register("resolvers.swiglib",function(v) trace_swiglib=v end)
+local function requireswiglib(required,version)
+ local library=loaded[required]
+ if library==nil then
+ local required_full=gsub(required,"%.","/")
+ local required_path=pathpart(required_full)
+ local required_base=nameonly(required_full)
+ local required_name=required_base.."."..os.libsuffix
+ local version=type(version)=="string" and version~="" and version or false
+ local function check(locate,...)
+ local found_library=nil
+ if version then
+ local asked_library=joinfile(required_path,version,required_name)
+ if trace_swiglib then
+ report_swiglib("checking %s: %a","with version",asked_library)
+ end
+ found_library=locate(asked_library,...)
+ if not found_library or found_library==""then
+ asked_library=joinfile(required_path,required_name)
+ if trace_swiglib then
+ report_swiglib("checking %s: %a","without version",asked_library)
+ end
+ found_library=locate(asked_library,...)
+ end
+ else
+ local asked_library=joinfile(required_path,required_name)
+ if trace_swiglib then
+ report_swiglib("checking %s: %a","without version",asked_library)
+ end
+ found_library=locate(asked_library,...)
+ end
+ return found_library and found_library~="" and found_library or false
+ end
+ local found_library=findfile and check(findfile,"lib")
+ if findfiles and not found_library then
+ local asked_library=joinfile(required_path,".*",required_name)
+ if trace_swiglib then
+ report_swiglib("checking %s: %a","latest version",asked_library)
+ end
+ local list=findfiles(asked_library,"lib",true)
+ if list and #list>0 then
+ table.sort(list)
+ found_library=list[#list]
+ end
+ end
+ if not found_library then
+ package.extraclibpath(environment.ownpath)
+ local paths=package.clibpaths()
+ for i=1,#paths do
+ local found_library=check(lfs.isfile)
+ if found_library then
+ break
+ end
+ end
+ end
+ if not found_library then
+ if trace_swiglib then
+ report_swiglib("not found: %a",asked_library)
+ end
+ library=false
+ else
+ local path=pathpart(found_library)
+ local base=nameonly(found_library)
+ dir.push(path)
+ if trace_swiglib then
+ report_swiglib("found: %a",found_library)
+ end
+ library=package.loadlib(found_library,"luaopen_"..required_base)
+ if type(library)=="function" then
+ library=library()
+ else
+ library=false
+ end
+ dir.pop()
+ end
+ if not library then
+ report_swiglib("unknown: %a",required)
+ elseif trace_swiglib then
+ report_swiglib("stored: %a",required)
+ end
+ loaded[required]=library
+ else
+ report_swiglib("reused: %a",required)
+ end
+ return library
+end
+local savedrequire=require
+function require(name,version)
+ if find(name,"^swiglib%.") then
+ return requireswiglib(name,version)
+ else
+ return savedrequire(name)
+ end
+end
+local swiglibs={}
+function swiglib(name,version)
+ local library=swiglibs[name]
+ if not library then
+ statistics.starttiming(swiglibs)
+ report_swiglib("loading %a",name)
+ library=requireswiglib("swiglib."..name,version)
+ swiglibs[name]=library
+ statistics.stoptiming(swiglibs)
+ end
+ return library
+end
+statistics.register("used swiglibs",function()
+ if next(swiglibs) then
+ return string.format("%s, initial load time %s seconds",table.concat(table.sortedkeys(swiglibs)," "),statistics.elapsedtime(swiglibs))
+ end
+end)
-states = states or { }
-local states = states
-states.data = states.data or { }
-local data = states.data
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
-states.hash = states.hash or { }
-local hash = states.hash
+package.loaded["luat-sta"] = package.loaded["luat-sta"] or true
-states.tag = states.tag or ""
-states.filename = states.filename or ""
+-- original size: 5703, stripped down to: 2507
+if not modules then modules={} end modules ['luat-sta']={
+ version=1.001,
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local gmatch,match=string.gmatch,string.match
+local type=type
+states=states or {}
+local states=states
+states.data=states.data or {}
+local data=states.data
+states.hash=states.hash or {}
+local hash=states.hash
+states.tag=states.tag or ""
+states.filename=states.filename or ""
function states.save(filename,tag)
- tag = tag or states.tag
- filename = file.addsuffix(filename or states.filename,'lus')
- io.savedata(filename,
- "-- generator : luat-sta.lua\n" ..
- "-- state tag : " .. tag .. "\n\n" ..
- table.serialize(data[tag or states.tag] or {},true)
- )
+ tag=tag or states.tag
+ filename=file.addsuffix(filename or states.filename,'lus')
+ io.savedata(filename,
+ "-- generator : luat-sta.lua\n".."-- state tag : "..tag.."\n\n"..table.serialize(data[tag or states.tag] or {},true)
+ )
end
-
function states.load(filename,tag)
- states.filename = filename
- states.tag = tag or "whatever"
- states.filename = file.addsuffix(states.filename,'lus')
- data[states.tag], hash[states.tag] = (io.exists(filename) and dofile(filename)) or { }, { }
+ states.filename=filename
+ states.tag=tag or "whatever"
+ states.filename=file.addsuffix(states.filename,'lus')
+ data[states.tag],hash[states.tag]=(io.exists(filename) and dofile(filename)) or {},{}
end
-
local function set_by_tag(tag,key,value,default,persistent)
- local d, h = data[tag], hash[tag]
- if d then
- if type(d) == "table" then
- local dkey, hkey = key, key
- local pre, post = match(key,"(.+)%.([^%.]+)$")
- if pre and post then
- for k in gmatch(pre,"[^%.]+") do
- local dk = d[k]
- if not dk then
- dk = { }
- d[k] = dk
- elseif type(dk) == "string" then
- -- invalid table, unable to upgrade structure
- -- hope for the best or delete the state file
- break
- end
- d = dk
- end
- dkey, hkey = post, key
- end
- if value == nil then
- value = default
- elseif value == false then
- -- special case
- elseif persistent then
- value = value or d[dkey] or default
- else
- value = value or default
- end
- d[dkey], h[hkey] = value, value
- elseif type(d) == "string" then
- -- weird
- data[tag], hash[tag] = value, value
- end
- end
+ local d,h=data[tag],hash[tag]
+ if d then
+ if type(d)=="table" then
+ local dkey,hkey=key,key
+ local pre,post=match(key,"(.+)%.([^%.]+)$")
+ if pre and post then
+ for k in gmatch(pre,"[^%.]+") do
+ local dk=d[k]
+ if not dk then
+ dk={}
+ d[k]=dk
+ elseif type(dk)=="string" then
+ break
+ end
+ d=dk
+ end
+ dkey,hkey=post,key
+ end
+ if value==nil then
+ value=default
+ elseif value==false then
+ elseif persistent then
+ value=value or d[dkey] or default
+ else
+ value=value or default
+ end
+ d[dkey],h[hkey]=value,value
+ elseif type(d)=="string" then
+ data[tag],hash[tag]=value,value
+ end
+ end
end
-
local function get_by_tag(tag,key,default)
- local h = hash[tag]
- if h and h[key] then
- return h[key]
- else
- local d = data[tag]
- if d then
- for k in gmatch(key,"[^%.]+") do
- local dk = d[k]
- if dk ~= nil then
- d = dk
- else
- return default
- end
- end
- if d == false then
- return false
- else
- return d or default
- end
+ local h=hash[tag]
+ if h and h[key] then
+ return h[key]
+ else
+ local d=data[tag]
+ if d then
+ for k in gmatch(key,"[^%.]+") do
+ local dk=d[k]
+ if dk~=nil then
+ d=dk
+ else
+ return default
end
+ end
+ if d==false then
+ return false
+ else
+ return d or default
+ end
end
+ end
end
-
-states.set_by_tag = set_by_tag
-states.get_by_tag = get_by_tag
-
+states.set_by_tag=set_by_tag
+states.get_by_tag=get_by_tag
function states.set(key,value,default,persistent)
- set_by_tag(states.tag,key,value,default,persistent)
+ set_by_tag(states.tag,key,value,default,persistent)
end
-
function states.get(key,default)
- return get_by_tag(states.tag,key,default)
+ return get_by_tag(states.tag,key,default)
end
-
-
-
end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['luat-fmt'] = {
- version = 1.001,
- comment = "companion to mtxrun",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-
-local format = string.format
-
-local report_format = logs.reporter("resolvers","formats")
-
--- helper for mtxrun
+package.loaded["luat-fmt"] = package.loaded["luat-fmt"] or true
-local quoted = string.quoted
+-- original size: 5951, stripped down to: 4922
-local function primaryflags() -- not yet ok
- local trackers = environment.argument("trackers")
- local directives = environment.argument("directives")
- local flags = ""
- if trackers and trackers ~= "" then
- flags = flags .. "--trackers=" .. quoted(trackers)
- end
- if directives and directives ~= "" then
- flags = flags .. "--directives=" .. quoted(directives)
- end
- return flags
+if not modules then modules={} end modules ['luat-fmt']={
+ version=1.001,
+ comment="companion to mtxrun",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local format=string.format
+local concat=table.concat
+local quoted=string.quoted
+local luasuffixes=utilities.lua.suffixes
+local report_format=logs.reporter("resolvers","formats")
+local function primaryflags()
+ local trackers=environment.argument("trackers")
+ local directives=environment.argument("directives")
+ local flags={}
+ if trackers and trackers~="" then
+ flags={ "--trackers="..quoted(trackers) }
+ end
+ if directives and directives~="" then
+ flags={ "--directives="..quoted(directives) }
+ end
+ if environment.argument("jit") then
+ flags={ "--jiton" }
+ end
+ return concat(flags," ")
end
-
function environment.make_format(name)
- -- change to format path (early as we need expanded paths)
- local olddir = lfs.currentdir()
- local path = caches.getwritablepath("formats") or "" -- maybe platform
- if path ~= "" then
- lfs.chdir(path)
- end
- report_format("format path: %s",lfs.currentdir())
- -- check source file
- local texsourcename = file.addsuffix(name,"mkiv")
- local fulltexsourcename = resolvers.findfile(texsourcename,"tex") or ""
- if fulltexsourcename == "" then
- texsourcename = file.addsuffix(name,"tex")
- fulltexsourcename = resolvers.findfile(texsourcename,"tex") or ""
- end
- if fulltexsourcename == "" then
- report_format("no tex source file with name: %s (mkiv or tex)",name)
- lfs.chdir(olddir)
- return
- else
- report_format("using tex source file: %s",fulltexsourcename)
- end
- local texsourcepath = dir.expandname(file.dirname(fulltexsourcename)) -- really needed
- -- check specification
- local specificationname = file.replacesuffix(fulltexsourcename,"lus")
- local fullspecificationname = resolvers.findfile(specificationname,"tex") or ""
- if fullspecificationname == "" then
- specificationname = file.join(texsourcepath,"context.lus")
- fullspecificationname = resolvers.findfile(specificationname,"tex") or ""
- end
- if fullspecificationname == "" then
- report_format("unknown stub specification: %s",specificationname)
- lfs.chdir(olddir)
- return
- end
- local specificationpath = file.dirname(fullspecificationname)
- -- load specification
- local usedluastub = nil
- local usedlualibs = dofile(fullspecificationname)
- if type(usedlualibs) == "string" then
- usedluastub = file.join(file.dirname(fullspecificationname),usedlualibs)
- elseif type(usedlualibs) == "table" then
- report_format("using stub specification: %s",fullspecificationname)
- local texbasename = file.basename(name)
- local luastubname = file.addsuffix(texbasename,"lua")
- local lucstubname = file.addsuffix(texbasename,"luc")
- -- pack libraries in stub
- report_format("creating initialization file: %s",luastubname)
- utilities.merger.selfcreate(usedlualibs,specificationpath,luastubname)
- -- compile stub file (does not save that much as we don't use this stub at startup any more)
- local strip = resolvers.booleanvariable("LUACSTRIP", true)
- if utilities.lua.compile(luastubname,lucstubname) and lfs.isfile(lucstubname) then
- report_format("using compiled initialization file: %s",lucstubname)
- usedluastub = lucstubname
- else
- report_format("using uncompiled initialization file: %s",luastubname)
- usedluastub = luastubname
- end
+ local engine=environment.ownmain or "luatex"
+ local olddir=dir.current()
+ local path=caches.getwritablepath("formats",engine) or ""
+ if path~="" then
+ lfs.chdir(path)
+ end
+ report_format("using format path %a",dir.current())
+ local texsourcename=file.addsuffix(name,"mkiv")
+ local fulltexsourcename=resolvers.findfile(texsourcename,"tex") or ""
+ if fulltexsourcename=="" then
+ texsourcename=file.addsuffix(name,"tex")
+ fulltexsourcename=resolvers.findfile(texsourcename,"tex") or ""
+ end
+ if fulltexsourcename=="" then
+ report_format("no tex source file with name %a (mkiv or tex)",name)
+ lfs.chdir(olddir)
+ return
+ else
+ report_format("using tex source file %a",fulltexsourcename)
+ end
+ local texsourcepath=dir.expandname(file.dirname(fulltexsourcename))
+ local specificationname=file.replacesuffix(fulltexsourcename,"lus")
+ local fullspecificationname=resolvers.findfile(specificationname,"tex") or ""
+ if fullspecificationname=="" then
+ specificationname=file.join(texsourcepath,"context.lus")
+ fullspecificationname=resolvers.findfile(specificationname,"tex") or ""
+ end
+ if fullspecificationname=="" then
+ report_format("unknown stub specification %a",specificationname)
+ lfs.chdir(olddir)
+ return
+ end
+ local specificationpath=file.dirname(fullspecificationname)
+ local usedluastub=nil
+ local usedlualibs=dofile(fullspecificationname)
+ if type(usedlualibs)=="string" then
+ usedluastub=file.join(file.dirname(fullspecificationname),usedlualibs)
+ elseif type(usedlualibs)=="table" then
+ report_format("using stub specification %a",fullspecificationname)
+ local texbasename=file.basename(name)
+ local luastubname=file.addsuffix(texbasename,luasuffixes.lua)
+ local lucstubname=file.addsuffix(texbasename,luasuffixes.luc)
+ report_format("creating initialization file %a",luastubname)
+ utilities.merger.selfcreate(usedlualibs,specificationpath,luastubname)
+ if utilities.lua.compile(luastubname,lucstubname) and lfs.isfile(lucstubname) then
+ report_format("using compiled initialization file %a",lucstubname)
+ usedluastub=lucstubname
else
- report_format("invalid stub specification: %s",fullspecificationname)
- lfs.chdir(olddir)
- return
- end
- -- generate format
- local command = format("luatex --ini %s --lua=%s %s %sdump",primaryflags(),quoted(usedluastub),quoted(fulltexsourcename),os.platform == "unix" and "\\\\" or "\\")
- report_format("running command: %s\n",command)
- os.spawn(command)
- -- remove related mem files
- local pattern = file.removesuffix(file.basename(usedluastub)).."-*.mem"
- -- report_format("removing related mplib format with pattern '%s'", pattern)
- local mp = dir.glob(pattern)
- if mp then
- for i=1,#mp do
- local name = mp[i]
- report_format("removing related mplib format %s", file.basename(name))
- os.remove(name)
- end
+ report_format("using uncompiled initialization file %a",luastubname)
+ usedluastub=luastubname
end
+ else
+ report_format("invalid stub specification %a",fullspecificationname)
lfs.chdir(olddir)
+ return
+ end
+ local command=format("%s --ini %s --lua=%s %s %sdump",engine,primaryflags(),quoted(usedluastub),quoted(fulltexsourcename),os.platform=="unix" and "\\\\" or "\\")
+ report_format("running command: %s\n",command)
+ os.spawn(command)
+ local pattern=file.removesuffix(file.basename(usedluastub)).."-*.mem"
+ local mp=dir.glob(pattern)
+ if mp then
+ for i=1,#mp do
+ local name=mp[i]
+ report_format("removing related mplib format %a",file.basename(name))
+ os.remove(name)
+ end
+ end
+ lfs.chdir(olddir)
end
-
function environment.run_format(name,data,more)
- -- hm, rather old code here; we can now use the file.whatever functions
- if name and name ~= "" then
- local barename = file.removesuffix(name)
- local fmtname = caches.getfirstreadablefile(file.addsuffix(barename,"fmt"),"formats")
- if fmtname == "" then
- fmtname = resolvers.findfile(file.addsuffix(barename,"fmt")) or ""
- end
- fmtname = resolvers.cleanpath(fmtname)
- if fmtname == "" then
- report_format("no format with name: %s",name)
- else
- local barename = file.removesuffix(name) -- expanded name
- local luaname = file.addsuffix(barename,"luc")
- if not lfs.isfile(luaname) then
- luaname = file.addsuffix(barename,"lua")
- end
- if not lfs.isfile(luaname) then
- report_format("using format name: %s",fmtname)
- report_format("no luc/lua with name: %s",barename)
- else
- local command = format("luatex %s --fmt=%s --lua=%s %s %s",primaryflags(),quoted(barename),quoted(luaname),quoted(data),more ~= "" and quoted(more) or "")
- report_format("running command: %s",command)
- os.spawn(command)
- end
- end
+ if name and name~="" then
+ local engine=environment.ownmain or "luatex"
+ local barename=file.removesuffix(name)
+ local fmtname=caches.getfirstreadablefile(file.addsuffix(barename,"fmt"),"formats",engine)
+ if fmtname=="" then
+ fmtname=resolvers.findfile(file.addsuffix(barename,"fmt")) or ""
+ end
+ fmtname=resolvers.cleanpath(fmtname)
+ if fmtname=="" then
+ report_format("no format with name %a",name)
+ else
+ local barename=file.removesuffix(name)
+ local luaname=file.addsuffix(barename,"luc")
+ if not lfs.isfile(luaname) then
+ luaname=file.addsuffix(barename,"lua")
+ end
+ if not lfs.isfile(luaname) then
+ report_format("using format name %a",fmtname)
+ report_format("no luc/lua file with name %a",barename)
+ else
+ local command=format("%s %s --fmt=%s --lua=%s %s %s",engine,primaryflags(),quoted(barename),quoted(luaname),quoted(data),more~="" and quoted(more) or "")
+ report_format("running command: %s",command)
+ os.spawn(command)
+ end
end
+ end
end
end -- of closure
+
+-- used libraries : l-lua.lua l-lpeg.lua l-function.lua l-string.lua l-table.lua l-io.lua l-number.lua l-set.lua l-os.lua l-file.lua l-md5.lua l-url.lua l-dir.lua l-boolean.lua l-unicode.lua l-math.lua util-str.lua util-tab.lua util-sto.lua util-prs.lua util-fmt.lua trac-set.lua trac-log.lua trac-inf.lua trac-pro.lua util-lua.lua util-deb.lua util-mrg.lua util-tpl.lua util-env.lua luat-env.lua lxml-tab.lua lxml-lpt.lua lxml-mis.lua lxml-aux.lua lxml-xml.lua trac-xml.lua data-ini.lua data-exp.lua data-env.lua data-tmp.lua data-met.lua data-res.lua data-pre.lua data-inp.lua data-out.lua data-fil.lua data-con.lua data-use.lua data-zip.lua data-tre.lua data-sch.lua data-lua.lua data-aux.lua data-tmf.lua data-lst.lua util-lib.lua luat-sta.lua luat-fmt.lua
+-- skipped libraries : -
+-- original bytes : 658276
+-- stripped bytes : 241564
+
-- end library merge
-own = { } -- not local, might change
+-- We need this hack till luatex is fixed.
+--
+-- for k,v in pairs(arg) do print(k,v) end
+
+if arg and (arg[0] == 'luatex' or arg[0] == 'luatex.exe') and arg[1] == "--luaonly" then
+ arg[-1]=arg[0] arg[0]=arg[2] for k=3,#arg do arg[k-2]=arg[k] end arg[#arg]=nil arg[#arg]=nil
+end
+
+-- End of hack.
+
+local format, gsub, gmatch, match, find = string.format, string.gsub, string.gmatch, string.match, string.find
+local concat = table.concat
+
+local ownname = environment and environment.ownname or arg[0] or 'mtxrun.lua'
+local ownpath = gsub(match(ownname,"^(.+)[\\/].-$") or ".","\\","/")
+local owntree = environment and environment.ownpath or ownpath
-own.libs = { -- order can be made better
+local ownlibs = { -- order can be made better
+ 'l-lua.lua',
+ 'l-lpeg.lua',
+ 'l-function.lua',
'l-string.lua',
'l-table.lua',
- 'l-lpeg.lua',
'l-io.lua',
'l-number.lua',
'l-set.lua',
@@ -15758,19 +15814,23 @@ own.libs = { -- order can be made better
'l-unicode.lua',
'l-math.lua',
+ 'util-str.lua', -- code might move to l-string
'util-tab.lua',
'util-sto.lua',
- 'util-mrg.lua',
- 'util-lua.lua',
'util-prs.lua',
'util-fmt.lua',
- 'util-deb.lua',
- 'trac-inf.lua',
'trac-set.lua',
'trac-log.lua',
- 'trac-pro.lua',
+ 'trac-inf.lua', -- was before trac-set
+ 'trac-pro.lua', -- not really needed
+ 'util-lua.lua', -- indeed here?
+ 'util-deb.lua',
+
+ 'util-mrg.lua',
+ 'util-tpl.lua',
+ 'util-env.lua',
'luat-env.lua', -- can come before inf (as in mkiv)
'lxml-tab.lua',
@@ -15780,6 +15840,8 @@ own.libs = { -- order can be made better
'lxml-aux.lua',
'lxml-xml.lua',
+ 'trac-xml.lua',
+
'data-ini.lua',
'data-exp.lua',
'data-env.lua',
@@ -15796,35 +15858,20 @@ own.libs = { -- order can be made better
-- 'data-bin.lua',
'data-zip.lua',
'data-tre.lua',
- 'data-crl.lua',
+ 'data-sch.lua',
'data-lua.lua',
'data-aux.lua', -- updater
'data-tmf.lua',
'data-lst.lua',
+ 'util-lib.lua', -- swiglib
+
'luat-sta.lua',
'luat-fmt.lua',
-}
-
--- We need this hack till luatex is fixed.
---
--- for k,v in pairs(arg) do print(k,v) end
-
-if arg and (arg[0] == 'luatex' or arg[0] == 'luatex.exe') and arg[1] == "--luaonly" then
- arg[-1]=arg[0] arg[0]=arg[2] for k=3,#arg do arg[k-2]=arg[k] end arg[#arg]=nil arg[#arg]=nil
-end
--- End of hack.
-
-local format, gsub, gmatch, match, find = string.format, string.gsub, string.gmatch, string.match, string.find
-local concat = table.concat
-
-own.name = (environment and environment.ownname) or arg[0] or 'mtxrun.lua'
-own.path = gsub(match(own.name,"^(.+)[\\/].-$") or ".","\\","/")
-
-local ownpath, owntree = own.path, environment and environment.ownpath or own.path
+}
-own.list = {
+local ownlist = {
'.',
ownpath ,
ownpath .. "/../sources", -- HH's development path
@@ -15838,13 +15885,21 @@ own.list = {
owntree .. "/../../../texmf/tex/context/base",
}
-if own.path == "." then table.remove(own.list,1) end
+if ownpath == "." then table.remove(ownlist,1) end
+
+own = {
+ name = ownname,
+ path = ownpath,
+ tree = owntree,
+ list = ownlist,
+ libs = ownlibs,
+}
local function locate_libs()
- for l=1,#own.libs do
- local lib = own.libs[l]
- for p =1,#own.list do
- local pth = own.list[p]
+ for l=1,#ownlibs do
+ local lib = ownlibs[l]
+ for p =1,#ownlist do
+ local pth = ownlist[p]
local filename = pth .. "/" .. lib
local found = lfs.isfile(filename)
if found then
@@ -15858,8 +15913,8 @@ end
local function load_libs()
local found = locate_libs()
if found then
- for l=1,#own.libs do
- local filename = found .. "/" .. own.libs[l]
+ for l=1,#ownlibs do
+ local filename = found .. "/" .. ownlibs[l]
local codeblob = loadfile(filename)
if codeblob then
codeblob()
@@ -15933,55 +15988,85 @@ if not environment.experiments then environment.experiments = e_experiments end
local instance = resolvers.reset()
local helpinfo = [[
---script run an mtx script (lua prefered method) (--noquotes), no script gives list
---execute run a script or program (texmfstart method) (--noquotes)
---resolve resolve prefixed arguments
---ctxlua run internally (using preloaded libs)
---internal run script using built in libraries (same as --ctxlua)
---locate locate given filename in database (default) or system (--first --all --detail)
-
---autotree use texmf tree cf. env 'texmfstart_tree' or 'texmfstarttree'
---tree=pathtotree use given texmf tree (default file: 'setuptex.tmf')
---environment=name use given (tmf) environment file
---path=runpath go to given path before execution
---ifchanged=filename only execute when given file has changed (md checksum)
---iftouched=old,new only execute when given file has changed (time stamp)
-
---makestubs create stubs for (context related) scripts
---removestubs remove stubs (context related) scripts
---stubpath=binpath paths where stubs wil be written
---windows create windows (mswin) stubs
---unix create unix (linux) stubs
-
---verbose give a bit more info
---trackers=list enable given trackers
---progname=str format or backend
-
---edit launch editor with found file
---launch (--all) launch files like manuals, assumes os support
-
---timedrun run a script an time its run
---autogenerate regenerate databases if needed (handy when used to run context in an editor)
-
---usekpse use kpse as fallback (when no mkiv and cache installed, often slower)
---forcekpse force using kpse (handy when no mkiv and cache installed but less functionality)
-
---prefixes show supported prefixes
-
---generate generate file database
-
---variables show configuration variables
---configurations show configuration order
-
---expand-braces expand complex variable
---expand-path expand variable (resolve paths)
---expand-var expand variable (resolve references)
---show-path show path expansion of ...
---var-value report value of variable
---find-file report file location
---find-path report path of file
-
---pattern=str filter variables
+
+
+
+ mtxrun
+ ConTeXt TDS Runner Tool
+ 1.31
+
+
+
+
+ run an mtx script (lua prefered method) (), no script gives list
+ run a script or program (texmfstart method) ()
+ resolve prefixed arguments
+ run internally (using preloaded libs)
+ run script using built in libraries (same as )
+ locate given filename in database (default) or system ( )
+
+
+ use texmf tree cf. env texmfstart_tree or texmfstarttree
+ use given texmf tree (default file: setuptex.tmf)
+ use given (tmf) environment file
+ go to given path before execution
+ only execute when given file has changed (md checksum)
+ only execute when given file has changed (time stamp)
+
+
+ create stubs for (context related) scripts
+ remove stubs (context related) scripts
+ paths where stubs wil be written
+ create windows (mswin) stubs
+ create unix (linux) stubs
+
+
+ give a bit more info
+ enable given trackers
+ format or backend
+
+
+ launch editor with found file
+ launch files like manuals, assumes os support ()
+
+
+ run a script and time its run
+ regenerate databases if needed (handy when used to run context in an editor)
+
+
+ use kpse as fallback (when no mkiv and cache installed, often slower)
+ force using kpse (handy when no mkiv and cache installed but less functionality)
+
+
+ show supported prefixes
+
+
+ generate file database
+
+
+ show configuration variables
+ show configuration order
+
+
+ show (known) directives
+ show (known) trackers
+ show (known) experiments
+
+
+ expand complex variable
+ expand variable (resolve paths)
+ expand variable (resolve references)
+ show path expansion of ...
+ report value of variable
+ report file location
+ report path of file
+
+
+ filter variables
+
+
+
+
]]
local application = logs.application {
@@ -16093,7 +16178,8 @@ function runners.execute_script(fullname,internal,nosplit)
elseif state == 'skip' then
return true
elseif state == "run" then
- local path, name, suffix, result = file.dirname(fullname), file.basename(fullname), file.extname(fullname), ""
+ local path, name, suffix = file.splitname(fullname)
+ local result = ""
if path ~= "" then
result = fullname
elseif name then
@@ -16104,7 +16190,7 @@ function runners.execute_script(fullname,internal,nosplit)
name = gsub(name,"^script:","")
if suffix == "" and runners.registered[name] and runners.registered[name][1] then
name = runners.registered[name][1]
- suffix = file.extname(name)
+ suffix = file.suffix(name)
end
if suffix == "" then
-- loop over known suffixes
@@ -16131,7 +16217,7 @@ function runners.execute_script(fullname,internal,nosplit)
environment.ownscript = result
dofile(result)
else
- local binary = runners.applications[file.extname(result)]
+ local binary = runners.applications[file.suffix(result)]
result = string.quoted(string.unquoted(result))
-- if string.match(result,' ') and not string.match(result,"^\".*\"$") then
-- result = '"' .. result .. '"'
@@ -16324,7 +16410,7 @@ function resolvers.launch(str)
-- maybe we also need to test on mtxrun.launcher.suffix environment
-- variable or on windows consult the assoc and ftype vars and such
local launchers = runners.launchers[os.platform] if launchers then
- local suffix = file.extname(str) if suffix then
+ local suffix = file.suffix(str) if suffix then
local runner = launchers[suffix] if runner then
str = runner .. " " .. str
end
@@ -16383,7 +16469,7 @@ function runners.find_mtx_script(filename)
end
filename = file.addsuffix(filename,"lua")
local basename = file.removesuffix(file.basename(filename))
- local suffix = file.extname(filename)
+ local suffix = file.suffix(filename)
-- qualified path, raw name
local fullname = file.is_qualified_path(filename) and io.exists(filename) and filename
if fullname and fullname ~= "" then
@@ -16438,7 +16524,7 @@ function runners.execute_ctx_script(filename,...)
runners.register_arguments(...)
local arguments = environment.arguments_after
local fullname = runners.find_mtx_script(filename) or ""
- if file.extname(fullname) == "cld" then
+ if file.suffix(fullname) == "cld" then
-- handy in editors where we force --autopdf
report("running cld script: %s",filename)
table.insert(arguments,1,fullname)
@@ -16546,6 +16632,21 @@ function runners.timed(action)
statistics.timed(action)
end
+function runners.associate(filename)
+ os.launch(filename)
+end
+
+function runners.gethelp(filename)
+ local url = environment.argument("url")
+ if url and url ~= "" then
+ local command = string.gsub(environment.argument("command") or "unknown","^%s*\\*(.-)%s*$","%1")
+ url = utilities.templates.replace(url,{ command = command })
+ os.launch(url)
+ else
+ report("no --url given")
+ end
+end
+
-- this is a bit dirty ... first we store the first filename and next we
-- split the arguments so that we only see the ones meant for this script
-- ... later we will use the second half
@@ -16647,8 +16748,18 @@ else
end
+if e_argument("script") or e_argument("scripts") then
+
+ -- run a script by loading it (using libs), pass args
+
+ runners.loadbase()
+ if is_mkii_stub then
+ ok = runners.execute_script(filename,false,true)
+ else
+ ok = runners.execute_ctx_script(filename)
+ end
-if e_argument("selfmerge") then
+elseif e_argument("selfmerge") then
-- embed used libraries
@@ -16678,17 +16789,6 @@ elseif e_argument("ctxlua") or e_argument("internal") then
runners.loadbase()
ok = runners.execute_script(filename,true)
-elseif e_argument("script") or e_argument("scripts") then
-
- -- run a script by loading it (using libs), pass args
-
- runners.loadbase()
- if is_mkii_stub then
- ok = runners.execute_script(filename,false,true)
- else
- ok = runners.execute_ctx_script(filename)
- end
-
elseif e_argument("execute") then
-- execute script
@@ -16715,6 +16815,14 @@ elseif e_argument("launch") then
runners.loadbase()
runners.launch_file(filename)
+elseif e_argument("associate") then
+
+ runners.associate(filename)
+
+elseif e_argument("gethelp") then
+
+ runners.gethelp()
+
elseif e_argument("makestubs") then
-- make stubs (depricated)
@@ -16806,7 +16914,7 @@ elseif e_argument("find-path") then
elseif e_argument("expand-braces") then
- -- luatools: runners.execute_ctx_script("mtx-base","--expand-braces",filename
+ -- luatools: runners.execute_ctx_script("mtx-base","--expand-braces",filename)
resolvers.load("nofiles")
runners.register_arguments(filename)
@@ -16908,6 +17016,23 @@ elseif e_argument("version") then
application.version()
+elseif e_argument("directives") then
+
+ directives.show()
+
+elseif e_argument("trackers") then
+
+ trackers.show()
+
+elseif e_argument("experiments") then
+
+ experiments.show()
+
+elseif e_argument("exporthelp") then
+
+ runners.loadbase()
+ application.export(e_argument("exporthelp"),filename)
+
elseif e_argument("help") or filename=='help' or filename == "" then
application.help()
@@ -16938,7 +17063,6 @@ elseif environment.files[1] == 'texmfcnf.lua' then -- so that we don't need to l
resolvers.listers.configurations()
else
-
runners.loadbase()
runners.execute_ctx_script("mtx-base",filename)
@@ -16955,4 +17079,4 @@ end
if ok == false then ok = 1 elseif ok == true then ok = 0 end
-os.exit(ok)
+os.exit(ok,true) -- true forces a cleanup in 5.2+
diff --git a/Master/texmf-dist/scripts/context/ruby/base/logger.rb b/Master/texmf-dist/scripts/context/ruby/base/logger.rb
index 2526cdb0e25..2245ab331f0 100644
--- a/Master/texmf-dist/scripts/context/ruby/base/logger.rb
+++ b/Master/texmf-dist/scripts/context/ruby/base/logger.rb
@@ -47,7 +47,8 @@ class Logger
print("\n")
return true
when 1
- message = str.first
+ # message = str.first
+ message = str.first.join(' ')
else
message = [str].flatten.collect{|s| s.to_s}.join(' ').chomp
end
diff --git a/Master/texmf-dist/scripts/context/ruby/base/tex.rb b/Master/texmf-dist/scripts/context/ruby/base/tex.rb
index 8f56839851c..9ba842501ea 100644
--- a/Master/texmf-dist/scripts/context/ruby/base/tex.rb
+++ b/Master/texmf-dist/scripts/context/ruby/base/tex.rb
@@ -362,7 +362,8 @@ class TEX
def mpsformats() @@mpsformats.keys.sort end
def defaulttexformats() ['en','nl','mptopdf'] end
- def defaultmpsformats() ['metafun'] end
+ # def defaultmpsformats() ['metafun'] end # no longer formats
+ def defaultmpsformats() [] end
def texmakeextras(format) @@texmakestr[format] || '' end
def mpsmakeextras(format) @@mpsmakestr[format] || '' end
diff --git a/Master/texmf-dist/scripts/context/ruby/fcd_start.rb b/Master/texmf-dist/scripts/context/ruby/fcd_start.rb
deleted file mode 100644
index 3d04754fac9..00000000000
--- a/Master/texmf-dist/scripts/context/ruby/fcd_start.rb
+++ /dev/null
@@ -1,472 +0,0 @@
-# Hans Hagen / PRAGMA ADE / 2005 / www.pragma-ade.com
-#
-# Fast Change Dir
-#
-# This is a kind of variant of the good old ncd
-# program. This script uses the same indirect cmd
-# trick as Erwin Waterlander's wcd program.
-#
-# === windows: fcd.cmd ===
-#
-# @echo off
-# ruby -S fcd_start.rb %1 %2 %3 %4 %5 %6 %7 %8 %9
-# if exist "%HOME%/fcd_stage.cmd" call %HOME%/fcd_stage.cmd
-#
-# === linux: fcd (fcd.sh) ===
-#
-# !/usr/bin/env sh
-# ruby -S fcd_start.rb $1 $2 $3 $4 $5 $6 $7 $8 $9
-# if test -f "$HOME/fcd_stage.sh" ; then
-# . $HOME/fcd_stage.sh ;
-# fi;
-#
-# ===
-#
-# On linux, one should source the file: ". fcd args" in order
-# to make the chdir persistent.
-#
-# You can create a stub with:
-#
-# ruby fcd_start.rb --stub --verbose
-#
-# usage:
-#
-# fcd --make t:\
-# fcd --add f:\project
-# fcd [--find] whatever
-# fcd [--find] whatever c (c being a list entry)
-# fcd [--find] whatever . (last choice with this pattern)
-# fcd --list
-
-# todo: HOMEDRIVE\HOMEPATH
-
-require 'rbconfig'
-
-class FastCD
-
- @@rootpath = nil
-
- ['HOME','TEMP','TMP','TMPDIR'].each do |key|
- if ENV[key] then
- if FileTest.directory?(ENV[key]) then
- @@rootpath = ENV[key]
- break
- end
- end
- end
-
- exit unless @@rootpath
-
- @@mswindows = RbConfig::CONFIG['host_os'] =~ /mswin/
- @@maxlength = 26
-
- require 'Win32API' if @@mswindows
-
- if @@mswindows then
- @@stubcode = [
- '@echo off',
- '',
- 'if not exist "%HOME%" goto temp',
- '',
- ':home',
- '',
- 'ruby -S fcd_start.rb %1 %2 %3 %4 %5 %6 %7 %8 %9',
- '',
- 'if exist "%HOME%\fcd_stage.cmd" call %HOME%\fcd_stage.cmd',
- 'goto end',
- '',
- ':temp',
- '',
- 'ruby -S fcd_start.rb %1 %2 %3 %4 %5 %6 %7 %8 %9',
- '',
- 'if exist "%TEMP%\fcd_stage.cmd" call %TEMP%\fcd_stage.cmd',
- 'goto end',
- '',
- ':end'
- ].join("\n")
- else
- @@stubcode = [
- '#!/usr/bin/env sh',
- '',
- 'ruby -S fcd_start.rb $1 $2 $3 $4 $5 $6 $7 $8 $9',
- '',
- 'if test -f "$HOME/fcd_stage.sh" ; then',
- ' . $HOME/fcd_stage.sh ;',
- 'fi;'
- ].join("\n")
- end
-
- @@selfpath = File.dirname($0)
- @@datafile = File.join(@@rootpath,'fcd_state.dat')
- @@histfile = File.join(@@rootpath,'fcd_state.his')
- @@cdirfile = File.join(@@rootpath,if @@mswindows then 'fcd_stage.cmd' else 'fcd_stage.sh' end)
- @@stubfile = File.join(@@selfpath,if @@mswindows then 'fcd.cmd' else 'fcd' end)
-
- def initialize(verbose=false)
- @list = Array.new
- @hist = Hash.new
- @result = Array.new
- @pattern = ''
- @result = ''
- @verbose = verbose
- if f = File.open(@@cdirfile,'w') then
- f << "#{if @@mswindows then 'rem' else '#' end} no dir to change to"
- f.close
- else
- report("unable to create stub #{@@cdirfile}")
- end
- end
-
- def filename(name)
- File.join(@@root,name)
- end
-
- def report(str,verbose=@verbose)
- puts(">> #{str}") if verbose
- end
-
- def flush(str,verbose=@verbose)
- print(str) if verbose
- end
-
- def clear
- if FileTest.file?(@@histfile)
- begin
- File.delete(@@histfile)
- rescue
- report("error in deleting history file '#{@histfile}'")
- else
- report("history file '#{@histfile}' is deleted")
- end
- else
- report("no history file '#{@histfile}'")
- end
- end
-
- def scan(dir='.')
- begin
- [dir].flatten.sort.uniq.each do |dir|
- begin
- Dir.chdir(dir)
- report("scanning '#{dir}'")
- # flush(">> ")
- Dir.glob("**/*").each do |d|
- if FileTest.directory?(d) then
- @list << File.expand_path(d)
- # flush(".")
- end
- end
- # flush("\n")
- @list = @list.sort.uniq
- report("#{@list.size} entries found")
- rescue
- report("unknown directory '#{dir}'")
- end
- end
- rescue
- report("invalid dir specification ")
- end
- end
-
- def save
- begin
- if f = File.open(@@datafile,'w') then
- @list.each do |l|
- f.puts(l)
- end
- f.close
- report("#{@list.size} status bytes saved in #{@@datafile}")
- else
- report("unable to save status in #{@@datafile}")
- end
- rescue
- report("error in saving status in #{@@datafile}")
- end
- end
-
- def remember
- if @hist[@pattern] == @result then
- # no need to save result
- else
- begin
- if f = File.open(@@histfile,'w') then
- @hist[@pattern] = @result
- @hist.keys.each do |k|
- f.puts("#{k} #{@hist[k]}")
- end
- f.close
- report("#{@hist.size} history entries saved in #{@@histfile}")
- else
- report("unable to save history in #{@@histfile}")
- end
- rescue
- report("error in saving history in #{@@histfile}")
- end
- end
- end
-
- def load
- begin
- @list = IO.read(@@datafile).split("\n")
- report("#{@list.length} status bytes loaded from #{@@datafile}")
- rescue
- report("error in loading status from #{@@datafile}")
- end
- begin
- IO.readlines(@@histfile).each do |line|
- if line =~ /^(.*?)\s+(.*)$/i then
- @hist[$1] = $2
- end
- end
- report("#{@hist.length} history entries loaded from #{@@histfile}")
- rescue
- report("error in loading history from #{@@histfile}")
- end
- end
-
- def show
- begin
- puts("directories:")
- puts("\n")
- if @list.length > 0 then
- @list.each do |l|
- puts(l)
- end
- else
- puts("no entries")
- end
- puts("\n")
- puts("history:")
- puts("\n")
- if @hist.length > 0 then
- @hist.keys.sort.each do |h|
- puts("#{h} >> #{@hist[h]}")
- end
- else
- puts("no entries")
- end
- rescue
- end
- end
-
- def find(pattern=nil)
- begin
- if pattern = [pattern].flatten.first then
- if pattern.length > 0 and @pattern = pattern then
- @result = @list.grep(/\/#{@pattern}$/i)
- if @result.length == 0 then
- @result = @list.grep(/\/#{@pattern}[^\/]*$/i)
- end
- end
- else
- puts(Dir.pwd.gsub(/\\/o, '/'))
- end
- rescue
- puts("some error")
- end
- end
-
- def chdir(dir)
- begin
- if dir then
- if f = File.open(@@cdirfile,'w') then
- if @@mswindows then
- f.puts("cd /d #{dir.gsub('/','\\')}")
- else
- f.puts("cd #{dir.gsub("\\",'/')}")
- end
- f.close
- end
- @result = dir
- report("changing to #{dir}",true)
- else
- report("not changing dir")
- end
- rescue
- end
- end
-
- def choose(args=[])
- offset = 97
- unless @pattern.empty? then
- begin
- case @result.size
- when 0 then
- report("dir '#{@pattern}' not found",true)
- when 1 then
- chdir(@result[0])
- else
- list = @result.dup
- begin
- if answer = args[1] then # assignment & test
- if answer == '.' and @hist.key?(@pattern) then
- if FileTest.directory?(@hist[@pattern]) then
- print("last choice ")
- chdir(@hist[@pattern])
- return
- end
- else
- index = answer[0] - offset
- if dir = list[index] then
- chdir(dir)
- return
- end
- end
- end
- rescue
- puts("some error")
- end
- loop do
- print("\n")
- list.each_index do |i|
-begin
- if i < @@maxlength then
- # puts("#{(i+?a).chr} #{list[i]}")
- puts("#{(i+offset).chr} #{list[i]}")
- else
- puts("\n there are #{list.length-@@maxlength} entries more")
- break
- end
-rescue
- puts("some error")
-end
- end
- print("\n>> ")
- if answer = wait then
- if answer >= offset and answer <= offset+25 then
- index = answer - offset
- if dir = list[index] then
- print("#{answer.chr} ")
- chdir(dir)
- elsif @hist.key?(@pattern) and FileTest.directory?(@hist[@pattern]) then
- print("last choice ")
- chdir(@hist[@pattern])
- else
- print("quit\n")
- end
- break
- elsif list.length >= @@maxlength then
- @@maxlength.times do |i| list.shift end
- print("next set")
- print("\n")
- elsif @hist.key?(@pattern) and FileTest.directory?(@hist[@pattern]) then
- print("last choice ")
- chdir(@hist[@pattern])
- break
- else
- print("quit\n")
- break
- end
- end
- end
- end
- rescue
- report($!)
- end
- end
- end
-
- def wait
- begin
- $stdout.flush
- return getc
- rescue
- return nil
- end
- end
-
- def getc
- begin
- if @@mswindows then
- ch = Win32API.new('crtdll','_getch',[],'L').call
- else
- system('stty raw -echo')
- ch = $stdin.getc
- system('stty -raw echo')
- end
- rescue
- ch = nil
- end
- return ch
- end
-
- def check
- unless FileTest.file?(@@stubfile) then
- report("creating stub #{@@stubfile}")
- begin
- if f = File.open(@@stubfile,'w') then
- f.puts(@@stubcode)
- f.close
- end
- rescue
- report("unable to create stub #{@@stubfile}")
- else
- unless @mswindows then
- begin
- File.chmod(0755,@@stubfile)
- rescue
- report("unable to change protections on #{@@stubfile}")
- end
- end
- end
- else
- report("stub #{@@stubfile} already present")
- end
- end
-
-end
-
-$stdout.sync = true
-
-verbose, action, args = false, :find, Array.new
-
-usage = "fcd [--add|clear|find|list|make|show|stub] [--verbose] [pattern]"
-version = "1.0.2"
-
-def quit(message)
- puts(message)
- exit
-end
-
-ARGV.each do |a|
- case a
- when '-a', '--add' then action = :add
- when '-c', '--clear' then action = :clear
- when '-f', '--find' then action = :find
- when '-l', '--list' then action = :show
- when '-m', '--make' then action = :make
- when '-s', '--show' then action = :show
- when '--stub' then action = :stub
- when '-v', '--verbose' then verbose = true
- when '--version' then quit("version: #{version}")
- when '-h', '--help' then quit("usage: #{usage}")
- when /^\-\-.*/ then quit("error: unknown switch #{a}, try --help")
- else args << a
- end
-end
-
-fcd = FastCD.new(verbose)
-fcd.report("Fast Change Dir / version #{version}")
-
-case action
- when :make then
- fcd.clear
- fcd.scan(args)
- fcd.save
- when :clear then
- fcd.clear
- when :add then
- fcd.load
- fcd.scan(args)
- fcd.save
- when :show then
- fcd.load
- fcd.show
- when :find then
- fcd.load
- fcd.find(args)
- fcd.choose(args)
- fcd.remember
- when :stub
- fcd.check
-end
diff --git a/Master/texmf-dist/scripts/context/ruby/mpstools.rb b/Master/texmf-dist/scripts/context/ruby/mpstools.rb
deleted file mode 100644
index 534bfb95bcf..00000000000
--- a/Master/texmf-dist/scripts/context/ruby/mpstools.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-# todo
-#
-# this script will replace mptopdf and makempy
-
-puts("This program is yet unfinished, for the moment it just calls 'mptopdf'.\n\n")
-
-system("texmfstart mptopdf #{ARGV.join(' ')}")
diff --git a/Master/texmf-dist/scripts/context/ruby/texexec.rb b/Master/texmf-dist/scripts/context/ruby/texexec.rb
index 32c9d0ca538..c673cb46b17 100644
--- a/Master/texmf-dist/scripts/context/ruby/texexec.rb
+++ b/Master/texmf-dist/scripts/context/ruby/texexec.rb
@@ -733,7 +733,7 @@ class Commands
else
n += 1
end
- r << ' ' + s
+ r << ' ' + s.to_s
end
report(r) unless r.empty?
end
diff --git a/Master/texmf-dist/scripts/context/ruby/texsync.rb b/Master/texmf-dist/scripts/context/ruby/texsync.rb
deleted file mode 100644
index fd6593f05fb..00000000000
--- a/Master/texmf-dist/scripts/context/ruby/texsync.rb
+++ /dev/null
@@ -1,206 +0,0 @@
-#!/usr/bin/env ruby
-
-# program : texsync
-# copyright : PRAGMA Advanced Document Engineering
-# version : 2003-2005
-# author : Hans Hagen
-#
-# project : ConTeXt / eXaMpLe
-# concept : Hans Hagen
-# info : j.hagen@xs4all.nl
-# www : www.pragma-ade.com
-
-# For the moment this script only handles the 'minimal' context
-# distribution. In due time I will add a few more options, like
-# synchronization of the iso image.
-
-# taco's sync: rsync -au -v rsync://www.pragma-ade.com/all ./htdocs
-
-banner = ['TeXSync', 'version 1.1.1', '2002/2004', 'PRAGMA ADE/POD']
-
-$: << File.expand_path(File.dirname($0)) ; $: << File.join($:.last,'lib') ; $:.uniq!
-
-require 'base/switch'
-require 'base/logger'
-# require 'base/tool'
-
-require 'rbconfig'
-
-class Commands
-
- include CommandBase
-
- @@formats = ['en','nl','de','cz','it','ro', 'fr']
- @@always = ['metafun','mptopdf','en','nl']
- @@rsync = 'rsync -r -z -c --progress --stats "--exclude=*.fmt" "--exclude=*.efmt" "--exclude=*.mem"'
-
- @@kpsewhich = Hash.new
-
- @@kpsewhich['minimal'] = 'SELFAUTOPARENT'
- @@kpsewhich['context'] = 'TEXMFLOCAL'
- @@kpsewhich['documentation'] = 'TEXMFLOCAL'
- @@kpsewhich['unknown'] = 'SELFAUTOPARENT'
-
- def update
-
- report
-
- return unless destination = getdestination
-
- texpaths = gettexpaths
- address = option('address')
- user = option('user')
- tree = option('tree')
- force = option('force')
-
- ok = true
- begin
- report("synchronizing '#{tree}' from '#{address}' to '#{destination}'")
- report
- if texpaths then
- texpaths.each do |path|
- report("synchronizing path '#{path}' of '#{tree}' from '#{address}' to '#{destination}'")
- command = "#{rsync} #{user}@#{address}::#{tree}/#{path} #{destination}/{path}"
- ok = ok && system(command) if force
- end
- else
- command = "#{@@rsync} #{user}@#{address}::#{tree} #{destination}"
- ok = system(command) if force
- end
- rescue
- report("error in running rsync")
- ok = false
- ensure
- if force then
- if ok then
- if option('make') then
- report("generating tex and metapost formats")
- report
- @@formats.delete_if do |f|
- begin
- `kpsewhich cont-#{f}`.chomp.empty?
- rescue
- end
- end
- str = [@@formats,@@always].flatten.uniq.join(' ')
- begin
- system("texexec --make --alone #{str}")
- rescue
- report("unable to generate formats '#{str}'")
- else
- report
- end
- else
- report("regenerate the formats files if needed")
- end
- else
- report("error in synchronizing '#{tree}'")
- end
- else
- report("provide --force to execute '#{command}'") unless force
- end
- end
-
- end
-
- def list
-
- report
-
- address = option('address')
- user = option('user')
- result = nil
-
- begin
- report("fetching list of trees from '#{address}'")
- command = "#{@@rsync} #{user}@#{address}::"
- if option('force') then
- result = `#{command}`.chomp
- else
- report("provide --force to execute '#{command}'")
- end
- rescue
- result = nil
- else
- if result then
- report("available trees:")
- report
- reportlines(result)
- end
- ensure
- report("unable to fetch list") unless result
- end
-
- end
-
- private
-
- def gettexpaths
- if option('full') then
- texpaths = ['texmf','texmf-local','texmf-fonts','texmf-mswin','texmf-linux','texmf-macos']
- elsif option('terse') then
- texpaths = ['texmf','texmf-local','texmf-fonts']
- case RbConfig::CONFIG['host_os'] # or: Tool.ruby_platform
- when /mswin/ then texpaths.push('texmf-mswin')
- when /linux/ then texpaths.push('texmf-linux')
- when /darwin/ then texpaths.push('texmf-macosx')
- end
- else
- texpaths = nil
- end
- texpaths
- end
-
- def getdestination
- if (destination = option('destination')) && ! destination.empty? then
- begin
- if @@kpsewhich.key?(destination) then
- destination = @@kpsewhich[option('tree')] || @@kpsewhich['unknown']
- destination = `kpsewhich --expand-var=$#{destination}`.chomp
- elsif ! FileTest.directory?(destination) then
- destination = nil
- end
- rescue
- report("unable to determine destination tex root")
- else
- if ! destination || destination.empty? then
- report("no destination is specified")
- elsif not FileTest.directory?(destination) then
- report("invalid destination '#{destination}'")
- elsif not FileTest.writable?(destination) then
- report("destination '#{destination}' is not writable")
- else
- report("using destination '#{destination}'")
- return destination
- end
- end
- else
- report("unknown destination")
- end
- return nil
- end
-
-end
-
-logger = Logger.new(banner.shift)
-commandline = CommandLine.new
-
-commandline.registeraction('update', 'update installed tree')
-commandline.registeraction('list', 'list available trees')
-
-commandline.registerflag('terse', 'download as less as possible (esp binaries)')
-commandline.registerflag('full', 'download everything (all binaries)')
-commandline.registerflag('force', 'confirm action')
-commandline.registerflag('make', 'remake formats')
-
-commandline.registervalue('address', 'www.pragma-ade.com', 'adress of repository (www.pragma-ade)')
-commandline.registervalue('user', 'guest', 'user account (guest)')
-commandline.registervalue('tree', 'tex', 'tree to synchronize (tex)')
-commandline.registervalue('destination', nil, 'destination of tree (kpsewhich)')
-
-commandline.registeraction('help')
-commandline.registeraction('version')
-
-commandline.expand
-
-Commands.new(commandline,logger,banner).send(commandline.action || 'help')
diff --git a/Master/texmf-dist/scripts/context/stubs/mswin/ctxtools.exe b/Master/texmf-dist/scripts/context/stubs/mswin/ctxtools.exe
new file mode 100755
index 00000000000..2d45f27494d
Binary files /dev/null and b/Master/texmf-dist/scripts/context/stubs/mswin/ctxtools.exe differ
diff --git a/Master/texmf-dist/scripts/context/stubs/mswin/mptopdf.exe b/Master/texmf-dist/scripts/context/stubs/mswin/mptopdf.exe
deleted file mode 100755
index 2d45f27494d..00000000000
Binary files a/Master/texmf-dist/scripts/context/stubs/mswin/mptopdf.exe and /dev/null differ
diff --git a/Master/texmf-dist/scripts/context/stubs/mswin/mtxrun.dll b/Master/texmf-dist/scripts/context/stubs/mswin/mtxrun.dll
index 4116c5a24a6..6ba2597d56f 100755
Binary files a/Master/texmf-dist/scripts/context/stubs/mswin/mtxrun.dll and b/Master/texmf-dist/scripts/context/stubs/mswin/mtxrun.dll differ
diff --git a/Master/texmf-dist/scripts/context/stubs/mswin/mtxrun.exe b/Master/texmf-dist/scripts/context/stubs/mswin/mtxrun.exe
index 745eaf22464..acd99ddbf3b 100755
Binary files a/Master/texmf-dist/scripts/context/stubs/mswin/mtxrun.exe and b/Master/texmf-dist/scripts/context/stubs/mswin/mtxrun.exe differ
diff --git a/Master/texmf-dist/scripts/context/stubs/mswin/mtxrun.lua b/Master/texmf-dist/scripts/context/stubs/mswin/mtxrun.lua
index 108f2a8a112..00f63a5791d 100644
--- a/Master/texmf-dist/scripts/context/stubs/mswin/mtxrun.lua
+++ b/Master/texmf-dist/scripts/context/stubs/mswin/mtxrun.lua
@@ -1,5 +1,16 @@
#!/usr/bin/env texlua
+-- for k, v in next, _G.string do
+-- local tv = type(v)
+-- if tv == "table" then
+-- for kk, vv in next, v do
+-- print(k,kk,vv)
+-- end
+-- else
+-- print(tv,k,v)
+-- end
+-- end
+
if not modules then modules = { } end modules ['mtxrun'] = {
version = 1.001,
comment = "runner, lua replacement for texmfstart.rb",
@@ -43,3016 +54,7333 @@ if not modules then modules = { } end modules ['mtxrun'] = {
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-string'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
+package.loaded["l-lua"] = package.loaded["l-lua"] or true
+
+-- original size: 10048, stripped down to: 5684
+
+if not modules then modules={} end modules ['l-lua']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local major,minor=string.match(_VERSION,"^[^%d]+(%d+)%.(%d+).*$")
+_MAJORVERSION=tonumber(major) or 5
+_MINORVERSION=tonumber(minor) or 1
+_LUAVERSION=_MAJORVERSION+_MINORVERSION/10
+if not lpeg then
+ lpeg=require("lpeg")
+end
+if loadstring then
+ local loadnormal=load
+ function load(first,...)
+ if type(first)=="string" then
+ return loadstring(first,...)
+ else
+ return loadnormal(first,...)
+ end
+ end
+else
+ loadstring=load
+end
+if not ipairs then
+ local function iterate(a,i)
+ i=i+1
+ local v=a[i]
+ if v~=nil then
+ return i,v
+ end
+ end
+ function ipairs(a)
+ return iterate,a,0
+ end
+end
+if not pairs then
+ function pairs(t)
+ return next,t
+ end
+end
+if not table.unpack then
+ table.unpack=_G.unpack
+elseif not unpack then
+ _G.unpack=table.unpack
+end
+if not package.loaders then
+ package.loaders=package.searchers
+end
+local print,select,tostring=print,select,tostring
+local inspectors={}
+function setinspector(inspector)
+ inspectors[#inspectors+1]=inspector
+end
+function inspect(...)
+ for s=1,select("#",...) do
+ local value=select(s,...)
+ local done=false
+ for i=1,#inspectors do
+ done=inspectors[i](value)
+ if done then
+ break
+ end
+ end
+ if not done then
+ print(tostring(value))
+ end
+ end
+end
+local dummy=function() end
+function optionalrequire(...)
+ local ok,result=xpcall(require,dummy,...)
+ if ok then
+ return result
+ end
+end
+local type=type
+local gsub,format=string.gsub,string.format
+local package=package
+local searchers=package.searchers or package.loaders
+local libpaths=nil
+local clibpaths=nil
+local libhash={}
+local clibhash={}
+local libextras={}
+local clibextras={}
+local filejoin=file and file.join or function(path,name) return path.."/"..name end
+local isreadable=file and file.is_readable or function(name) local f=io.open(name) if f then f:close() return true end end
+local addsuffix=file and file.addsuffix or function(name,suffix) return name.."."..suffix end
+local function cleanpath(path)
+ return path
+end
+local helpers=package.helpers or {
+ libpaths=function() return {} end,
+ clibpaths=function() return {} end,
+ cleanpath=cleanpath,
+ trace=false,
+ report=function(...) print(format(...)) end,
}
+package.helpers=helpers
+local function getlibpaths()
+ return libpaths or helpers.libpaths(libhash)
+end
+local function getclibpaths()
+ return clibpaths or helpers.clibpaths(clibhash)
+end
+package.libpaths=getlibpaths
+package.clibpaths=getclibpaths
+local function addpath(what,paths,extras,hash,...)
+ local pathlist={... }
+ local cleanpath=helpers.cleanpath
+ local trace=helpers.trace
+ local report=helpers.report
+ local function add(path)
+ local path=cleanpath(path)
+ if not hash[path] then
+ if trace then
+ report("extra %s path: %s",what,path)
+ end
+ paths [#paths+1]=path
+ extras[#extras+1]=path
+ end
+ end
+ for p=1,#pathlist do
+ local path=pathlist[p]
+ if type(path)=="table" then
+ for i=1,#path do
+ add(path[i])
+ end
+ else
+ add(path)
+ end
+ end
+ return paths,extras
+end
+function package.extralibpath(...)
+ libpaths,libextras=addpath("lua",getlibpaths(),libextras,libhash,...)
+end
+function package.extraclibpath(...)
+ clibpaths,clibextras=addpath("lib",getclibpaths(),clibextras,clibhash,...)
+end
+if not searchers[-2] then
+ searchers[-2]=searchers[2]
+end
+searchers[2]=function(name)
+ return helpers.loaded(name)
+end
+searchers[3]=nil
+local function loadedaslib(resolved,rawname)
+ local init="luaopen_"..gsub(rawname,"%.","_")
+ if helpers.trace then
+ helpers.report("calling loadlib with '%s' with init '%s'",resolved,init)
+ end
+ return package.loadlib(resolved,init)
+end
+local function loadedbylua(name)
+ if helpers.trace then
+ helpers.report("locating '%s' using normal loader",name)
+ end
+ return true,searchers[-2](name)
+end
+local function loadedbypath(name,rawname,paths,islib,what)
+ local trace=helpers.trace
+ local report=helpers.report
+ if trace then
+ report("locating '%s' as '%s' on '%s' paths",rawname,name,what)
+ end
+ for p=1,#paths do
+ local path=paths[p]
+ local resolved=filejoin(path,name)
+ if trace then
+ report("checking for '%s' using '%s' path '%s'",name,what,path)
+ end
+ if isreadable(resolved) then
+ if trace then
+ report("lib '%s' located on '%s'",name,resolved)
+ end
+ if islib then
+ return true,loadedaslib(resolved,rawname)
+ else
+ return true,loadfile(resolved)
+ end
+ end
+ end
+end
+local function notloaded(name)
+ if helpers.trace then
+ helpers.report("? unable to locate library '%s'",name)
+ end
+end
+helpers.loadedaslib=loadedaslib
+helpers.loadedbylua=loadedbylua
+helpers.loadedbypath=loadedbypath
+helpers.notloaded=notloaded
+function helpers.loaded(name)
+ local thename=gsub(name,"%.","/")
+ local luaname=addsuffix(thename,"lua")
+ local libname=addsuffix(thename,os.libsuffix or "so")
+ local libpaths=getlibpaths()
+ local clibpaths=getclibpaths()
+ local done,result=loadedbypath(luaname,name,libpaths,false,"lua")
+ if done then
+ return result
+ end
+ local done,result=loadedbypath(luaname,name,clibpaths,false,"lua")
+ if done then
+ return result
+ end
+ local done,result=loadedbypath(libname,name,clibpaths,true,"lib")
+ if done then
+ return result
+ end
+ local done,result=loadedbylua(name)
+ if done then
+ return result
+ end
+ return notloaded(name)
+end
-local string = string
-local sub, gsub, find, match, gmatch, format, char, byte, rep, lower = string.sub, string.gsub, string.find, string.match, string.gmatch, string.format, string.char, string.byte, string.rep, string.lower
-local lpegmatch, S, C, Ct = lpeg.match, lpeg.S, lpeg.C, lpeg.Ct
--- some functions may disappear as they are not used anywhere
+end -- of closure
-if not string.split then
+do -- create closure to overcome 200 locals limit
- -- this will be overloaded by a faster lpeg variant
+package.loaded["l-lpeg"] = package.loaded["l-lpeg"] or true
- function string.split(str,pattern)
- local t = { }
- if #str > 0 then
- local n = 1
- for s in gmatch(str..pattern,"(.-)"..pattern) do
- t[n] = s
- n = n + 1
- end
- end
- return t
- end
+-- original size: 26252, stripped down to: 14371
+if not modules then modules={} end modules ['l-lpeg']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+lpeg=require("lpeg")
+local type,next,tostring=type,next,tostring
+local byte,char,gmatch,format=string.byte,string.char,string.gmatch,string.format
+local floor=math.floor
+local P,R,S,V,Ct,C,Cs,Cc,Cp,Cmt=lpeg.P,lpeg.R,lpeg.S,lpeg.V,lpeg.Ct,lpeg.C,lpeg.Cs,lpeg.Cc,lpeg.Cp,lpeg.Cmt
+local lpegtype,lpegmatch,lpegprint=lpeg.type,lpeg.match,lpeg.print
+setinspector(function(v) if lpegtype(v) then lpegprint(v) return true end end)
+lpeg.patterns=lpeg.patterns or {}
+local patterns=lpeg.patterns
+local anything=P(1)
+local endofstring=P(-1)
+local alwaysmatched=P(true)
+patterns.anything=anything
+patterns.endofstring=endofstring
+patterns.beginofstring=alwaysmatched
+patterns.alwaysmatched=alwaysmatched
+local digit,sign=R('09'),S('+-')
+local cr,lf,crlf=P("\r"),P("\n"),P("\r\n")
+local newline=crlf+S("\r\n")
+local escaped=P("\\")*anything
+local squote=P("'")
+local dquote=P('"')
+local space=P(" ")
+local utfbom_32_be=P('\000\000\254\255')
+local utfbom_32_le=P('\255\254\000\000')
+local utfbom_16_be=P('\255\254')
+local utfbom_16_le=P('\254\255')
+local utfbom_8=P('\239\187\191')
+local utfbom=utfbom_32_be+utfbom_32_le+utfbom_16_be+utfbom_16_le+utfbom_8
+local utftype=utfbom_32_be*Cc("utf-32-be")+utfbom_32_le*Cc("utf-32-le")+utfbom_16_be*Cc("utf-16-be")+utfbom_16_le*Cc("utf-16-le")+utfbom_8*Cc("utf-8")+alwaysmatched*Cc("utf-8")
+local utfoffset=utfbom_32_be*Cc(4)+utfbom_32_le*Cc(4)+utfbom_16_be*Cc(2)+utfbom_16_le*Cc(2)+utfbom_8*Cc(3)+Cc(0)
+local utf8next=R("\128\191")
+patterns.utf8one=R("\000\127")
+patterns.utf8two=R("\194\223")*utf8next
+patterns.utf8three=R("\224\239")*utf8next*utf8next
+patterns.utf8four=R("\240\244")*utf8next*utf8next*utf8next
+patterns.utfbom=utfbom
+patterns.utftype=utftype
+patterns.utfoffset=utfoffset
+local utf8char=patterns.utf8one+patterns.utf8two+patterns.utf8three+patterns.utf8four
+local validutf8char=utf8char^0*endofstring*Cc(true)+Cc(false)
+local utf8character=P(1)*R("\128\191")^0
+patterns.utf8=utf8char
+patterns.utf8char=utf8char
+patterns.utf8character=utf8character
+patterns.validutf8=validutf8char
+patterns.validutf8char=validutf8char
+local eol=S("\n\r")
+local spacer=S(" \t\f\v")
+local whitespace=eol+spacer
+local nonspacer=1-spacer
+local nonwhitespace=1-whitespace
+patterns.eol=eol
+patterns.spacer=spacer
+patterns.whitespace=whitespace
+patterns.nonspacer=nonspacer
+patterns.nonwhitespace=nonwhitespace
+local stripper=spacer^0*C((spacer^0*nonspacer^1)^0)
+local collapser=Cs(spacer^0/""*nonspacer^0*((spacer^0/" "*nonspacer^1)^0))
+patterns.stripper=stripper
+patterns.collapser=collapser
+patterns.digit=digit
+patterns.sign=sign
+patterns.cardinal=sign^0*digit^1
+patterns.integer=sign^0*digit^1
+patterns.unsigned=digit^0*P('.')*digit^1
+patterns.float=sign^0*patterns.unsigned
+patterns.cunsigned=digit^0*P(',')*digit^1
+patterns.cfloat=sign^0*patterns.cunsigned
+patterns.number=patterns.float+patterns.integer
+patterns.cnumber=patterns.cfloat+patterns.integer
+patterns.oct=P("0")*R("07")^1
+patterns.octal=patterns.oct
+patterns.HEX=P("0x")*R("09","AF")^1
+patterns.hex=P("0x")*R("09","af")^1
+patterns.hexadecimal=P("0x")*R("09","AF","af")^1
+patterns.lowercase=R("az")
+patterns.uppercase=R("AZ")
+patterns.letter=patterns.lowercase+patterns.uppercase
+patterns.space=space
+patterns.tab=P("\t")
+patterns.spaceortab=patterns.space+patterns.tab
+patterns.newline=newline
+patterns.emptyline=newline^1
+patterns.equal=P("=")
+patterns.comma=P(",")
+patterns.commaspacer=P(",")*spacer^0
+patterns.period=P(".")
+patterns.colon=P(":")
+patterns.semicolon=P(";")
+patterns.underscore=P("_")
+patterns.escaped=escaped
+patterns.squote=squote
+patterns.dquote=dquote
+patterns.nosquote=(escaped+(1-squote))^0
+patterns.nodquote=(escaped+(1-dquote))^0
+patterns.unsingle=(squote/"")*patterns.nosquote*(squote/"")
+patterns.undouble=(dquote/"")*patterns.nodquote*(dquote/"")
+patterns.unquoted=patterns.undouble+patterns.unsingle
+patterns.unspacer=((patterns.spacer^1)/"")^0
+patterns.singlequoted=squote*patterns.nosquote*squote
+patterns.doublequoted=dquote*patterns.nodquote*dquote
+patterns.quoted=patterns.doublequoted+patterns.singlequoted
+patterns.propername=R("AZ","az","__")*R("09","AZ","az","__")^0*P(-1)
+patterns.somecontent=(anything-newline-space)^1
+patterns.beginline=#(1-newline)
+patterns.longtostring=Cs(whitespace^0/""*nonwhitespace^0*((whitespace^0/" "*(patterns.quoted+nonwhitespace)^1)^0))
+local function anywhere(pattern)
+ return P { P(pattern)+1*V(1) }
+end
+lpeg.anywhere=anywhere
+function lpeg.instringchecker(p)
+ p=anywhere(p)
+ return function(str)
+ return lpegmatch(p,str) and true or false
+ end
+end
+function lpeg.splitter(pattern,action)
+ return (((1-P(pattern))^1)/action+1)^0
+end
+function lpeg.tsplitter(pattern,action)
+ return Ct((((1-P(pattern))^1)/action+1)^0)
+end
+local splitters_s,splitters_m,splitters_t={},{},{}
+local function splitat(separator,single)
+ local splitter=(single and splitters_s[separator]) or splitters_m[separator]
+ if not splitter then
+ separator=P(separator)
+ local other=C((1-separator)^0)
+ if single then
+ local any=anything
+ splitter=other*(separator*C(any^0)+"")
+ splitters_s[separator]=splitter
+ else
+ splitter=other*(separator*other)^0
+ splitters_m[separator]=splitter
+ end
+ end
+ return splitter
end
-
-function string.unquoted(str)
- return (gsub(str,"^([\"\'])(.*)%1$","%2"))
+local function tsplitat(separator)
+ local splitter=splitters_t[separator]
+ if not splitter then
+ splitter=Ct(splitat(separator))
+ splitters_t[separator]=splitter
+ end
+ return splitter
+end
+lpeg.splitat=splitat
+lpeg.tsplitat=tsplitat
+function string.splitup(str,separator)
+ if not separator then
+ separator=","
+ end
+ return lpegmatch(splitters_m[separator] or splitat(separator),str)
end
-
-
-function string.quoted(str)
- return format("%q",str) -- always "
+local cache={}
+function lpeg.split(separator,str)
+ local c=cache[separator]
+ if not c then
+ c=tsplitat(separator)
+ cache[separator]=c
+ end
+ return lpegmatch(c,str)
end
-
-function string.count(str,pattern) -- variant 3
- local n = 0
- for _ in gmatch(str,pattern) do -- not for utf
- n = n + 1
+function string.split(str,separator)
+ if separator then
+ local c=cache[separator]
+ if not c then
+ c=tsplitat(separator)
+ cache[separator]=c
+ end
+ return lpegmatch(c,str)
+ else
+ return { str }
+ end
+end
+local spacing=patterns.spacer^0*newline
+local empty=spacing*Cc("")
+local nonempty=Cs((1-spacing)^1)*spacing^-1
+local content=(empty+nonempty)^1
+patterns.textline=content
+local linesplitter=tsplitat(newline)
+patterns.linesplitter=linesplitter
+function string.splitlines(str)
+ return lpegmatch(linesplitter,str)
+end
+local cache={}
+function lpeg.checkedsplit(separator,str)
+ local c=cache[separator]
+ if not c then
+ separator=P(separator)
+ local other=C((1-separator)^1)
+ c=Ct(separator^0*other*(separator^1*other)^0)
+ cache[separator]=c
+ end
+ return lpegmatch(c,str)
+end
+function string.checkedsplit(str,separator)
+ local c=cache[separator]
+ if not c then
+ separator=P(separator)
+ local other=C((1-separator)^1)
+ c=Ct(separator^0*other*(separator^1*other)^0)
+ cache[separator]=c
+ end
+ return lpegmatch(c,str)
+end
+local function f2(s) local c1,c2=byte(s,1,2) return c1*64+c2-12416 end
+local function f3(s) local c1,c2,c3=byte(s,1,3) return (c1*64+c2)*64+c3-925824 end
+local function f4(s) local c1,c2,c3,c4=byte(s,1,4) return ((c1*64+c2)*64+c3)*64+c4-63447168 end
+local utf8byte=patterns.utf8one/byte+patterns.utf8two/f2+patterns.utf8three/f3+patterns.utf8four/f4
+patterns.utf8byte=utf8byte
+local cache={}
+function lpeg.stripper(str)
+ if type(str)=="string" then
+ local s=cache[str]
+ if not s then
+ s=Cs(((S(str)^1)/""+1)^0)
+ cache[str]=s
end
- return n
+ return s
+ else
+ return Cs(((str^1)/""+1)^0)
+ end
end
-
-function string.limit(str,n,sentinel) -- not utf proof
- if #str > n then
- sentinel = sentinel or "..."
- return sub(str,1,(n-#sentinel)) .. sentinel
+local cache={}
+function lpeg.keeper(str)
+ if type(str)=="string" then
+ local s=cache[str]
+ if not s then
+ s=Cs((((1-S(str))^1)/""+1)^0)
+ cache[str]=s
+ end
+ return s
+ else
+ return Cs((((1-str)^1)/""+1)^0)
+ end
+end
+function lpeg.frontstripper(str)
+ return (P(str)+P(true))*Cs(anything^0)
+end
+function lpeg.endstripper(str)
+ return Cs((1-P(str)*endofstring)^0)
+end
+function lpeg.replacer(one,two,makefunction,isutf)
+ local pattern
+ local u=isutf and utf8char or 1
+ if type(one)=="table" then
+ local no=#one
+ local p=P(false)
+ if no==0 then
+ for k,v in next,one do
+ p=p+P(k)/v
+ end
+ pattern=Cs((p+u)^0)
+ elseif no==1 then
+ local o=one[1]
+ one,two=P(o[1]),o[2]
+ pattern=Cs((one/two+u)^0)
+ else
+ for i=1,no do
+ local o=one[i]
+ p=p+P(o[1])/o[2]
+ end
+ pattern=Cs((p+u)^0)
+ end
+ else
+ pattern=Cs((P(one)/(two or "")+u)^0)
+ end
+ if makefunction then
+ return function(str)
+ return lpegmatch(pattern,str)
+ end
+ else
+ return pattern
+ end
+end
+function lpeg.finder(lst,makefunction)
+ local pattern
+ if type(lst)=="table" then
+ pattern=P(false)
+ if #lst==0 then
+ for k,v in next,lst do
+ pattern=pattern+P(k)
+ end
else
- return str
+ for i=1,#lst do
+ pattern=pattern+P(lst[i])
+ end
+ end
+ else
+ pattern=P(lst)
+ end
+ pattern=(1-pattern)^0*pattern
+ if makefunction then
+ return function(str)
+ return lpegmatch(pattern,str)
+ end
+ else
+ return pattern
+ end
+end
+local splitters_f,splitters_s={},{}
+function lpeg.firstofsplit(separator)
+ local splitter=splitters_f[separator]
+ if not splitter then
+ separator=P(separator)
+ splitter=C((1-separator)^0)
+ splitters_f[separator]=splitter
+ end
+ return splitter
+end
+function lpeg.secondofsplit(separator)
+ local splitter=splitters_s[separator]
+ if not splitter then
+ separator=P(separator)
+ splitter=(1-separator)^0*separator*C(anything^0)
+ splitters_s[separator]=splitter
+ end
+ return splitter
+end
+function lpeg.balancer(left,right)
+ left,right=P(left),P(right)
+ return P { left*((1-left-right)+V(1))^0*right }
+end
+local nany=utf8char/""
+function lpeg.counter(pattern)
+ pattern=Cs((P(pattern)/" "+nany)^0)
+ return function(str)
+ return #lpegmatch(pattern,str)
+ end
+end
+utf=utf or (unicode and unicode.utf8) or {}
+local utfcharacters=utf and utf.characters or string.utfcharacters
+local utfgmatch=utf and utf.gmatch
+local utfchar=utf and utf.char
+lpeg.UP=lpeg.P
+if utfcharacters then
+ function lpeg.US(str)
+ local p=P(false)
+ for uc in utfcharacters(str) do
+ p=p+P(uc)
+ end
+ return p
+ end
+elseif utfgmatch then
+ function lpeg.US(str)
+ local p=P(false)
+ for uc in utfgmatch(str,".") do
+ p=p+P(uc)
+ end
+ return p
+ end
+else
+ function lpeg.US(str)
+ local p=P(false)
+ local f=function(uc)
+ p=p+P(uc)
end
+ lpegmatch((utf8char/f)^0,str)
+ return p
+ end
end
-
-local space = S(" \t\v\n")
-local nospace = 1 - space
-local stripper = space^0 * C((space^0 * nospace^1)^0) -- roberto's code
-
-function string.strip(str)
- return lpegmatch(stripper,str) or ""
+local range=utf8byte*utf8byte+Cc(false)
+function lpeg.UR(str,more)
+ local first,last
+ if type(str)=="number" then
+ first=str
+ last=more or first
+ else
+ first,last=lpegmatch(range,str)
+ if not last then
+ return P(str)
+ end
+ end
+ if first==last then
+ return P(str)
+ elseif utfchar and (last-first<8) then
+ local p=P(false)
+ for i=first,last do
+ p=p+P(utfchar(i))
+ end
+ return p
+ else
+ local f=function(b)
+ return b>=first and b<=last
+ end
+ return utf8byte/f
+ end
end
-
-function string.is_empty(str)
- return not find(str,"%S")
+function lpeg.is_lpeg(p)
+ return p and lpegtype(p)=="pattern"
+end
+function lpeg.oneof(list,...)
+ if type(list)~="table" then
+ list={ list,... }
+ end
+ local p=P(list[1])
+ for l=2,#list do
+ p=p+P(list[l])
+ end
+ return p
+end
+local sort=table.sort
+local function copyindexed(old)
+ local new={}
+ for i=1,#old do
+ new[i]=old
+ end
+ return new
end
-
-local patterns_escapes = {
- ["%"] = "%%",
- ["."] = "%.",
- ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
- ["["] = "%[", ["]"] = "%]",
- ["("] = "%(", [")"] = "%)",
- -- ["{"] = "%{", ["}"] = "%}"
- -- ["^"] = "%^", ["$"] = "%$",
-}
-
-local simple_escapes = {
- ["-"] = "%-",
- ["."] = "%.",
- ["?"] = ".",
- ["*"] = ".*",
-}
-
-function string.escapedpattern(str,simple)
- return (gsub(str,".",simple and simple_escapes or patterns_escapes))
+local function sortedkeys(tab)
+ local keys,s={},0
+ for key,_ in next,tab do
+ s=s+1
+ keys[s]=key
+ end
+ sort(keys)
+ return keys
end
-
-function string.topattern(str,lowercase,strict)
- if str == "" then
- return ".*"
+function lpeg.append(list,pp,delayed,checked)
+ local p=pp
+ if #list>0 then
+ local keys=copyindexed(list)
+ sort(keys)
+ for i=#keys,1,-1 do
+ local k=keys[i]
+ if p then
+ p=P(k)+p
+ else
+ p=P(k)
+ end
+ end
+ elseif delayed then
+ local keys=sortedkeys(list)
+ if p then
+ for i=1,#keys,1 do
+ local k=keys[i]
+ local v=list[k]
+ p=P(k)/list+p
+ end
else
- str = gsub(str,".",simple_escapes)
- if lowercase then
- str = lower(str)
+ for i=1,#keys do
+ local k=keys[i]
+ local v=list[k]
+ if p then
+ p=P(k)+p
+ else
+ p=P(k)
+ end
+ end
+ if p then
+ p=p/list
+ end
+ end
+ elseif checked then
+ local keys=sortedkeys(list)
+ for i=1,#keys do
+ local k=keys[i]
+ local v=list[k]
+ if p then
+ if k==v then
+ p=P(k)+p
+ else
+ p=P(k)/v+p
end
- if strict then
- return "^" .. str .. "$"
+ else
+ if k==v then
+ p=P(k)
else
- return str
+ p=P(k)/v
end
+ end
+ end
+ else
+ local keys=sortedkeys(list)
+ for i=1,#keys do
+ local k=keys[i]
+ local v=list[k]
+ if p then
+ p=P(k)/v+p
+ else
+ p=P(k)/v
+ end
end
+ end
+ return p
end
-
--- obsolete names:
-
-string.quote = string.quoted
-string.unquote = string.unquoted
+local function make(t)
+ local p
+ local keys=sortedkeys(t)
+ for i=1,#keys do
+ local k=keys[i]
+ local v=t[k]
+ if not p then
+ if next(v) then
+ p=P(k)*make(v)
+ else
+ p=P(k)
+ end
+ else
+ if next(v) then
+ p=p+P(k)*make(v)
+ else
+ p=p+P(k)
+ end
+ end
+ end
+ return p
+end
+function lpeg.utfchartabletopattern(list)
+ local tree={}
+ for i=1,#list do
+ local t=tree
+ for c in gmatch(list[i],".") do
+ if not t[c] then
+ t[c]={}
+ end
+ t=t[c]
+ end
+ end
+ return make(tree)
+end
+patterns.containseol=lpeg.finder(eol)
+local function nextstep(n,step,result)
+ local m=n%step
+ local d=floor(n/step)
+ if d>0 then
+ local v=V(tostring(step))
+ local s=result.start
+ for i=1,d do
+ if s then
+ s=v*s
+ else
+ s=v
+ end
+ end
+ result.start=s
+ end
+ if step>1 and result.start then
+ local v=V(tostring(step/2))
+ result[tostring(step)]=v*v
+ end
+ if step>0 then
+ return nextstep(m,step/2,result)
+ else
+ return result
+ end
+end
+function lpeg.times(pattern,n)
+ return P(nextstep(n,2^16,{ "start",["1"]=pattern }))
+end
+local digit=R("09")
+local period=P(".")
+local zero=P("0")
+local trailingzeros=zero^0*-digit
+local case_1=period*trailingzeros/""
+local case_2=period*(digit-trailingzeros)^1*(trailingzeros/"")
+local number=digit^1*(case_1+case_2)
+local stripper=Cs((number+1)^0)
+lpeg.patterns.stripzeros=stripper
end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-table'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local type, next, tostring, tonumber, ipairs, table, string = type, next, tostring, tonumber, ipairs, table, string
-local concat, sort, insert, remove = table.concat, table.sort, table.insert, table.remove
-local format, find, gsub, lower, dump, match = string.format, string.find, string.gsub, string.lower, string.dump, string.match
-local getmetatable, setmetatable = getmetatable, setmetatable
-local getinfo = debug.getinfo
+package.loaded["l-function"] = package.loaded["l-function"] or true
--- Starting with version 5.2 Lua no longer provide ipairs, which makes
--- sense. As we already used the for loop and # in most places the
--- impact on ConTeXt was not that large; the remaining ipairs already
--- have been replaced. In a similar fashion we also hardly used pairs.
---
--- Just in case, we provide the fallbacks as discussed in Programming
--- in Lua (http://www.lua.org/pil/7.3.html):
+-- original size: 361, stripped down to: 322
-if not ipairs then
+if not modules then modules={} end modules ['l-functions']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+functions=functions or {}
+function functions.dummy() end
- -- for k, v in ipairs(t) do ... end
- -- for k=1,#t do local v = t[k] ... end
- local function iterate(a,i)
- i = i + 1
- local v = a[i]
- if v ~= nil then
- return i, v --, nil
- end
- end
+end -- of closure
- function ipairs(a)
- return iterate, a, 0
- end
+do -- create closure to overcome 200 locals limit
-end
+package.loaded["l-string"] = package.loaded["l-string"] or true
-if not pairs then
+-- original size: 5513, stripped down to: 2708
- -- for k, v in pairs(t) do ... end
- -- for k, v in next, t do ... end
+if not modules then modules={} end modules ['l-string']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local string=string
+local sub,gmatch,format,char,byte,rep,lower=string.sub,string.gmatch,string.format,string.char,string.byte,string.rep,string.lower
+local lpegmatch,patterns=lpeg.match,lpeg.patterns
+local P,S,C,Ct,Cc,Cs=lpeg.P,lpeg.S,lpeg.C,lpeg.Ct,lpeg.Cc,lpeg.Cs
+local unquoted=patterns.squote*C(patterns.nosquote)*patterns.squote+patterns.dquote*C(patterns.nodquote)*patterns.dquote
+function string.unquoted(str)
+ return lpegmatch(unquoted,str) or str
+end
+function string.quoted(str)
+ return format("%q",str)
+end
+function string.count(str,pattern)
+ local n=0
+ for _ in gmatch(str,pattern) do
+ n=n+1
+ end
+ return n
+end
+function string.limit(str,n,sentinel)
+ if #str>n then
+ sentinel=sentinel or "..."
+ return sub(str,1,(n-#sentinel))..sentinel
+ else
+ return str
+ end
+end
+local stripper=patterns.stripper
+local collapser=patterns.collapser
+local longtostring=patterns.longtostring
+function string.strip(str)
+ return lpegmatch(stripper,str) or ""
+end
+function string.collapsespaces(str)
+ return lpegmatch(collapser,str) or ""
+end
+function string.longtostring(str)
+ return lpegmatch(longtostring,str) or ""
+end
+local pattern=P(" ")^0*P(-1)
+function string.is_empty(str)
+ if str=="" then
+ return true
+ else
+ return lpegmatch(pattern,str) and true or false
+ end
+end
+local anything=patterns.anything
+local allescapes=Cc("%")*S(".-+%?()[]*")
+local someescapes=Cc("%")*S(".-+%()[]")
+local matchescapes=Cc(".")*S("*?")
+local pattern_a=Cs ((allescapes+anything )^0 )
+local pattern_b=Cs ((someescapes+matchescapes+anything )^0 )
+local pattern_c=Cs (Cc("^")*(someescapes+matchescapes+anything )^0*Cc("$") )
+function string.escapedpattern(str,simple)
+ return lpegmatch(simple and pattern_b or pattern_a,str)
+end
+function string.topattern(str,lowercase,strict)
+ if str=="" or type(str)~="string" then
+ return ".*"
+ elseif strict then
+ str=lpegmatch(pattern_c,str)
+ else
+ str=lpegmatch(pattern_b,str)
+ end
+ if lowercase then
+ return lower(str)
+ else
+ return str
+ end
+end
+function string.valid(str,default)
+ return (type(str)=="string" and str~="" and str) or default or nil
+end
+string.itself=function(s) return s end
+local pattern=Ct(C(1)^0)
+function string.totable(str)
+ return lpegmatch(pattern,str)
+end
+local replacer=lpeg.replacer("@","%%")
+function string.tformat(fmt,...)
+ return format(lpegmatch(replacer,fmt),...)
+end
+string.quote=string.quoted
+string.unquote=string.unquoted
- function pairs(t)
- return next, t -- , nil
- end
-end
+end -- of closure
--- Also, unpack has been moved to the table table, and for compatiility
--- reasons we provide both now.
+do -- create closure to overcome 200 locals limit
-if not table.unpack then
- table.unpack = _G.unpack
-elseif not unpack then
- _G.unpack = table.unpack
-end
+package.loaded["l-table"] = package.loaded["l-table"] or true
--- extra functions, some might go (when not used)
+-- original size: 44643, stripped down to: 19717
+if not modules then modules={} end modules ['l-table']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local type,next,tostring,tonumber,ipairs,select=type,next,tostring,tonumber,ipairs,select
+local table,string=table,string
+local concat,sort,insert,remove=table.concat,table.sort,table.insert,table.remove
+local format,lower,dump=string.format,string.lower,string.dump
+local getmetatable,setmetatable=getmetatable,setmetatable
+local getinfo=debug.getinfo
+local lpegmatch,patterns=lpeg.match,lpeg.patterns
+local floor=math.floor
+local stripper=patterns.stripper
function table.strip(tab)
- local lst, l = { }, 0
- for i=1,#tab do
- local s = gsub(tab[i],"^%s*(.-)%s*$","%1")
- if s == "" then
- -- skip this one
- else
- l = l + 1
- lst[l] = s
- end
+ local lst,l={},0
+ for i=1,#tab do
+ local s=lpegmatch(stripper,tab[i]) or ""
+ if s=="" then
+ else
+ l=l+1
+ lst[l]=s
end
- return lst
+ end
+ return lst
end
-
function table.keys(t)
- local keys, k = { }, 0
- for key, _ in next, t do
- k = k + 1
- keys[k] = key
+ if t then
+ local keys,k={},0
+ for key,_ in next,t do
+ k=k+1
+ keys[k]=key
end
return keys
+ else
+ return {}
+ end
end
-
local function compare(a,b)
- local ta, tb = type(a), type(b) -- needed, else 11 < 2
- if ta == tb then
- return a < b
- else
- return tostring(a) < tostring(b)
- end
+ local ta,tb=type(a),type(b)
+ if ta==tb then
+ return a0 then
+ local n=0
+ for _,v in next,t do
+ n=n+1
+ end
+ if n==#t then
+ local tt,nt={},0
+ for i=1,#t do
+ local v=t[i]
+ local tv=type(v)
+ if tv=="number" then
+ nt=nt+1
+ if hexify then
+ tt[nt]=format("0x%04X",v)
+ else
+ tt[nt]=tostring(v)
+ end
+ elseif tv=="boolean" then
+ nt=nt+1
+ tt[nt]=tostring(v)
+ elseif tv=="string" then
+ nt=nt+1
+ tt[nt]=format("%q",v)
+ else
+ tt=nil
+ break
end
+ end
+ return tt
end
- return tmp
+ end
+ return nil
end
-
-local function fastcopy(old,metatabletoo) -- fast one
- if old then
- local new = { }
- for k,v in next, old do
- if type(v) == "table" then
- new[k] = fastcopy(v,metatabletoo) -- was just table.copy
- else
- new[k] = v
- end
+local propername=patterns.propername
+local function dummy() end
+local function do_serialize(root,name,depth,level,indexed)
+ if level>0 then
+ depth=depth.." "
+ if indexed then
+ handle(format("%s{",depth))
+ else
+ local tn=type(name)
+ if tn=="number" then
+ if hexify then
+ handle(format("%s[0x%04X]={",depth,name))
+ else
+ handle(format("%s[%s]={",depth,name))
end
- if metatabletoo then
- -- optional second arg
- local mt = getmetatable(old)
- if mt then
- setmetatable(new,mt)
+ elseif tn=="string" then
+ if noquotes and not reserved[name] and lpegmatch(propername,name) then
+ handle(format("%s%s={",depth,name))
+ else
+ handle(format("%s[%q]={",depth,name))
+ end
+ elseif tn=="boolean" then
+ handle(format("%s[%s]={",depth,tostring(name)))
+ else
+ handle(format("%s{",depth))
+ end
+ end
+ end
+ if root and next(root) then
+ local first,last=nil,0
+ if compact then
+ last=#root
+ for k=1,last do
+ if root[k]==nil then
+ last=k-1
+ break
+ end
+ end
+ if last>0 then
+ first=1
+ end
+ end
+ local sk=sortedkeys(root)
+ for i=1,#sk do
+ local k=sk[i]
+ local v=root[k]
+ local t,tk=type(v),type(k)
+ if compact and first and tk=="number" and k>=first and k<=last then
+ if t=="number" then
+ if hexify then
+ handle(format("%s 0x%04X,",depth,v))
+ else
+ handle(format("%s %s,",depth,v))
+ end
+ elseif t=="string" then
+ if reduce and tonumber(v) then
+ handle(format("%s %s,",depth,v))
+ else
+ handle(format("%s %q,",depth,v))
+ end
+ elseif t=="table" then
+ if not next(v) then
+ handle(format("%s {},",depth))
+ elseif inline then
+ local st=simple_table(v)
+ if st then
+ handle(format("%s { %s },",depth,concat(st,", ")))
+ else
+ do_serialize(v,k,depth,level+1,true)
+ end
+ else
+ do_serialize(v,k,depth,level+1,true)
+ end
+ elseif t=="boolean" then
+ handle(format("%s %s,",depth,tostring(v)))
+ elseif t=="function" then
+ if functions then
+ handle(format('%s load(%q),',depth,dump(v)))
+ else
+ handle(format('%s "function",',depth))
+ end
+ else
+ handle(format("%s %q,",depth,tostring(v)))
+ end
+ elseif k=="__p__" then
+ if false then
+ handle(format("%s __p__=nil,",depth))
+ end
+ elseif t=="number" then
+ if tk=="number" then
+ if hexify then
+ handle(format("%s [0x%04X]=0x%04X,",depth,k,v))
+ else
+ handle(format("%s [%s]=%s,",depth,k,v))
+ end
+ elseif tk=="boolean" then
+ if hexify then
+ handle(format("%s [%s]=0x%04X,",depth,tostring(k),v))
+ else
+ handle(format("%s [%s]=%s,",depth,tostring(k),v))
+ end
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
+ if hexify then
+ handle(format("%s %s=0x%04X,",depth,k,v))
+ else
+ handle(format("%s %s=%s,",depth,k,v))
+ end
+ else
+ if hexify then
+ handle(format("%s [%q]=0x%04X,",depth,k,v))
+ else
+ handle(format("%s [%q]=%s,",depth,k,v))
+ end
+ end
+ elseif t=="string" then
+ if reduce and tonumber(v) then
+ if tk=="number" then
+ if hexify then
+ handle(format("%s [0x%04X]=%s,",depth,k,v))
+ else
+ handle(format("%s [%s]=%s,",depth,k,v))
+ end
+ elseif tk=="boolean" then
+ handle(format("%s [%s]=%s,",depth,tostring(k),v))
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
+ handle(format("%s %s=%s,",depth,k,v))
+ else
+ handle(format("%s [%q]=%s,",depth,k,v))
+ end
+ else
+ if tk=="number" then
+ if hexify then
+ handle(format("%s [0x%04X]=%q,",depth,k,v))
+ else
+ handle(format("%s [%s]=%q,",depth,k,v))
+ end
+ elseif tk=="boolean" then
+ handle(format("%s [%s]=%q,",depth,tostring(k),v))
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
+ handle(format("%s %s=%q,",depth,k,v))
+ else
+ handle(format("%s [%q]=%q,",depth,k,v))
+ end
+ end
+ elseif t=="table" then
+ if not next(v) then
+ if tk=="number" then
+ if hexify then
+ handle(format("%s [0x%04X]={},",depth,k))
+ else
+ handle(format("%s [%s]={},",depth,k))
+ end
+ elseif tk=="boolean" then
+ handle(format("%s [%s]={},",depth,tostring(k)))
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
+ handle(format("%s %s={},",depth,k))
+ else
+ handle(format("%s [%q]={},",depth,k))
+ end
+ elseif inline then
+ local st=simple_table(v)
+ if st then
+ if tk=="number" then
+ if hexify then
+ handle(format("%s [0x%04X]={ %s },",depth,k,concat(st,", ")))
+ else
+ handle(format("%s [%s]={ %s },",depth,k,concat(st,", ")))
+ end
+ elseif tk=="boolean" then
+ handle(format("%s [%s]={ %s },",depth,tostring(k),concat(st,", ")))
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
+ handle(format("%s %s={ %s },",depth,k,concat(st,", ")))
+ else
+ handle(format("%s [%q]={ %s },",depth,k,concat(st,", ")))
end
+ else
+ do_serialize(v,k,depth,level+1)
+ end
+ else
+ do_serialize(v,k,depth,level+1)
+ end
+ elseif t=="boolean" then
+ if tk=="number" then
+ if hexify then
+ handle(format("%s [0x%04X]=%s,",depth,k,tostring(v)))
+ else
+ handle(format("%s [%s]=%s,",depth,k,tostring(v)))
+ end
+ elseif tk=="boolean" then
+ handle(format("%s [%s]=%s,",depth,tostring(k),tostring(v)))
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
+ handle(format("%s %s=%s,",depth,k,tostring(v)))
+ else
+ handle(format("%s [%q]=%s,",depth,k,tostring(v)))
end
- return new
+ elseif t=="function" then
+ if functions then
+ local f=getinfo(v).what=="C" and dump(dummy) or dump(v)
+ if tk=="number" then
+ if hexify then
+ handle(format("%s [0x%04X]=load(%q),",depth,k,f))
+ else
+ handle(format("%s [%s]=load(%q),",depth,k,f))
+ end
+ elseif tk=="boolean" then
+ handle(format("%s [%s]=load(%q),",depth,tostring(k),f))
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
+ handle(format("%s %s=load(%q),",depth,k,f))
+ else
+ handle(format("%s [%q]=load(%q),",depth,k,f))
+ end
+ end
+ else
+ if tk=="number" then
+ if hexify then
+ handle(format("%s [0x%04X]=%q,",depth,k,tostring(v)))
+ else
+ handle(format("%s [%s]=%q,",depth,k,tostring(v)))
+ end
+ elseif tk=="boolean" then
+ handle(format("%s [%s]=%q,",depth,tostring(k),tostring(v)))
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
+ handle(format("%s %s=%q,",depth,k,tostring(v)))
+ else
+ handle(format("%s [%q]=%q,",depth,k,tostring(v)))
+ end
+ end
+ end
+ end
+ if level>0 then
+ handle(format("%s},",depth))
+ end
+end
+local function serialize(_handle,root,name,specification)
+ local tname=type(name)
+ if type(specification)=="table" then
+ noquotes=specification.noquotes
+ hexify=specification.hexify
+ handle=_handle or specification.handle or print
+ reduce=specification.reduce or false
+ functions=specification.functions
+ compact=specification.compact
+ inline=specification.inline and compact
+ if functions==nil then
+ functions=true
+ end
+ if compact==nil then
+ compact=true
+ end
+ if inline==nil then
+ inline=compact
+ end
+ else
+ noquotes=false
+ hexify=false
+ handle=_handle or print
+ reduce=false
+ compact=true
+ inline=true
+ functions=true
+ end
+ if tname=="string" then
+ if name=="return" then
+ handle("return {")
else
- return { }
+ handle(name.."={")
end
-end
-
--- todo : copy without metatable
-
-local function copy(t, tables) -- taken from lua wiki, slightly adapted
- tables = tables or { }
- local tcopy = {}
- if not tables[t] then
- tables[t] = tcopy
+ elseif tname=="number" then
+ if hexify then
+ handle(format("[0x%04X]={",name))
+ else
+ handle("["..name.."]={")
end
- for i,v in next, t do -- brrr, what happens with sparse indexed
- if type(i) == "table" then
- if tables[i] then
- i = tables[i]
- else
- i = copy(i, tables)
- end
- end
- if type(v) ~= "table" then
- tcopy[i] = v
- elseif tables[v] then
- tcopy[i] = tables[v]
- else
- tcopy[i] = copy(v, tables)
- end
+ elseif tname=="boolean" then
+ if name then
+ handle("return {")
+ else
+ handle("{")
end
- local mt = getmetatable(t)
- if mt then
- setmetatable(tcopy,mt)
+ else
+ handle("t={")
+ end
+ if root then
+ if getmetatable(root) then
+ local dummy=root._w_h_a_t_e_v_e_r_
+ root._w_h_a_t_e_v_e_r_=nil
end
- return tcopy
-end
-
-table.fastcopy = fastcopy
-table.copy = copy
-
-function table.derive(parent)
- local child = { }
- if parent then
- setmetatable(child,{ __index = parent })
+ if next(root) then
+ do_serialize(root,name,"",0)
end
- return child
+ end
+ handle("}")
end
-
-function table.tohash(t,value)
- local h = { }
- if t then
- if value == nil then value = true end
- for _, v in next, t do -- no ipairs here
- h[v] = value
- end
+function table.serialize(root,name,specification)
+ local t,n={},0
+ local function flush(s)
+ n=n+1
+ t[n]=s
+ end
+ serialize(flush,root,name,specification)
+ return concat(t,"\n")
+end
+table.tohandle=serialize
+local maxtab=2*1024
+function table.tofile(filename,root,name,specification)
+ local f=io.open(filename,'w')
+ if f then
+ if maxtab>1 then
+ local t,n={},0
+ local function flush(s)
+ n=n+1
+ t[n]=s
+ if n>maxtab then
+ f:write(concat(t,"\n"),"\n")
+ t,n={},0
+ end
+ end
+ serialize(flush,root,name,specification)
+ f:write(concat(t,"\n"),"\n")
+ else
+ local function flush(s)
+ f:write(s,"\n")
+ end
+ serialize(flush,root,name,specification)
end
- return h
+ f:close()
+ io.flush()
+ end
end
-
-function table.fromhash(t)
- local hsh, h = { }, 0
- for k, v in next, t do -- no ipairs here
- if v then
- h = h + 1
- hsh[h] = k
- end
+local function flattened(t,f,depth)
+ if f==nil then
+ f={}
+ depth=0xFFFF
+ elseif tonumber(f) then
+ depth=f
+ f={}
+ elseif not depth then
+ depth=0xFFFF
+ end
+ for k,v in next,t do
+ if type(k)~="number" then
+ if depth>0 and type(v)=="table" then
+ flattened(v,f,depth-1)
+ else
+ f[k]=v
+ end
+ end
+ end
+ local n=#f
+ for k=1,#t do
+ local v=t[k]
+ if depth>0 and type(v)=="table" then
+ flattened(v,f,depth-1)
+ n=#f
+ else
+ n=n+1
+ f[n]=v
+ end
+ end
+ return f
+end
+table.flattened=flattened
+local function unnest(t,f)
+ if not f then
+ f={}
+ end
+ for i=1,#t do
+ local v=t[i]
+ if type(v)=="table" then
+ if type(v[1])=="table" then
+ unnest(v,f)
+ else
+ f[#f+1]=v
+ end
+ else
+ f[#f+1]=v
+ end
+ end
+ return f
+end
+function table.unnest(t)
+ return unnest(t)
+end
+local function are_equal(a,b,n,m)
+ if a and b and #a==#b then
+ n=n or 1
+ m=m or #a
+ for i=n,m do
+ local ai,bi=a[i],b[i]
+ if ai==bi then
+ elseif type(ai)=="table" and type(bi)=="table" then
+ if not are_equal(ai,bi) then
+ return false
+ end
+ else
+ return false
+ end
end
- return hsh
-end
-
-local noquotes, hexify, handle, reduce, compact, inline, functions
-
-local reserved = table.tohash { -- intercept a language inconvenience: no reserved words as key
- 'and', 'break', 'do', 'else', 'elseif', 'end', 'false', 'for', 'function', 'if',
- 'in', 'local', 'nil', 'not', 'or', 'repeat', 'return', 'then', 'true', 'until', 'while',
-}
-
-local function simple_table(t)
- if #t > 0 then
- local n = 0
- for _,v in next, t do
- n = n + 1
- end
- if n == #t then
- local tt, nt = { }, 0
- for i=1,#t do
- local v = t[i]
- local tv = type(v)
- if tv == "number" then
- nt = nt + 1
- if hexify then
- tt[nt] = format("0x%04X",v)
- else
- tt[nt] = tostring(v) -- tostring not needed
- end
- elseif tv == "boolean" then
- nt = nt + 1
- tt[nt] = tostring(v)
- elseif tv == "string" then
- nt = nt + 1
- tt[nt] = format("%q",v)
- else
- tt = nil
- break
- end
- end
- return tt
- end
+ return true
+ else
+ return false
+ end
+end
+local function identical(a,b)
+ for ka,va in next,a do
+ local vb=b[ka]
+ if va==vb then
+ elseif type(va)=="table" and type(vb)=="table" then
+ if not identical(va,vb) then
+ return false
+ end
+ else
+ return false
end
- return nil
+ end
+ return true
end
-
--- Because this is a core function of mkiv I moved some function calls
--- inline.
---
--- twice as fast in a test:
---
--- local propername = lpeg.P(lpeg.R("AZ","az","__") * lpeg.R("09","AZ","az", "__")^0 * lpeg.P(-1) )
-
--- problem: there no good number_to_string converter with the best resolution
-
-local function dummy() end
-
-local function do_serialize(root,name,depth,level,indexed)
- if level > 0 then
- depth = depth .. " "
- if indexed then
- handle(format("%s{",depth))
- else
- local tn = type(name)
- if tn == "number" then -- or find(k,"^%d+$") then
- if hexify then
- handle(format("%s[0x%04X]={",depth,name))
- else
- handle(format("%s[%s]={",depth,name))
- end
- elseif tn == "string" then
- if noquotes and not reserved[name] and find(name,"^%a[%w%_]*$") then
- handle(format("%s%s={",depth,name))
- else
- handle(format("%s[%q]={",depth,name))
- end
- elseif tn == "boolean" then
- handle(format("%s[%s]={",depth,tostring(name)))
- else
- handle(format("%s{",depth))
- end
- end
- end
- -- we could check for k (index) being number (cardinal)
- if root and next(root) then
- local first, last = nil, 0 -- #root cannot be trusted here (will be ok in 5.2 when ipairs is gone)
- if compact then
- -- NOT: for k=1,#root do (we need to quit at nil)
- for k,v in ipairs(root) do -- can we use next?
- if not first then first = k end
- last = last + 1
- end
- end
- local sk = sortedkeys(root)
- for i=1,#sk do
- local k = sk[i]
- local v = root[k]
- -- circular
- local t, tk = type(v), type(k)
- if compact and first and tk == "number" and k >= first and k <= last then
- if t == "number" then
- if hexify then
- handle(format("%s 0x%04X,",depth,v))
- else
- handle(format("%s %s,",depth,v)) -- %.99g
- end
- elseif t == "string" then
- if reduce and tonumber(v) then
- handle(format("%s %s,",depth,v))
- else
- handle(format("%s %q,",depth,v))
- end
- elseif t == "table" then
- if not next(v) then
- handle(format("%s {},",depth))
- elseif inline then -- and #t > 0
- local st = simple_table(v)
- if st then
- handle(format("%s { %s },",depth,concat(st,", ")))
- else
- do_serialize(v,k,depth,level+1,true)
- end
- else
- do_serialize(v,k,depth,level+1,true)
- end
- elseif t == "boolean" then
- handle(format("%s %s,",depth,tostring(v)))
- elseif t == "function" then
- if functions then
- handle(format('%s loadstring(%q),',depth,dump(v)))
- else
- handle(format('%s "function",',depth))
- end
- else
- handle(format("%s %q,",depth,tostring(v)))
- end
- elseif k == "__p__" then -- parent
- if false then
- handle(format("%s __p__=nil,",depth))
- end
- elseif t == "number" then
- if tk == "number" then -- or find(k,"^%d+$") then
- if hexify then
- handle(format("%s [0x%04X]=0x%04X,",depth,k,v))
- else
- handle(format("%s [%s]=%s,",depth,k,v)) -- %.99g
- end
- elseif tk == "boolean" then
- if hexify then
- handle(format("%s [%s]=0x%04X,",depth,tostring(k),v))
- else
- handle(format("%s [%s]=%s,",depth,tostring(k),v)) -- %.99g
- end
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
- if hexify then
- handle(format("%s %s=0x%04X,",depth,k,v))
- else
- handle(format("%s %s=%s,",depth,k,v)) -- %.99g
- end
- else
- if hexify then
- handle(format("%s [%q]=0x%04X,",depth,k,v))
- else
- handle(format("%s [%q]=%s,",depth,k,v)) -- %.99g
- end
- end
- elseif t == "string" then
- if reduce and tonumber(v) then
- if tk == "number" then -- or find(k,"^%d+$") then
- if hexify then
- handle(format("%s [0x%04X]=%s,",depth,k,v))
- else
- handle(format("%s [%s]=%s,",depth,k,v))
- end
- elseif tk == "boolean" then
- handle(format("%s [%s]=%s,",depth,tostring(k),v))
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
- handle(format("%s %s=%s,",depth,k,v))
- else
- handle(format("%s [%q]=%s,",depth,k,v))
- end
- else
- if tk == "number" then -- or find(k,"^%d+$") then
- if hexify then
- handle(format("%s [0x%04X]=%q,",depth,k,v))
- else
- handle(format("%s [%s]=%q,",depth,k,v))
- end
- elseif tk == "boolean" then
- handle(format("%s [%s]=%q,",depth,tostring(k),v))
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
- handle(format("%s %s=%q,",depth,k,v))
- else
- handle(format("%s [%q]=%q,",depth,k,v))
- end
- end
- elseif t == "table" then
- if not next(v) then
- if tk == "number" then -- or find(k,"^%d+$") then
- if hexify then
- handle(format("%s [0x%04X]={},",depth,k))
- else
- handle(format("%s [%s]={},",depth,k))
- end
- elseif tk == "boolean" then
- handle(format("%s [%s]={},",depth,tostring(k)))
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
- handle(format("%s %s={},",depth,k))
- else
- handle(format("%s [%q]={},",depth,k))
- end
- elseif inline then
- local st = simple_table(v)
- if st then
- if tk == "number" then -- or find(k,"^%d+$") then
- if hexify then
- handle(format("%s [0x%04X]={ %s },",depth,k,concat(st,", ")))
- else
- handle(format("%s [%s]={ %s },",depth,k,concat(st,", ")))
- end
- elseif tk == "boolean" then -- or find(k,"^%d+$") then
- handle(format("%s [%s]={ %s },",depth,tostring(k),concat(st,", ")))
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
- handle(format("%s %s={ %s },",depth,k,concat(st,", ")))
- else
- handle(format("%s [%q]={ %s },",depth,k,concat(st,", ")))
- end
- else
- do_serialize(v,k,depth,level+1)
- end
- else
- do_serialize(v,k,depth,level+1)
- end
- elseif t == "boolean" then
- if tk == "number" then -- or find(k,"^%d+$") then
- if hexify then
- handle(format("%s [0x%04X]=%s,",depth,k,tostring(v)))
- else
- handle(format("%s [%s]=%s,",depth,k,tostring(v)))
- end
- elseif tk == "boolean" then -- or find(k,"^%d+$") then
- handle(format("%s [%s]=%s,",depth,tostring(k),tostring(v)))
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
- handle(format("%s %s=%s,",depth,k,tostring(v)))
- else
- handle(format("%s [%q]=%s,",depth,k,tostring(v)))
- end
- elseif t == "function" then
- if functions then
- local f = getinfo(v).what == "C" and dump(dummy) or dump(v)
- -- local f = getinfo(v).what == "C" and dump(function(...) return v(...) end) or dump(v)
- if tk == "number" then -- or find(k,"^%d+$") then
- if hexify then
- handle(format("%s [0x%04X]=loadstring(%q),",depth,k,f))
- else
- handle(format("%s [%s]=loadstring(%q),",depth,k,f))
- end
- elseif tk == "boolean" then
- handle(format("%s [%s]=loadstring(%q),",depth,tostring(k),f))
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
- handle(format("%s %s=loadstring(%q),",depth,k,f))
- else
- handle(format("%s [%q]=loadstring(%q),",depth,k,f))
- end
- end
- else
- if tk == "number" then -- or find(k,"^%d+$") then
- if hexify then
- handle(format("%s [0x%04X]=%q,",depth,k,tostring(v)))
- else
- handle(format("%s [%s]=%q,",depth,k,tostring(v)))
- end
- elseif tk == "boolean" then -- or find(k,"^%d+$") then
- handle(format("%s [%s]=%q,",depth,tostring(k),tostring(v)))
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
- handle(format("%s %s=%q,",depth,k,tostring(v)))
- else
- handle(format("%s [%q]=%q,",depth,k,tostring(v)))
- end
- end
- end
+table.identical=identical
+table.are_equal=are_equal
+function table.compact(t)
+ if t then
+ for k,v in next,t do
+ if not next(v) then
+ t[k]=nil
+ end
end
- if level > 0 then
- handle(format("%s},",depth))
+ end
+end
+function table.contains(t,v)
+ if t then
+ for i=1,#t do
+ if t[i]==v then
+ return i
+ end
end
+ end
+ return false
end
-
--- replacing handle by a direct t[#t+1] = ... (plus test) is not much
--- faster (0.03 on 1.00 for zapfino.tma)
-
-local function serialize(_handle,root,name,specification) -- handle wins
- local tname = type(name)
- if type(specification) == "table" then
- noquotes = specification.noquotes
- hexify = specification.hexify
- handle = _handle or specification.handle or print
- reduce = specification.reduce or false
- functions = specification.functions
- compact = specification.compact
- inline = specification.inline and compact
- if functions == nil then
- functions = true
- end
- if compact == nil then
- compact = true
- end
- if inline == nil then
- inline = compact
- end
- else
- noquotes = false
- hexify = false
- handle = _handle or print
- reduce = false
- compact = true
- inline = true
- functions = true
- end
- if tname == "string" then
- if name == "return" then
- handle("return {")
- else
- handle(name .. "={")
- end
- elseif tname == "number" then
- if hexify then
- handle(format("[0x%04X]={",name))
- else
- handle("[" .. name .. "]={")
- end
- elseif tname == "boolean" then
- if name then
- handle("return {")
- else
- handle("{")
- end
- else
- handle("t={")
- end
- if root then
- -- The dummy access will initialize a table that has a delayed initialization
- -- using a metatable. (maybe explicitly test for metatable)
- if getmetatable(root) then -- todo: make this an option, maybe even per subtable
- local dummy = root._w_h_a_t_e_v_e_r_
- root._w_h_a_t_e_v_e_r_ = nil
- end
- -- Let's forget about empty tables.
- if next(root) then
- do_serialize(root,name,"",0)
- end
+function table.count(t)
+ local n=0
+ for k,v in next,t do
+ n=n+1
+ end
+ return n
+end
+function table.swapped(t,s)
+ local n={}
+ if s then
+ for k,v in next,s do
+ n[k]=v
+ end
+ end
+ for k,v in next,t do
+ n[v]=k
+ end
+ return n
+end
+function table.mirrored(t)
+ local n={}
+ for k,v in next,t do
+ n[v]=k
+ n[k]=v
+ end
+ return n
+end
+function table.reversed(t)
+ if t then
+ local tt,tn={},#t
+ if tn>0 then
+ local ttn=0
+ for i=tn,1,-1 do
+ ttn=ttn+1
+ tt[ttn]=t[i]
+ end
+ end
+ return tt
+ end
+end
+function table.reverse(t)
+ if t then
+ local n=#t
+ for i=1,floor(n/2) do
+ local j=n-i+1
+ t[i],t[j]=t[j],t[i]
end
- handle("}")
+ return t
+ end
end
-
-
-function table.serialize(root,name,specification)
- local t, n = { }, 0
- local function flush(s)
- n = n + 1
- t[n] = s
+function table.sequenced(t,sep,simple)
+ if not t then
+ return ""
+ end
+ local n=#t
+ local s={}
+ if n>0 then
+ for i=1,n do
+ s[i]=tostring(t[i])
+ end
+ else
+ n=0
+ for k,v in sortedhash(t) do
+ if simple then
+ if v==true then
+ n=n+1
+ s[n]=k
+ elseif v and v~="" then
+ n=n+1
+ s[n]=k.."="..tostring(v)
+ end
+ else
+ n=n+1
+ s[n]=k.."="..tostring(v)
+ end
+ end
+ end
+ return concat(s,sep or " | ")
+end
+function table.print(t,...)
+ if type(t)~="table" then
+ print(tostring(t))
+ else
+ serialize(print,t,...)
+ end
+end
+setinspector(function(v) if type(v)=="table" then serialize(print,v,"table") return true end end)
+function table.sub(t,i,j)
+ return { unpack(t,i,j) }
+end
+function table.is_empty(t)
+ return not t or not next(t)
+end
+function table.has_one_entry(t)
+ return t and not next(t,next(t))
+end
+function table.loweredkeys(t)
+ local l={}
+ for k,v in next,t do
+ l[lower(k)]=v
+ end
+ return l
+end
+function table.unique(old)
+ local hash={}
+ local new={}
+ local n=0
+ for i=1,#old do
+ local oi=old[i]
+ if not hash[oi] then
+ n=n+1
+ new[n]=oi
+ hash[oi]=true
end
- serialize(flush,root,name,specification)
- return concat(t,"\n")
+ end
+ return new
+end
+function table.sorted(t,...)
+ sort(t,...)
+ return t
end
-table.tohandle = serialize
-
--- sometimes tables are real use (zapfino extra pro is some 85M) in which
--- case a stepwise serialization is nice; actually, we could consider:
---
--- for line in table.serializer(root,name,reduce,noquotes) do
--- ...(line)
--- end
---
--- so this is on the todo list
-local maxtab = 2*1024
+end -- of closure
-function table.tofile(filename,root,name,specification)
- local f = io.open(filename,'w')
- if f then
- if maxtab > 1 then
- local t, n = { }, 0
- local function flush(s)
- n = n + 1
- t[n] = s
- if n > maxtab then
- f:write(concat(t,"\n"),"\n") -- hm, write(sometable) should be nice
- t, n = { }, 0 -- we could recycle t if needed
- end
- end
- serialize(flush,root,name,specification)
- f:write(concat(t,"\n"),"\n")
- else
- local function flush(s)
- f:write(s,"\n")
- end
- serialize(flush,root,name,specification)
- end
- f:close()
- io.flush()
- end
-end
+do -- create closure to overcome 200 locals limit
-local function flattened(t,f,depth)
- if f == nil then
- f = { }
- depth = 0xFFFF
- elseif tonumber(f) then
- -- assume then only two arguments are given
- depth = f
- f = { }
- elseif not depth then
- depth = 0xFFFF
- end
- for k, v in next, t do
- if type(k) ~= "number" then
- if depth > 0 and type(v) == "table" then
- flattened(v,f,depth-1)
- else
- f[k] = v
- end
- end
- end
- local n = #f
- for k=1,#t do
- local v = t[k]
- if depth > 0 and type(v) == "table" then
- flattened(v,f,depth-1)
- n = #f
- else
- n = n + 1
- f[n] = v
- end
- end
- return f
-end
+package.loaded["l-io"] = package.loaded["l-io"] or true
-table.flattened = flattened
+-- original size: 8799, stripped down to: 6325
-local function unnest(t,f) -- only used in mk, for old times sake
- if not f then -- and only relevant for token lists
- f = { }
- end
- for i=1,#t do
- local v = t[i]
- if type(v) == "table" then
- if type(v[1]) == "table" then
- unnest(v,f)
- else
- f[#f+1] = v
- end
- else
- f[#f+1] = v
- end
- end
- return f
+if not modules then modules={} end modules ['l-io']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local io=io
+local byte,find,gsub,format=string.byte,string.find,string.gsub,string.format
+local concat=table.concat
+local floor=math.floor
+local type=type
+if string.find(os.getenv("PATH"),";") then
+ io.fileseparator,io.pathseparator="\\",";"
+else
+ io.fileseparator,io.pathseparator="/",":"
end
-
-function table.unnest(t) -- bad name
- return unnest(t)
+local function readall(f)
+ return f:read("*all")
end
-
-local function are_equal(a,b,n,m) -- indexed
- if a and b and #a == #b then
- n = n or 1
- m = m or #a
- for i=n,m do
- local ai, bi = a[i], b[i]
- if ai==bi then
- -- same
- elseif type(ai)=="table" and type(bi)=="table" then
- if not are_equal(ai,bi) then
- return false
- end
- else
- return false
- end
- end
- return true
+local function readall(f)
+ local size=f:seek("end")
+ if size==0 then
+ return ""
+ elseif size<1024*1024 then
+ f:seek("set",0)
+ return f:read('*all')
+ else
+ local done=f:seek("set",0)
+ if size<1024*1024 then
+ step=1024*1024
+ elseif size>16*1024*1024 then
+ step=16*1024*1024
else
- return false
+ step=floor(size/(1024*1024))*1024*1024/8
end
+ local data={}
+ while true do
+ local r=f:read(step)
+ if not r then
+ return concat(data)
+ else
+ data[#data+1]=r
+ end
+ end
+ end
+end
+io.readall=readall
+function io.loaddata(filename,textmode)
+ local f=io.open(filename,(textmode and 'r') or 'rb')
+ if f then
+ local data=readall(f)
+ f:close()
+ if #data>0 then
+ return data
+ end
+ end
end
-
-local function identical(a,b) -- assumes same structure
- for ka, va in next, a do
- local vb = b[ka]
- if va == vb then
- -- same
- elseif type(va) == "table" and type(vb) == "table" then
- if not identical(va,vb) then
- return false
- end
- else
- return false
- end
+function io.savedata(filename,data,joiner)
+ local f=io.open(filename,"wb")
+ if f then
+ if type(data)=="table" then
+ f:write(concat(data,joiner or ""))
+ elseif type(data)=="function" then
+ data(f)
+ else
+ f:write(data or "")
end
+ f:close()
+ io.flush()
return true
+ else
+ return false
+ end
+end
+function io.loadlines(filename,n)
+ local f=io.open(filename,'r')
+ if not f then
+ elseif n then
+ local lines={}
+ for i=1,n do
+ local line=f:read("*lines")
+ if line then
+ lines[#lines+1]=line
+ else
+ break
+ end
+ end
+ f:close()
+ lines=concat(lines,"\n")
+ if #lines>0 then
+ return lines
+ end
+ else
+ local line=f:read("*line") or ""
+ f:close()
+ if #line>0 then
+ return line
+ end
+ end
+end
+function io.loadchunk(filename,n)
+ local f=io.open(filename,'rb')
+ if f then
+ local data=f:read(n or 1024)
+ f:close()
+ if #data>0 then
+ return data
+ end
+ end
end
-
-table.identical = identical
-table.are_equal = are_equal
-
--- maybe also make a combined one
-
-function table.compact(t)
- if t then
- for k,v in next, t do
- if not next(v) then
- t[k] = nil
- end
- end
- end
-end
-
-function table.contains(t, v)
- if t then
- for i=1, #t do
- if t[i] == v then
- return i
- end
- end
- end
+function io.exists(filename)
+ local f=io.open(filename)
+ if f==nil then
return false
+ else
+ f:close()
+ return true
+ end
end
-
-function table.count(t)
- local n = 0
- for k, v in next, t do
- n = n + 1
- end
- return n
+function io.size(filename)
+ local f=io.open(filename)
+ if f==nil then
+ return 0
+ else
+ local s=f:seek("end")
+ f:close()
+ return s
+ end
end
-
-function table.swapped(t,s) -- hash
- local n = { }
- if s then
- for k, v in next, s do
- n[k] = v
- end
+function io.noflines(f)
+ if type(f)=="string" then
+ local f=io.open(filename)
+ if f then
+ local n=f and io.noflines(f) or 0
+ f:close()
+ return n
+ else
+ return 0
end
- for k, v in next, t do
- n[v] = k
+ else
+ local n=0
+ for _ in f:lines() do
+ n=n+1
end
+ f:seek('set',0)
return n
+ end
+end
+local nextchar={
+ [ 4]=function(f)
+ return f:read(1,1,1,1)
+ end,
+ [ 2]=function(f)
+ return f:read(1,1)
+ end,
+ [ 1]=function(f)
+ return f:read(1)
+ end,
+ [-2]=function(f)
+ local a,b=f:read(1,1)
+ return b,a
+ end,
+ [-4]=function(f)
+ local a,b,c,d=f:read(1,1,1,1)
+ return d,c,b,a
+ end
+}
+function io.characters(f,n)
+ if f then
+ return nextchar[n or 1],f
+ end
end
-
-function table.reversed(t)
- if t then
- local tt, tn = { }, #t
- if tn > 0 then
- local ttn = 0
- for i=tn,1,-1 do
- ttn = ttn + 1
- tt[ttn] = t[i]
- end
- end
- return tt
+local nextbyte={
+ [4]=function(f)
+ local a,b,c,d=f:read(1,1,1,1)
+ if d then
+ return byte(a),byte(b),byte(c),byte(d)
+ end
+ end,
+ [3]=function(f)
+ local a,b,c=f:read(1,1,1)
+ if b then
+ return byte(a),byte(b),byte(c)
+ end
+ end,
+ [2]=function(f)
+ local a,b=f:read(1,1)
+ if b then
+ return byte(a),byte(b)
+ end
+ end,
+ [1]=function (f)
+ local a=f:read(1)
+ if a then
+ return byte(a)
+ end
+ end,
+ [-2]=function (f)
+ local a,b=f:read(1,1)
+ if b then
+ return byte(b),byte(a)
+ end
+ end,
+ [-3]=function(f)
+ local a,b,c=f:read(1,1,1)
+ if b then
+ return byte(c),byte(b),byte(a)
+ end
+ end,
+ [-4]=function(f)
+ local a,b,c,d=f:read(1,1,1,1)
+ if d then
+ return byte(d),byte(c),byte(b),byte(a)
end
+ end
+}
+function io.bytes(f,n)
+ if f then
+ return nextbyte[n or 1],f
+ else
+ return nil,nil
+ end
end
-
-function table.sequenced(t,sep,simple) -- hash only
- local s, n = { }, 0
- for k, v in sortedhash(t) do
- if simple then
- if v == true then
- n = n + 1
- s[n] = k
- elseif v and v~= "" then
- n = n + 1
- s[n] = k .. "=" .. tostring(v)
- end
- else
- n = n + 1
- s[n] = k .. "=" .. tostring(v)
+function io.ask(question,default,options)
+ while true do
+ io.write(question)
+ if options then
+ io.write(format(" [%s]",concat(options,"|")))
+ end
+ if default then
+ io.write(format(" [%s]",default))
+ end
+ io.write(format(" "))
+ io.flush()
+ local answer=io.read()
+ answer=gsub(answer,"^%s*(.*)%s*$","%1")
+ if answer=="" and default then
+ return default
+ elseif not options then
+ return answer
+ else
+ for k=1,#options do
+ if options[k]==answer then
+ return answer
+ end
+ end
+ local pattern="^"..answer
+ for k=1,#options do
+ local v=options[k]
+ if find(v,pattern) then
+ return v
end
+ end
end
- return concat(s, sep or " | ")
+ end
end
-
-function table.print(t,...)
- if type(t) ~= "table" then
- print(tostring(t))
- else
- table.tohandle(print,t,...)
- end
+local function readnumber(f,n,m)
+ if m then
+ f:seek("set",n)
+ n=m
+ end
+ if n==1 then
+ return byte(f:read(1))
+ elseif n==2 then
+ local a,b=byte(f:read(2),1,2)
+ return 256*a+b
+ elseif n==3 then
+ local a,b,c=byte(f:read(3),1,3)
+ return 256*256*a+256*b+c
+ elseif n==4 then
+ local a,b,c,d=byte(f:read(4),1,4)
+ return 256*256*256*a+256*256*b+256*c+d
+ elseif n==8 then
+ local a,b=readnumber(f,4),readnumber(f,4)
+ return 256*a+b
+ elseif n==12 then
+ local a,b,c=readnumber(f,4),readnumber(f,4),readnumber(f,4)
+ return 256*256*a+256*b+c
+ elseif n==-2 then
+ local b,a=byte(f:read(2),1,2)
+ return 256*a+b
+ elseif n==-3 then
+ local c,b,a=byte(f:read(3),1,3)
+ return 256*256*a+256*b+c
+ elseif n==-4 then
+ local d,c,b,a=byte(f:read(4),1,4)
+ return 256*256*256*a+256*256*b+256*c+d
+ elseif n==-8 then
+ local h,g,f,e,d,c,b,a=byte(f:read(8),1,8)
+ return 256*256*256*256*256*256*256*a+256*256*256*256*256*256*b+256*256*256*256*256*c+256*256*256*256*d+256*256*256*e+256*256*f+256*g+h
+ else
+ return 0
+ end
end
-
--- -- -- obsolete but we keep them for a while and might comment them later -- -- --
-
--- roughly: copy-loop : unpack : sub == 0.9 : 0.4 : 0.45 (so in critical apps, use unpack)
-
-function table.sub(t,i,j)
- return { unpack(t,i,j) }
+io.readnumber=readnumber
+function io.readstring(f,n,m)
+ if m then
+ f:seek("set",n)
+ n=m
+ end
+ local str=gsub(f:read(n),"\000","")
+ return str
end
+if not io.i_limiter then function io.i_limiter() end end
+if not io.o_limiter then function io.o_limiter() end end
--- slower than #t on indexed tables (#t only returns the size of the numerically indexed slice)
-
-function table.is_empty(t)
- return not t or not next(t)
-end
-function table.has_one_entry(t)
- return t and not next(t,next(t))
-end
+end -- of closure
--- new
+do -- create closure to overcome 200 locals limit
-function table.loweredkeys(t) -- maybe utf
- local l = { }
- for k, v in next, t do
- l[lower(k)] = v
- end
- return l
-end
+package.loaded["l-number"] = package.loaded["l-number"] or true
--- new, might move (maybe duplicate)
+-- original size: 4939, stripped down to: 2830
-function table.unique(old)
- local hash = { }
- local new = { }
- local n = 0
- for i=1,#old do
- local oi = old[i]
- if not hash[oi] then
- n = n + 1
- new[n] = oi
- hash[oi] = true
- end
+if not modules then modules={} end modules ['l-number']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local tostring,tonumber=tostring,tonumber
+local format,floor,match,rep=string.format,math.floor,string.match,string.rep
+local concat,insert=table.concat,table.insert
+local lpegmatch=lpeg.match
+number=number or {}
+local number=number
+if bit32 then
+ local btest,bor=bit32.btest,bit32.bor
+ function number.bit(p)
+ return 2^(p-1)
+ end
+ number.hasbit=btest
+ number.setbit=bor
+ function number.setbit(x,p)
+ return btest(x,p) and x or x+p
+ end
+ function number.clearbit(x,p)
+ return btest(x,p) and x-p or x
+ end
+else
+ function number.bit(p)
+ return 2^(p-1)
+ end
+ function number.hasbit(x,p)
+ return x%(p+p)>=p
+ end
+ function number.setbit(x,p)
+ return (x%(p+p)>=p) and x or x+p
+ end
+ function number.clearbit(x,p)
+ return (x%(p+p)>=p) and x-p or x
+ end
+end
+if bit32 then
+ local bextract=bit32.extract
+ local t={
+ "0","0","0","0","0","0","0","0",
+ "0","0","0","0","0","0","0","0",
+ "0","0","0","0","0","0","0","0",
+ "0","0","0","0","0","0","0","0",
+ }
+ function number.tobitstring(b,m)
+ local n=32
+ for i=0,31 do
+ local v=bextract(b,i)
+ local k=32-i
+ if v==1 then
+ n=k
+ t[k]="1"
+ else
+ t[k]="0"
+ end
end
- return new
-end
-
--- function table.sorted(t,...)
--- table.sort(t,...)
--- return t -- still sorts in-place
--- end
+ if m then
+ m=33-m*8
+ if m<1 then
+ m=1
+ end
+ return concat(t,"",m)
+ elseif n<8 then
+ return concat(t)
+ elseif n<16 then
+ return concat(t,"",9)
+ elseif n<24 then
+ return concat(t,"",17)
+ else
+ return concat(t,"",25)
+ end
+ end
+else
+ function number.tobitstring(n,m)
+ if n>0 then
+ local t={}
+ while n>0 do
+ insert(t,1,n%2>0 and 1 or 0)
+ n=floor(n/2)
+ end
+ local nn=8-#t%8
+ if nn>0 and nn<8 then
+ for i=1,nn do
+ insert(t,1,0)
+ end
+ end
+ if m then
+ m=m*8-#t
+ if m>0 then
+ insert(t,1,rep("0",m))
+ end
+ end
+ return concat(t)
+ elseif m then
+ rep("00000000",m)
+ else
+ return "00000000"
+ end
+ end
+end
+function number.valid(str,default)
+ return tonumber(str) or default or nil
+end
+function number.toevenhex(n)
+ local s=format("%X",n)
+ if #s%2==0 then
+ return s
+ else
+ return "0"..s
+ end
+end
+local one=lpeg.C(1-lpeg.S('')/tonumber)^1
+function number.toset(n)
+ return lpegmatch(one,tostring(n))
+end
+local function bits(n,i,...)
+ if n>0 then
+ local m=n%2
+ local n=floor(n/2)
+ if m>0 then
+ return bits(n,i+1,i,...)
+ else
+ return bits(n,i+1,...)
+ end
+ else
+ return...
+ end
+end
+function number.bits(n)
+ return { bits(n,1) }
+end
end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-lpeg'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
+package.loaded["l-set"] = package.loaded["l-set"] or true
--- a new lpeg fails on a #(1-P(":")) test and really needs a + P(-1)
-
-local lpeg = require("lpeg")
-
--- tracing (only used when we encounter a problem in integration of lpeg in luatex)
-
-local report = texio and texio.write_nl or print
-
--- local lpmatch = lpeg.match
--- local lpprint = lpeg.print
--- local lpp = lpeg.P
--- local lpr = lpeg.R
--- local lps = lpeg.S
--- local lpc = lpeg.C
--- local lpb = lpeg.B
--- local lpv = lpeg.V
--- local lpcf = lpeg.Cf
--- local lpcb = lpeg.Cb
--- local lpcg = lpeg.Cg
--- local lpct = lpeg.Ct
--- local lpcs = lpeg.Cs
--- local lpcc = lpeg.Cc
--- local lpcmt = lpeg.Cmt
--- local lpcarg = lpeg.Carg
-
--- function lpeg.match(l,...) report("LPEG MATCH") lpprint(l) return lpmatch(l,...) end
-
--- function lpeg.P (l) local p = lpp (l) report("LPEG P =") lpprint(l) return p end
--- function lpeg.R (l) local p = lpr (l) report("LPEG R =") lpprint(l) return p end
--- function lpeg.S (l) local p = lps (l) report("LPEG S =") lpprint(l) return p end
--- function lpeg.C (l) local p = lpc (l) report("LPEG C =") lpprint(l) return p end
--- function lpeg.B (l) local p = lpb (l) report("LPEG B =") lpprint(l) return p end
--- function lpeg.V (l) local p = lpv (l) report("LPEG V =") lpprint(l) return p end
--- function lpeg.Cf (l) local p = lpcf (l) report("LPEG Cf =") lpprint(l) return p end
--- function lpeg.Cb (l) local p = lpcb (l) report("LPEG Cb =") lpprint(l) return p end
--- function lpeg.Cg (l) local p = lpcg (l) report("LPEG Cg =") lpprint(l) return p end
--- function lpeg.Ct (l) local p = lpct (l) report("LPEG Ct =") lpprint(l) return p end
--- function lpeg.Cs (l) local p = lpcs (l) report("LPEG Cs =") lpprint(l) return p end
--- function lpeg.Cc (l) local p = lpcc (l) report("LPEG Cc =") lpprint(l) return p end
--- function lpeg.Cmt (l) local p = lpcmt (l) report("LPEG Cmt =") lpprint(l) return p end
--- function lpeg.Carg (l) local p = lpcarg(l) report("LPEG Carg =") lpprint(l) return p end
-
-local type = type
-local byte, char, gmatch = string.byte, string.char, string.gmatch
-
--- Beware, we predefine a bunch of patterns here and one reason for doing so
--- is that we get consistent behaviour in some of the visualizers.
-
-lpeg.patterns = lpeg.patterns or { } -- so that we can share
-local patterns = lpeg.patterns
-
-local P, R, S, V, match = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.match
-local Ct, C, Cs, Cc = lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc
-local lpegtype = lpeg.type
-
-local utfcharacters = string.utfcharacters
-local utfgmatch = unicode and unicode.utf8.gmatch
-
-local anything = P(1)
-local endofstring = P(-1)
-local alwaysmatched = P(true)
-
-patterns.anything = anything
-patterns.endofstring = endofstring
-patterns.beginofstring = alwaysmatched
-patterns.alwaysmatched = alwaysmatched
-
-local digit, sign = R('09'), S('+-')
-local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
-local newline = crlf + S("\r\n") -- cr + lf
-local escaped = P("\\") * anything
-local squote = P("'")
-local dquote = P('"')
-local space = P(" ")
-
-local utfbom_32_be = P('\000\000\254\255')
-local utfbom_32_le = P('\255\254\000\000')
-local utfbom_16_be = P('\255\254')
-local utfbom_16_le = P('\254\255')
-local utfbom_8 = P('\239\187\191')
-local utfbom = utfbom_32_be + utfbom_32_le
- + utfbom_16_be + utfbom_16_le
- + utfbom_8
-local utftype = utfbom_32_be / "utf-32-be" + utfbom_32_le / "utf-32-le"
- + utfbom_16_be / "utf-16-be" + utfbom_16_le / "utf-16-le"
- + utfbom_8 / "utf-8" + alwaysmatched / "unknown"
-
-local utf8next = R("\128\191")
-
-patterns.utf8one = R("\000\127")
-patterns.utf8two = R("\194\223") * utf8next
-patterns.utf8three = R("\224\239") * utf8next * utf8next
-patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
-patterns.utfbom = utfbom
-patterns.utftype = utftype
-
-local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
-local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
-
-patterns.utf8 = utf8char
-patterns.utf8char = utf8char
-patterns.validutf8 = validutf8char
-patterns.validutf8char = validutf8char
-
-patterns.digit = digit
-patterns.sign = sign
-patterns.cardinal = sign^0 * digit^1
-patterns.integer = sign^0 * digit^1
-patterns.float = sign^0 * digit^0 * P('.') * digit^1
-patterns.cfloat = sign^0 * digit^0 * P(',') * digit^1
-patterns.number = patterns.float + patterns.integer
-patterns.cnumber = patterns.cfloat + patterns.integer
-patterns.oct = P("0") * R("07")^1
-patterns.octal = patterns.oct
-patterns.HEX = P("0x") * R("09","AF")^1
-patterns.hex = P("0x") * R("09","af")^1
-patterns.hexadecimal = P("0x") * R("09","AF","af")^1
-patterns.lowercase = R("az")
-patterns.uppercase = R("AZ")
-patterns.letter = patterns.lowercase + patterns.uppercase
-patterns.space = space
-patterns.tab = P("\t")
-patterns.spaceortab = patterns.space + patterns.tab
-patterns.eol = S("\n\r")
-patterns.spacer = S(" \t\f\v") -- + char(0xc2, 0xa0) if we want utf (cf mail roberto)
-patterns.newline = newline
-patterns.emptyline = newline^1
-patterns.nonspacer = 1 - patterns.spacer
-patterns.whitespace = patterns.eol + patterns.spacer
-patterns.nonwhitespace = 1 - patterns.whitespace
-patterns.equal = P("=")
-patterns.comma = P(",")
-patterns.commaspacer = P(",") * patterns.spacer^0
-patterns.period = P(".")
-patterns.colon = P(":")
-patterns.semicolon = P(";")
-patterns.underscore = P("_")
-patterns.escaped = escaped
-patterns.squote = squote
-patterns.dquote = dquote
-patterns.nosquote = (escaped + (1-squote))^0
-patterns.nodquote = (escaped + (1-dquote))^0
-patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"")
-patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
-patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
-patterns.unspacer = ((patterns.spacer^1)/"")^0
-
-patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
-patterns.beginline = #(1-newline)
-
--- print(string.unquoted("test"))
--- print(string.unquoted([["t\"est"]]))
--- print(string.unquoted([["t\"est"x]]))
--- print(string.unquoted("\'test\'"))
--- print(string.unquoted('"test"'))
--- print(string.unquoted('"test"'))
-
-function lpeg.anywhere(pattern) --slightly adapted from website
- return P { P(pattern) + 1 * V(1) } -- why so complex?
-end
-
-function lpeg.splitter(pattern, action)
- return (((1-P(pattern))^1)/action+1)^0
-end
-
-function lpeg.tsplitter(pattern, action)
- return Ct((((1-P(pattern))^1)/action+1)^0)
-end
-
--- probleem: separator can be lpeg and that does not hash too well, but
--- it's quite okay as the key is then not garbage collected
-
-local splitters_s, splitters_m, splitters_t = { }, { }, { }
-
-local function splitat(separator,single)
- local splitter = (single and splitters_s[separator]) or splitters_m[separator]
- if not splitter then
- separator = P(separator)
- local other = C((1 - separator)^0)
- if single then
- local any = anything
- splitter = other * (separator * C(any^0) + "") -- ?
- splitters_s[separator] = splitter
- else
- splitter = other * (separator * other)^0
- splitters_m[separator] = splitter
- end
- end
- return splitter
-end
+-- original size: 1923, stripped down to: 1133
-local function tsplitat(separator)
- local splitter = splitters_t[separator]
- if not splitter then
- splitter = Ct(splitat(separator))
- splitters_t[separator] = splitter
+if not modules then modules={} end modules ['l-set']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+set=set or {}
+local nums={}
+local tabs={}
+local concat=table.concat
+local next,type=next,type
+set.create=table.tohash
+function set.tonumber(t)
+ if next(t) then
+ local s=""
+ for k,v in next,t do
+ if v then
+ s=s.." "..k
+ end
+ end
+ local n=nums[s]
+ if not n then
+ n=#tabs+1
+ tabs[n]=t
+ nums[s]=n
end
- return splitter
+ return n
+ else
+ return 0
+ end
end
-
-lpeg.splitat = splitat
-lpeg.tsplitat = tsplitat
-
-function string.splitup(str,separator)
- if not separator then
- separator = ","
- end
- return match(splitters_m[separator] or splitat(separator),str)
+function set.totable(n)
+ if n==0 then
+ return {}
+ else
+ return tabs[n] or {}
+ end
end
-
-
-local cache = { }
-
-function lpeg.split(separator,str)
- local c = cache[separator]
- if not c then
- c = tsplitat(separator)
- cache[separator] = c
+function set.tolist(n)
+ if n==0 or not tabs[n] then
+ return ""
+ else
+ local t,n={},0
+ for k,v in next,tabs[n] do
+ if v then
+ n=n+1
+ t[n]=k
+ end
end
- return match(c,str)
+ return concat(t," ")
+ end
end
-
-function string.split(str,separator)
- local c = cache[separator]
- if not c then
- c = tsplitat(separator)
- cache[separator] = c
- end
- return match(c,str)
+function set.contains(n,s)
+ if type(n)=="table" then
+ return n[s]
+ elseif n==0 then
+ return false
+ else
+ local t=tabs[n]
+ return t and t[s]
+ end
end
-local spacing = patterns.spacer^0 * newline -- sort of strip
-local empty = spacing * Cc("")
-local nonempty = Cs((1-spacing)^1) * spacing^-1
-local content = (empty + nonempty)^1
-patterns.textline = content
+end -- of closure
+do -- create closure to overcome 200 locals limit
-local linesplitter = tsplitat(newline)
+package.loaded["l-os"] = package.loaded["l-os"] or true
-patterns.linesplitter = linesplitter
+-- original size: 13692, stripped down to: 8406
-function string.splitlines(str)
- return match(linesplitter,str)
+if not modules then modules={} end modules ['l-os']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local os=os
+local date,time=os.date,os.time
+local find,format,gsub,upper,gmatch=string.find,string.format,string.gsub,string.upper,string.gmatch
+local concat=table.concat
+local random,ceil,randomseed=math.random,math.ceil,math.randomseed
+local rawget,rawset,type,getmetatable,setmetatable,tonumber,tostring=rawget,rawset,type,getmetatable,setmetatable,tonumber,tostring
+math.initialseed=tonumber(string.sub(string.reverse(tostring(ceil(socket and socket.gettime()*10000 or time()))),1,6))
+randomseed(math.initialseed)
+if not os.__getenv__ then
+ os.__getenv__=os.getenv
+ os.__setenv__=os.setenv
+ if os.env then
+ local osgetenv=os.getenv
+ local ossetenv=os.setenv
+ local osenv=os.env local _=osenv.PATH
+ function os.setenv(k,v)
+ if v==nil then
+ v=""
+ end
+ local K=upper(k)
+ osenv[K]=v
+ if type(v)=="table" then
+ v=concat(v,";")
+ end
+ ossetenv(K,v)
+ end
+ function os.getenv(k)
+ local K=upper(k)
+ local v=osenv[K] or osenv[k] or osgetenv(K) or osgetenv(k)
+ if v=="" then
+ return nil
+ else
+ return v
+ end
+ end
+ else
+ local ossetenv=os.setenv
+ local osgetenv=os.getenv
+ local osenv={}
+ function os.setenv(k,v)
+ if v==nil then
+ v=""
+ end
+ local K=upper(k)
+ osenv[K]=v
+ end
+ function os.getenv(k)
+ local K=upper(k)
+ local v=osenv[K] or osgetenv(K) or osgetenv(k)
+ if v=="" then
+ return nil
+ else
+ return v
+ end
+ end
+ local function __index(t,k)
+ return os.getenv(k)
+ end
+ local function __newindex(t,k,v)
+ os.setenv(k,v)
+ end
+ os.env={}
+ setmetatable(os.env,{ __index=__index,__newindex=__newindex } )
+ end
end
-
-local utflinesplitter = utfbom^-1 * tsplitat(newline)
-
-patterns.utflinesplitter = utflinesplitter
-
-function string.utfsplitlines(str)
- return match(utflinesplitter,str or "")
+local execute,spawn,exec,iopopen,ioflush=os.execute,os.spawn or os.execute,os.exec or os.execute,io.popen,io.flush
+function os.execute(...) ioflush() return execute(...) end
+function os.spawn (...) ioflush() return spawn (...) end
+function os.exec (...) ioflush() return exec (...) end
+function io.popen (...) ioflush() return iopopen(...) end
+function os.resultof(command)
+ local handle=io.popen(command,"r")
+ return handle and handle:read("*all") or ""
end
-
-
-local cache = { }
-
-function lpeg.checkedsplit(separator,str)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
+if not io.fileseparator then
+ if find(os.getenv("PATH"),";") then
+ io.fileseparator,io.pathseparator,os.type="\\",";",os.type or "mswin"
+ else
+ io.fileseparator,io.pathseparator,os.type="/",":",os.type or "unix"
+ end
+end
+os.type=os.type or (io.pathseparator==";" and "windows") or "unix"
+os.name=os.name or (os.type=="windows" and "mswin" ) or "linux"
+if os.type=="windows" then
+ os.libsuffix,os.binsuffix,os.binsuffixes='dll','exe',{ 'exe','cmd','bat' }
+else
+ os.libsuffix,os.binsuffix,os.binsuffixes='so','',{ '' }
+end
+local launchers={
+ windows="start %s",
+ macosx="open %s",
+ unix="$BROWSER %s &> /dev/null &",
+}
+function os.launch(str)
+ os.execute(format(launchers[os.name] or launchers.unix,str))
+end
+if not os.times then
+ function os.times()
+ return {
+ utime=os.gettimeofday(),
+ stime=0,
+ cutime=0,
+ cstime=0,
+ }
+ end
+end
+os.gettimeofday=os.gettimeofday or os.clock
+local startuptime=os.gettimeofday()
+function os.runtime()
+ return os.gettimeofday()-startuptime
+end
+os.resolvers=os.resolvers or {}
+local resolvers=os.resolvers
+setmetatable(os,{ __index=function(t,k)
+ local r=resolvers[k]
+ return r and r(t,k) or nil
+end })
+local name,platform=os.name or "linux",os.getenv("MTX_PLATFORM") or ""
+local function guess()
+ local architecture=os.resultof("uname -m") or ""
+ if architecture~="" then
+ return architecture
+ end
+ architecture=os.getenv("HOSTTYPE") or ""
+ if architecture~="" then
+ return architecture
+ end
+ return os.resultof("echo $HOSTTYPE") or ""
+end
+if platform~="" then
+ os.platform=platform
+elseif os.type=="windows" then
+ function os.resolvers.platform(t,k)
+ local platform,architecture="",os.getenv("PROCESSOR_ARCHITECTURE") or ""
+ if find(architecture,"AMD64") then
+ platform="mswin-64"
+ else
+ platform="mswin"
+ end
+ os.setenv("MTX_PLATFORM",platform)
+ os.platform=platform
+ return platform
+ end
+elseif name=="linux" then
+ function os.resolvers.platform(t,k)
+ local platform,architecture="",os.getenv("HOSTTYPE") or os.resultof("uname -m") or ""
+ if find(architecture,"x86_64") then
+ platform="linux-64"
+ elseif find(architecture,"ppc") then
+ platform="linux-ppc"
+ else
+ platform="linux"
+ end
+ os.setenv("MTX_PLATFORM",platform)
+ os.platform=platform
+ return platform
+ end
+elseif name=="macosx" then
+ function os.resolvers.platform(t,k)
+ local platform,architecture="",os.resultof("echo $HOSTTYPE") or ""
+ if architecture=="" then
+ platform="osx-intel"
+ elseif find(architecture,"i386") then
+ platform="osx-intel"
+ elseif find(architecture,"x86_64") then
+ platform="osx-64"
+ else
+ platform="osx-ppc"
+ end
+ os.setenv("MTX_PLATFORM",platform)
+ os.platform=platform
+ return platform
+ end
+elseif name=="sunos" then
+ function os.resolvers.platform(t,k)
+ local platform,architecture="",os.resultof("uname -m") or ""
+ if find(architecture,"sparc") then
+ platform="solaris-sparc"
+ else
+ platform="solaris-intel"
+ end
+ os.setenv("MTX_PLATFORM",platform)
+ os.platform=platform
+ return platform
+ end
+elseif name=="freebsd" then
+ function os.resolvers.platform(t,k)
+ local platform,architecture="",os.resultof("uname -m") or ""
+ if find(architecture,"amd64") then
+ platform="freebsd-amd64"
+ else
+ platform="freebsd"
+ end
+ os.setenv("MTX_PLATFORM",platform)
+ os.platform=platform
+ return platform
+ end
+elseif name=="kfreebsd" then
+ function os.resolvers.platform(t,k)
+ local platform,architecture="",os.getenv("HOSTTYPE") or os.resultof("uname -m") or ""
+ if find(architecture,"x86_64") then
+ platform="kfreebsd-amd64"
+ else
+ platform="kfreebsd-i386"
end
- return match(c,str)
+ os.setenv("MTX_PLATFORM",platform)
+ os.platform=platform
+ return platform
+ end
+else
+ function os.resolvers.platform(t,k)
+ local platform="linux"
+ os.setenv("MTX_PLATFORM",platform)
+ os.platform=platform
+ return platform
+ end
+end
+local t={ 8,9,"a","b" }
+function os.uuid()
+ return format("%04x%04x-4%03x-%s%03x-%04x-%04x%04x%04x",
+ random(0xFFFF),random(0xFFFF),
+ random(0x0FFF),
+ t[ceil(random(4))] or 8,random(0x0FFF),
+ random(0xFFFF),
+ random(0xFFFF),random(0xFFFF),random(0xFFFF)
+ )
end
-
-function string.checkedsplit(str,separator)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
+local d
+function os.timezone(delta)
+ d=d or tonumber(tonumber(date("%H")-date("!%H")))
+ if delta then
+ if d>0 then
+ return format("+%02i:00",d)
+ else
+ return format("-%02i:00",-d)
+ end
+ else
+ return 1
+ end
+end
+local timeformat=format("%%s%s",os.timezone(true))
+local dateformat="!%Y-%m-%d %H:%M:%S"
+function os.fulltime(t,default)
+ t=tonumber(t) or 0
+ if t>0 then
+ elseif default then
+ return default
+ else
+ t=nil
+ end
+ return format(timeformat,date(dateformat,t))
+end
+local dateformat="%Y-%m-%d %H:%M:%S"
+function os.localtime(t,default)
+ t=tonumber(t) or 0
+ if t>0 then
+ elseif default then
+ return default
+ else
+ t=nil
+ end
+ return date(dateformat,t)
+end
+function os.converttime(t,default)
+ local t=tonumber(t)
+ if t and t>0 then
+ return date(dateformat,t)
+ else
+ return default or "-"
+ end
+end
+local memory={}
+local function which(filename)
+ local fullname=memory[filename]
+ if fullname==nil then
+ local suffix=file.suffix(filename)
+ local suffixes=suffix=="" and os.binsuffixes or { suffix }
+ for directory in gmatch(os.getenv("PATH"),"[^"..io.pathseparator.."]+") do
+ local df=file.join(directory,filename)
+ for i=1,#suffixes do
+ local dfs=file.addsuffix(df,suffixes[i])
+ if io.exists(dfs) then
+ fullname=dfs
+ break
+ end
+ end
end
- return match(c,str)
+ if not fullname then
+ fullname=false
+ end
+ memory[filename]=fullname
+ end
+ return fullname
+end
+os.which=which
+os.where=which
+function os.today()
+ return date("!*t")
+end
+function os.now()
+ return date("!%Y-%m-%d %H:%M:%S")
+end
+if not os.sleep and socket then
+ os.sleep=socket.sleep
end
-local function f2(s) local c1, c2 = byte(s,1,2) return c1 * 64 + c2 - 12416 end
-local function f3(s) local c1, c2, c3 = byte(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
-local function f4(s) local c1, c2, c3, c4 = byte(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
-
-local utf8byte = patterns.utf8one/byte + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
-
-patterns.utf8byte = utf8byte
+end -- of closure
+do -- create closure to overcome 200 locals limit
+package.loaded["l-file"] = package.loaded["l-file"] or true
-local cache = { }
+-- original size: 16648, stripped down to: 9051
-function lpeg.stripper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs(((S(str)^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs(((str^1)/"" + 1)^0)
- end
+if not modules then modules={} end modules ['l-file']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+file=file or {}
+local file=file
+if not lfs then
+ lfs=optionalrequire("lfs")
+end
+if not lfs then
+ lfs={
+ getcurrentdir=function()
+ return "."
+ end,
+ attributes=function()
+ return nil
+ end,
+ isfile=function(name)
+ local f=io.open(name,'rb')
+ if f then
+ f:close()
+ return true
+ end
+ end,
+ isdir=function(name)
+ print("you need to load lfs")
+ return false
+ end
+ }
+elseif not lfs.isfile then
+ local attributes=lfs.attributes
+ function lfs.isdir(name)
+ return attributes(name,"mode")=="directory"
+ end
+ function lfs.isfile(name)
+ return attributes(name,"mode")=="file"
+ end
+end
+local insert,concat=table.insert,table.concat
+local match=string.match
+local lpegmatch=lpeg.match
+local getcurrentdir,attributes=lfs.currentdir,lfs.attributes
+local checkedsplit=string.checkedsplit
+local P,R,S,C,Cs,Cp,Cc,Ct=lpeg.P,lpeg.R,lpeg.S,lpeg.C,lpeg.Cs,lpeg.Cp,lpeg.Cc,lpeg.Ct
+local colon=P(":")
+local period=P(".")
+local periods=P("..")
+local fwslash=P("/")
+local bwslash=P("\\")
+local slashes=S("\\/")
+local noperiod=1-period
+local noslashes=1-slashes
+local name=noperiod^1
+local suffix=period/""*(1-period-slashes)^1*-1
+local pattern=C((1-(slashes^1*noslashes^1*-1))^1)*P(1)
+local function pathpart(name,default)
+ return name and lpegmatch(pattern,name) or default or ""
+end
+local pattern=(noslashes^0*slashes)^1*C(noslashes^1)*-1
+local function basename(name)
+ return name and lpegmatch(pattern,name) or name
end
-
-local cache = { }
-
-function lpeg.keeper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs((((1-S(str))^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
+local pattern=(noslashes^0*slashes^1)^0*Cs((1-suffix)^1)*suffix^0
+local function nameonly(name)
+ return name and lpegmatch(pattern,name) or name
+end
+local pattern=(noslashes^0*slashes)^0*(noperiod^1*period)^1*C(noperiod^1)*-1
+local function suffixonly(name)
+ return name and lpegmatch(pattern,name) or ""
+end
+file.pathpart=pathpart
+file.basename=basename
+file.nameonly=nameonly
+file.suffixonly=suffixonly
+file.suffix=suffixonly
+file.dirname=pathpart
+file.extname=suffixonly
+local drive=C(R("az","AZ"))*colon
+local path=C((noslashes^0*slashes)^0)
+local suffix=period*C(P(1-period)^0*P(-1))
+local base=C((1-suffix)^0)
+local rest=C(P(1)^0)
+drive=drive+Cc("")
+path=path+Cc("")
+base=base+Cc("")
+suffix=suffix+Cc("")
+local pattern_a=drive*path*base*suffix
+local pattern_b=path*base*suffix
+local pattern_c=C(drive*path)*C(base*suffix)
+local pattern_d=path*rest
+function file.splitname(str,splitdrive)
+ if not str then
+ elseif splitdrive then
+ return lpegmatch(pattern_a,str)
+ else
+ return lpegmatch(pattern_b,str)
+ end
+end
+function file.splitbase(str)
+ return str and lpegmatch(pattern_d,str)
+end
+function file.nametotable(str,splitdrive)
+ if str then
+ local path,drive,subpath,name,base,suffix=lpegmatch(pattern_c,str)
+ if splitdrive then
+ return {
+ path=path,
+ drive=drive,
+ subpath=subpath,
+ name=name,
+ base=base,
+ suffix=suffix,
+ }
else
- return Cs((((1-str)^1)/"" + 1)^0)
+ return {
+ path=path,
+ name=name,
+ base=base,
+ suffix=suffix,
+ }
+ end
+ end
+end
+local pattern=Cs(((period*(1-period-slashes)^1*-1)/""+1)^1)
+function file.removesuffix(name)
+ return name and lpegmatch(pattern,name)
+end
+local suffix=period/""*(1-period-slashes)^1*-1
+local pattern=Cs((noslashes^0*slashes^1)^0*((1-suffix)^1))*Cs(suffix)
+function file.addsuffix(filename,suffix,criterium)
+ if not filename or not suffix or suffix=="" then
+ return filename
+ elseif criterium==true then
+ return filename.."."..suffix
+ elseif not criterium then
+ local n,s=lpegmatch(pattern,filename)
+ if not s or s=="" then
+ return filename.."."..suffix
+ else
+ return filename
+ end
+ else
+ local n,s=lpegmatch(pattern,filename)
+ if s and s~="" then
+ local t=type(criterium)
+ if t=="table" then
+ for i=1,#criterium do
+ if s==criterium[i] then
+ return filename
+ end
+ end
+ elseif t=="string" then
+ if s==criterium then
+ return filename
+ end
+ end
end
+ return (n or filename).."."..suffix
+ end
end
-
-function lpeg.frontstripper(str) -- or pattern (yet undocumented)
- return (P(str) + P(true)) * Cs(P(1)^0)
+local suffix=period*(1-period-slashes)^1*-1
+local pattern=Cs((1-suffix)^0)
+function file.replacesuffix(name,suffix)
+ if name and suffix and suffix~="" then
+ return lpegmatch(pattern,name).."."..suffix
+ else
+ return name
+ end
end
-
-function lpeg.endstripper(str) -- or pattern (yet undocumented)
- return Cs((1 - P(str) * P(-1))^0)
+local reslasher=lpeg.replacer(P("\\"),"/")
+function file.reslash(str)
+ return str and lpegmatch(reslasher,str)
end
-
--- Just for fun I looked at the used bytecode and
--- p = (p and p + pp) or pp gets one more (testset).
-
-function lpeg.replacer(one,two)
- if type(one) == "table" then
- local no = #one
- if no > 0 then
- local p
- for i=1,no do
- local o = one[i]
- local pp = P(o[1]) / o[2]
- if p then
- p = p + pp
- else
- p = pp
- end
- end
- return Cs((p + 1)^0)
- end
- else
- two = two or ""
- return Cs((P(one)/two + 1)^0)
+function file.is_writable(name)
+ if not name then
+ elseif lfs.isdir(name) then
+ name=name.."/m_t_x_t_e_s_t.tmp"
+ local f=io.open(name,"wb")
+ if f then
+ f:close()
+ os.remove(name)
+ return true
end
-end
-
-local splitters_f, splitters_s = { }, { }
-
-function lpeg.firstofsplit(separator) -- always return value
- local splitter = splitters_f[separator]
- if not splitter then
- separator = P(separator)
- splitter = C((1 - separator)^0)
- splitters_f[separator] = splitter
+ elseif lfs.isfile(name) then
+ local f=io.open(name,"ab")
+ if f then
+ f:close()
+ return true
+ end
+ else
+ local f=io.open(name,"ab")
+ if f then
+ f:close()
+ os.remove(name)
+ return true
end
- return splitter
+ end
+ return false
end
-
-function lpeg.secondofsplit(separator) -- nil if not split
- local splitter = splitters_s[separator]
- if not splitter then
- separator = P(separator)
- splitter = (1 - separator)^0 * separator * C(anything^0)
- splitters_s[separator] = splitter
+local readable=P("r")*Cc(true)
+function file.is_readable(name)
+ if name then
+ local a=attributes(name)
+ return a and lpegmatch(readable,a.permissions) or false
+ else
+ return false
+ end
+end
+file.isreadable=file.is_readable
+file.iswritable=file.is_writable
+function file.size(name)
+ if name then
+ local a=attributes(name)
+ return a and a.size or 0
+ else
+ return 0
+ end
+end
+function file.splitpath(str,separator)
+ return str and checkedsplit(lpegmatch(reslasher,str),separator or io.pathseparator)
+end
+function file.joinpath(tab,separator)
+ return tab and concat(tab,separator or io.pathseparator)
+end
+local stripper=Cs(P(fwslash)^0/""*reslasher)
+local isnetwork=fwslash*fwslash*(1-fwslash)+(1-fwslash-colon)^1*colon
+local isroot=fwslash^1*-1
+local hasroot=fwslash^1
+local deslasher=lpeg.replacer(S("\\/")^1,"/")
+function file.join(...)
+ local lst={... }
+ local one=lst[1]
+ if lpegmatch(isnetwork,one) then
+ local two=lpegmatch(deslasher,concat(lst,"/",2))
+ return one.."/"..two
+ elseif lpegmatch(isroot,one) then
+ local two=lpegmatch(deslasher,concat(lst,"/",2))
+ if lpegmatch(hasroot,two) then
+ return two
+ else
+ return "/"..two
+ end
+ elseif one=="" then
+ return lpegmatch(stripper,concat(lst,"/",2))
+ else
+ return lpegmatch(deslasher,concat(lst,"/"))
+ end
+end
+local drivespec=R("az","AZ")^1*colon
+local anchors=fwslash+drivespec
+local untouched=periods+(1-period)^1*P(-1)
+local splitstarter=(Cs(drivespec*(bwslash/"/"+fwslash)^0)+Cc(false))*Ct(lpeg.splitat(S("/\\")^1))
+local absolute=fwslash
+function file.collapsepath(str,anchor)
+ if not str then
+ return
+ end
+ if anchor and not lpegmatch(anchors,str) then
+ str=getcurrentdir().."/"..str
+ end
+ if str=="" or str=="." then
+ return "."
+ elseif lpegmatch(untouched,str) then
+ return lpegmatch(reslasher,str)
+ end
+ local starter,oldelements=lpegmatch(splitstarter,str)
+ local newelements={}
+ local i=#oldelements
+ while i>0 do
+ local element=oldelements[i]
+ if element=='.' then
+ elseif element=='..' then
+ local n=i-1
+ while n>0 do
+ local element=oldelements[n]
+ if element~='..' and element~='.' then
+ oldelements[n]='.'
+ break
+ else
+ n=n-1
+ end
+ end
+ if n<1 then
+ insert(newelements,1,'..')
+ end
+ elseif element~="" then
+ insert(newelements,1,element)
+ end
+ i=i-1
+ end
+ if #newelements==0 then
+ return starter or "."
+ elseif starter then
+ return starter..concat(newelements,'/')
+ elseif lpegmatch(absolute,str) then
+ return "/"..concat(newelements,'/')
+ else
+ return concat(newelements,'/')
+ end
+end
+local validchars=R("az","09","AZ","--","..")
+local pattern_a=lpeg.replacer(1-validchars)
+local pattern_a=Cs((validchars+P(1)/"-")^1)
+local whatever=P("-")^0/""
+local pattern_b=Cs(whatever*(1-whatever*-1)^1)
+function file.robustname(str,strict)
+ if str then
+ str=lpegmatch(pattern_a,str) or str
+ if strict then
+ return lpegmatch(pattern_b,str) or str
+ else
+ return str
end
- return splitter
+ end
end
-
-function lpeg.balancer(left,right)
- left, right = P(left), P(right)
- return P { left * ((1 - left - right) + V(1))^0 * right }
+file.readdata=io.loaddata
+file.savedata=io.savedata
+function file.copy(oldname,newname)
+ if oldname and newname then
+ local data=io.loaddata(oldname)
+ if data and data~="" then
+ file.savedata(newname,data)
+ end
+ end
+end
+local letter=R("az","AZ")+S("_-+")
+local separator=P("://")
+local qualified=period^0*fwslash+letter*colon+letter^1*separator+letter^1*fwslash
+local rootbased=fwslash+letter*colon
+lpeg.patterns.qualified=qualified
+lpeg.patterns.rootbased=rootbased
+function file.is_qualified_path(filename)
+ return filename and lpegmatch(qualified,filename)~=nil
+end
+function file.is_rootbased_path(filename)
+ return filename and lpegmatch(rootbased,filename)~=nil
+end
+function file.strip(name,dir)
+ if name then
+ local b,a=match(name,"^(.-)"..dir.."(.*)$")
+ return a~="" and a or name
+ end
end
+end -- of closure
-local nany = utf8char/""
+do -- create closure to overcome 200 locals limit
-function lpeg.counter(pattern)
- pattern = Cs((P(pattern)/" " + nany)^0)
- return function(str)
- return #match(pattern,str)
- end
-end
+package.loaded["l-md5"] = package.loaded["l-md5"] or true
-if utfgmatch then
+-- original size: 3760, stripped down to: 2088
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local n = 0
- for _ in utfgmatch(str,what) do
- n = n + 1
- end
- return n
- else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
- end
+if not modules then modules={} end modules ['l-md5']={
+ version=1.001,
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+if not md5 then
+ md5=optionalrequire("md5")
+end
+if not md5 then
+ md5={
+ sum=function(str) print("error: md5 is not loaded (sum ignored)") return str end,
+ sumhexa=function(str) print("error: md5 is not loaded (sumhexa ignored)") return str end,
+ }
+end
+local md5,file=md5,file
+local gsub,format,byte=string.gsub,string.format,string.byte
+local md5sum=md5.sum
+local function convert(str,fmt)
+ return (gsub(md5sum(str),".",function(chr) return format(fmt,byte(chr)) end))
+end
+if not md5.HEX then function md5.HEX(str) return convert(str,"%02X") end end
+if not md5.hex then function md5.hex(str) return convert(str,"%02x") end end
+if not md5.dec then function md5.dec(str) return convert(str,"%03i") end end
+function file.needsupdating(oldname,newname,threshold)
+ local oldtime=lfs.attributes(oldname,"modification")
+ if oldtime then
+ local newtime=lfs.attributes(newname,"modification")
+ if not newtime then
+ return true
+ elseif newtime>=oldtime then
+ return false
+ elseif oldtime-newtime<(threshold or 1) then
+ return false
+ else
+ return true
+ end
+ else
+ return false
+ end
+end
+file.needs_updating=file.needsupdating
+function file.syncmtimes(oldname,newname)
+ local oldtime=lfs.attributes(oldname,"modification")
+ if oldtime and lfs.isfile(newname) then
+ lfs.touch(newname,oldtime,oldtime)
+ end
+end
+function file.checksum(name)
+ if md5 then
+ local data=io.loaddata(name)
+ if data then
+ return md5.HEX(data)
end
+ end
+ return nil
+end
+function file.loadchecksum(name)
+ if md5 then
+ local data=io.loaddata(name..".md5")
+ return data and (gsub(data,"%s",""))
+ end
+ return nil
+end
+function file.savechecksum(name,checksum)
+ if not checksum then checksum=file.checksum(name) end
+ if checksum then
+ io.savedata(name..".md5",checksum)
+ return checksum
+ end
+ return nil
+end
-else
- local cache = { }
+end -- of closure
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local p = cache[what]
- if not p then
- p = Cs((P(what)/" " + nany)^0)
- cache[p] = p
- end
- return #match(p,str)
- else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
- end
- end
+do -- create closure to overcome 200 locals limit
-end
+package.loaded["l-url"] = package.loaded["l-url"] or true
-local patterns_escapes = { -- also defines in l-string
- ["%"] = "%%",
- ["."] = "%.",
- ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
- ["["] = "%[", ["]"] = "%]",
- ["("] = "%)", [")"] = "%)",
- -- ["{"] = "%{", ["}"] = "%}"
- -- ["^"] = "%^", ["$"] = "%$",
-}
+-- original size: 11806, stripped down to: 5417
-local simple_escapes = { -- also defines in l-string
- ["-"] = "%-",
- ["."] = "%.",
- ["?"] = ".",
- ["*"] = ".*",
+if not modules then modules={} end modules ['l-url']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
}
-
-local p = Cs((S("-.+*%()[]") / patterns_escapes + anything)^0)
-local s = Cs((S("-.+*%()[]") / simple_escapes + anything)^0)
-
-function string.escapedpattern(str,simple)
- return match(simple and s or p,str)
+local char,format,byte=string.char,string.format,string.byte
+local concat=table.concat
+local tonumber,type=tonumber,type
+local P,C,R,S,Cs,Cc,Ct,Cf,Cg,V=lpeg.P,lpeg.C,lpeg.R,lpeg.S,lpeg.Cs,lpeg.Cc,lpeg.Ct,lpeg.Cf,lpeg.Cg,lpeg.V
+local lpegmatch,lpegpatterns,replacer=lpeg.match,lpeg.patterns,lpeg.replacer
+url=url or {}
+local url=url
+local tochar=function(s) return char(tonumber(s,16)) end
+local colon=P(":")
+local qmark=P("?")
+local hash=P("#")
+local slash=P("/")
+local percent=P("%")
+local endofstring=P(-1)
+local hexdigit=R("09","AF","af")
+local plus=P("+")
+local nothing=Cc("")
+local escapedchar=(percent*C(hexdigit*hexdigit))/tochar
+local escaped=(plus/" ")+escapedchar
+local noslash=P("/")/""
+local schemestr=Cs((escaped+(1-colon-slash-qmark-hash))^2)
+local authoritystr=Cs((escaped+(1- slash-qmark-hash))^0)
+local pathstr=Cs((escaped+(1- qmark-hash))^0)
+local querystr=Cs(((1- hash))^0)
+local fragmentstr=Cs((escaped+(1- endofstring))^0)
+local scheme=schemestr*colon+nothing
+local authority=slash*slash*authoritystr+nothing
+local path=slash*pathstr+nothing
+local query=qmark*querystr+nothing
+local fragment=hash*fragmentstr+nothing
+local validurl=scheme*authority*path*query*fragment
+local parser=Ct(validurl)
+lpegpatterns.url=validurl
+lpegpatterns.urlsplitter=parser
+local escapes={}
+setmetatable(escapes,{ __index=function(t,k)
+ local v=format("%%%02X",byte(k))
+ t[k]=v
+ return v
+end })
+local escaper=Cs((R("09","AZ","az")^1+P(" ")/"%%20"+S("-./_")^1+P(1)/escapes)^0)
+local unescaper=Cs((escapedchar+1)^0)
+lpegpatterns.urlunescaped=escapedchar
+lpegpatterns.urlescaper=escaper
+lpegpatterns.urlunescaper=unescaper
+local function split(str)
+ return (type(str)=="string" and lpegmatch(parser,str)) or str
+end
+local isscheme=schemestr*colon*slash*slash
+local function hasscheme(str)
+ if str then
+ local scheme=lpegmatch(isscheme,str)
+ return scheme~="" and scheme or false
+ else
+ return false
+ end
+end
+local rootletter=R("az","AZ")+S("_-+")
+local separator=P("://")
+local qualified=P(".")^0*P("/")+rootletter*P(":")+rootletter^1*separator+rootletter^1*P("/")
+local rootbased=P("/")+rootletter*P(":")
+local barswapper=replacer("|",":")
+local backslashswapper=replacer("\\","/")
+local equal=P("=")
+local amp=P("&")
+local key=Cs(((escapedchar+1)-equal )^0)
+local value=Cs(((escapedchar+1)-amp -endofstring)^0)
+local splitquery=Cf (Ct("")*P { "sequence",
+ sequence=V("pair")*(amp*V("pair"))^0,
+ pair=Cg(key*equal*value),
+},rawset)
+local function hashed(str)
+ if str=="" then
+ return {
+ scheme="invalid",
+ original=str,
+ }
+ end
+ local s=split(str)
+ local rawscheme=s[1]
+ local rawquery=s[4]
+ local somescheme=rawscheme~=""
+ local somequery=rawquery~=""
+ if not somescheme and not somequery then
+ s={
+ scheme="file",
+ authority="",
+ path=str,
+ query="",
+ fragment="",
+ original=str,
+ noscheme=true,
+ filename=str,
+ }
+ else
+ local authority,path,filename=s[2],s[3]
+ if authority=="" then
+ filename=path
+ elseif path=="" then
+ filename=""
+ else
+ filename=authority.."/"..path
+ end
+ s={
+ scheme=rawscheme,
+ authority=authority,
+ path=path,
+ query=lpegmatch(unescaper,rawquery),
+ queries=lpegmatch(splitquery,rawquery),
+ fragment=s[5],
+ original=str,
+ noscheme=false,
+ filename=filename,
+ }
+ end
+ return s
+end
+url.split=split
+url.hasscheme=hasscheme
+url.hashed=hashed
+function url.addscheme(str,scheme)
+ if hasscheme(str) then
+ return str
+ elseif not scheme then
+ return "file:///"..str
+ else
+ return scheme..":///"..str
+ end
+end
+function url.construct(hash)
+ local fullurl,f={},0
+ local scheme,authority,path,query,fragment=hash.scheme,hash.authority,hash.path,hash.query,hash.fragment
+ if scheme and scheme~="" then
+ f=f+1;fullurl[f]=scheme.."://"
+ end
+ if authority and authority~="" then
+ f=f+1;fullurl[f]=authority
+ end
+ if path and path~="" then
+ f=f+1;fullurl[f]="/"..path
+ end
+ if query and query~="" then
+ f=f+1;fullurl[f]="?"..query
+ end
+ if fragment and fragment~="" then
+ f=f+1;fullurl[f]="#"..fragment
+ end
+ return lpegmatch(escaper,concat(fullurl))
+end
+local pattern=Cs(noslash*R("az","AZ")*(S(":|")/":")*noslash*P(1)^0)
+function url.filename(filename)
+ local spec=hashed(filename)
+ local path=spec.path
+ return (spec.scheme=="file" and path and lpegmatch(pattern,path)) or filename
+end
+local function escapestring(str)
+ return lpegmatch(escaper,str)
+end
+url.escape=escapestring
+function url.query(str)
+ if type(str)=="string" then
+ return lpegmatch(splitquery,str) or ""
+ else
+ return str
+ end
+end
+function url.toquery(data)
+ local td=type(data)
+ if td=="string" then
+ return #str and escape(data) or nil
+ elseif td=="table" then
+ if next(data) then
+ local t={}
+ for k,v in next,data do
+ t[#t+1]=format("%s=%s",k,escapestring(v))
+ end
+ return concat(t,"&")
+ end
+ else
+ end
+end
+local pattern=Cs(noslash^0*(1-noslash*P(-1))^0)
+function url.barepath(path)
+ if not path or path=="" then
+ return ""
+ else
+ return lpegmatch(pattern,path)
+ end
end
--- utf extensies
-
-lpeg.UP = lpeg.P
-if utfcharacters then
+end -- of closure
- function lpeg.US(str)
- local p
- for uc in utfcharacters(str) do
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- return p
- end
+do -- create closure to overcome 200 locals limit
+package.loaded["l-dir"] = package.loaded["l-dir"] or true
-elseif utfgmatch then
+-- original size: 13139, stripped down to: 8196
- function lpeg.US(str)
- local p
- for uc in utfgmatch(str,".") do
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
+if not modules then modules={} end modules ['l-dir']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local type,select=type,select
+local find,gmatch,match,gsub=string.find,string.gmatch,string.match,string.gsub
+local concat,insert,remove=table.concat,table.insert,table.remove
+local lpegmatch=lpeg.match
+local P,S,R,C,Cc,Cs,Ct,Cv,V=lpeg.P,lpeg.S,lpeg.R,lpeg.C,lpeg.Cc,lpeg.Cs,lpeg.Ct,lpeg.Cv,lpeg.V
+dir=dir or {}
+local dir=dir
+local lfs=lfs
+local attributes=lfs.attributes
+local walkdir=lfs.dir
+local isdir=lfs.isdir
+local isfile=lfs.isfile
+local currentdir=lfs.currentdir
+local chdir=lfs.chdir
+if not isdir then
+ function isdir(name)
+ local a=attributes(name)
+ return a and a.mode=="directory"
+ end
+ lfs.isdir=isdir
+end
+if not isfile then
+ function isfile(name)
+ local a=attributes(name)
+ return a and a.mode=="file"
+ end
+ lfs.isfile=isfile
+end
+function dir.current()
+ return (gsub(currentdir(),"\\","/"))
+end
+local lfsisdir=isdir
+local function isdir(path)
+ path=gsub(path,"[/\\]+$","")
+ return lfsisdir(path)
+end
+lfs.isdir=isdir
+local function globpattern(path,patt,recurse,action)
+ if path=="/" then
+ path=path.."."
+ elseif not find(path,"/$") then
+ path=path..'/'
+ end
+ if isdir(path) then
+ for name in walkdir(path) do
+ local full=path..name
+ local mode=attributes(full,'mode')
+ if mode=='file' then
+ if find(full,patt) then
+ action(full)
+ end
+ elseif recurse and (mode=="directory") and (name~='.') and (name~="..") then
+ globpattern(full,patt,recurse,action)
+ end
+ end
+ end
+end
+dir.globpattern=globpattern
+local function collectpattern(path,patt,recurse,result)
+ local ok,scanner
+ result=result or {}
+ if path=="/" then
+ ok,scanner,first=xpcall(function() return walkdir(path..".") end,function() end)
+ else
+ ok,scanner,first=xpcall(function() return walkdir(path) end,function() end)
+ end
+ if ok and type(scanner)=="function" then
+ if not find(path,"/$") then path=path..'/' end
+ for name in scanner,first do
+ local full=path..name
+ local attr=attributes(full)
+ local mode=attr.mode
+ if mode=='file' then
+ if find(full,patt) then
+ result[name]=attr
+ end
+ elseif recurse and (mode=="directory") and (name~='.') and (name~="..") then
+ attr.list=collectpattern(full,patt,recurse)
+ result[name]=attr
+ end
+ end
+ end
+ return result
+end
+dir.collectpattern=collectpattern
+local pattern=Ct {
+ [1]=(C(P(".")+P("/")^1)+C(R("az","AZ")*P(":")*P("/")^0)+Cc("./"))*V(2)*V(3),
+ [2]=C(((1-S("*?/"))^0*P("/"))^0),
+ [3]=C(P(1)^0)
+}
+local filter=Cs ((
+ P("**")/".*"+P("*")/"[^/]*"+P("?")/"[^/]"+P(".")/"%%."+P("+")/"%%+"+P("-")/"%%-"+P(1)
+)^0 )
+local function glob(str,t)
+ if type(t)=="function" then
+ if type(str)=="table" then
+ for s=1,#str do
+ glob(str[s],t)
+ end
+ elseif isfile(str) then
+ t(str)
+ else
+ local split=lpegmatch(pattern,str)
+ if split then
+ local root,path,base=split[1],split[2],split[3]
+ local recurse=find(base,"%*%*")
+ local start=root..path
+ local result=lpegmatch(filter,start..base)
+ globpattern(start,result,recurse,t)
+ end
+ end
+ else
+ if type(str)=="table" then
+ local t=t or {}
+ for s=1,#str do
+ glob(str[s],t)
+ end
+ return t
+ elseif isfile(str) then
+ if t then
+ t[#t+1]=str
+ return t
+ else
+ return { str }
+ end
+ else
+ local split=lpegmatch(pattern,str)
+ if split then
+ local t=t or {}
+ local action=action or function(name) t[#t+1]=name end
+ local root,path,base=split[1],split[2],split[3]
+ local recurse=find(base,"%*%*")
+ local start=root..path
+ local result=lpegmatch(filter,start..base)
+ globpattern(start,result,recurse,action)
+ return t
+ else
+ return {}
+ end
+ end
+ end
+end
+dir.glob=glob
+local function globfiles(path,recurse,func,files)
+ if type(func)=="string" then
+ local s=func
+ func=function(name) return find(name,s) end
+ end
+ files=files or {}
+ local noffiles=#files
+ for name in walkdir(path) do
+ if find(name,"^%.") then
+ else
+ local mode=attributes(name,'mode')
+ if mode=="directory" then
+ if recurse then
+ globfiles(path.."/"..name,recurse,func,files)
end
- return p
- end
-
-else
-
- function lpeg.US(str)
- local p
- local f = function(uc)
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
+ elseif mode=="file" then
+ if not func or func(name) then
+ noffiles=noffiles+1
+ files[noffiles]=path.."/"..name
end
- match((utf8char/f)^0,str)
- return p
+ end
end
-
+ end
+ return files
end
-
-local range = Cs(utf8byte) * (Cs(utf8byte) + Cc(false))
-
-local utfchar = unicode and unicode.utf8 and unicode.utf8.char
-
-function lpeg.UR(str,more)
- local first, last
- if type(str) == "number" then
- first = str
- last = more or first
+dir.globfiles=globfiles
+function dir.ls(pattern)
+ return concat(glob(pattern),"\n")
+end
+local make_indeed=true
+local onwindows=os.type=="windows" or find(os.getenv("PATH"),";")
+if onwindows then
+ function dir.mkdirs(...)
+ local str,pth="",""
+ for i=1,select("#",...) do
+ local s=select(i,...)
+ if s=="" then
+ elseif str=="" then
+ str=s
+ else
+ str=str.."/"..s
+ end
+ end
+ local first,middle,last
+ local drive=false
+ first,middle,last=match(str,"^(//)(//*)(.*)$")
+ if first then
else
- first, last = match(range,str)
- if not last then
- return P(str)
+ first,last=match(str,"^(//)/*(.-)$")
+ if first then
+ middle,last=match(str,"([^/]+)/+(.-)$")
+ if middle then
+ pth="//"..middle
+ else
+ pth="//"..last
+ last=""
+ end
+ else
+ first,middle,last=match(str,"^([a-zA-Z]:)(/*)(.-)$")
+ if first then
+ pth,drive=first..middle,true
+ else
+ middle,last=match(str,"^(/*)(.-)$")
+ if not middle then
+ last=str
+ end
+ end
+ end
+ end
+ for s in gmatch(last,"[^/]+") do
+ if pth=="" then
+ pth=s
+ elseif drive then
+ pth,drive=pth..s,false
+ else
+ pth=pth.."/"..s
+ end
+ if make_indeed and not isdir(pth) then
+ lfs.mkdir(pth)
+ end
+ end
+ return pth,(isdir(pth)==true)
+ end
+else
+ function dir.mkdirs(...)
+ local str,pth="",""
+ for i=1,select("#",...) do
+ local s=select(i,...)
+ if s and s~="" then
+ if str~="" then
+ str=str.."/"..s
+ else
+ str=s
end
+ end
end
- if first == last then
- return P(str)
- elseif utfchar and last - first < 8 then -- a somewhat arbitrary criterium
- local p
- for i=first,last do
- if p then
- p = p + P(utfchar(i))
- else
- p = P(utfchar(i))
- end
+ str=gsub(str,"/+","/")
+ if find(str,"^/") then
+ pth="/"
+ for s in gmatch(str,"[^/]+") do
+ local first=(pth=="/")
+ if first then
+ pth=pth..s
+ else
+ pth=pth.."/"..s
end
- return p -- nil when invalid range
+ if make_indeed and not first and not isdir(pth) then
+ lfs.mkdir(pth)
+ end
+ end
else
- local f = function(b)
- return b >= first and b <= last
+ pth="."
+ for s in gmatch(str,"[^/]+") do
+ pth=pth.."/"..s
+ if make_indeed and not isdir(pth) then
+ lfs.mkdir(pth)
end
- return utf8byte / f -- nil when invalid range
+ end
end
+ return pth,(isdir(pth)==true)
+ end
end
-
-
-
-function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
- if type(list) ~= "table" then
- list = { list, ... }
+dir.makedirs=dir.mkdirs
+if onwindows then
+ function dir.expandname(str)
+ local first,nothing,last=match(str,"^(//)(//*)(.*)$")
+ if first then
+ first=dir.current().."/"
+ end
+ if not first then
+ first,last=match(str,"^(//)/*(.*)$")
+ end
+ if not first then
+ first,last=match(str,"^([a-zA-Z]:)(.*)$")
+ if first and not find(last,"^/") then
+ local d=currentdir()
+ if chdir(first) then
+ first=dir.current()
+ end
+ chdir(d)
+ end
+ end
+ if not first then
+ first,last=dir.current(),str
+ end
+ last=gsub(last,"//","/")
+ last=gsub(last,"/%./","/")
+ last=gsub(last,"^/*","")
+ first=gsub(first,"/*$","")
+ if last=="" or last=="." then
+ return first
+ else
+ return first.."/"..last
end
- -- sort(list) -- longest match first
- local p = P(list[1])
- for l=2,#list do
- p = p + P(list[l])
+ end
+else
+ function dir.expandname(str)
+ if not find(str,"^/") then
+ str=currentdir().."/"..str
end
- return p
+ str=gsub(str,"//","/")
+ str=gsub(str,"/%./","/")
+ str=gsub(str,"(.)/%.$","%1")
+ return str
+ end
end
-
-function lpeg.is_lpeg(p)
- return p and lpegtype(p) == "pattern"
+file.expandname=dir.expandname
+local stack={}
+function dir.push(newdir)
+ insert(stack,currentdir())
+ if newdir and newdir~="" then
+ chdir(newdir)
+ end
+end
+function dir.pop()
+ local d=remove(stack)
+ if d then
+ chdir(d)
+ end
+ return d
end
--- For the moment here, but it might move to utilities. Beware, we need to
--- have the longest keyword first, so 'aaa' comes beforte 'aa' which is why we
--- loop back from the end cq. prepend.
-
-local sort, fastcopy, sortedkeys = table.sort, table.fastcopy, table.sortedkeys -- dependency!
-function lpeg.append(list,pp,delayed,checked)
- local p = pp
- if #list > 0 then
- local keys = fastcopy(list)
- sort(keys)
- for i=#keys,1,-1 do
- local k = keys[i]
- if p then
- p = P(k) + p
- else
- p = P(k)
- end
- end
- elseif delayed then -- hm, it looks like the lpeg parser resolves anyway
- local keys = sortedkeys(list)
- if p then
- for i=1,#keys,1 do
- local k = keys[i]
- local v = list[k]
- p = P(k)/list + p
- end
- else
- for i=1,#keys do
- local k = keys[i]
- local v = list[k]
- if p then
- p = P(k) + p
- else
- p = P(k)
- end
- end
- if p then
- p = p / list
- end
- end
- elseif checked then
- -- problem: substitution gives a capture
- local keys = sortedkeys(list)
- for i=1,#keys do
- local k = keys[i]
- local v = list[k]
- if p then
- if k == v then
- p = P(k) + p
- else
- p = P(k)/v + p
- end
- else
- if k == v then
- p = P(k)
- else
- p = P(k)/v
- end
- end
- end
- else
- local keys = sortedkeys(list)
- for i=1,#keys do
- local k = keys[i]
- local v = list[k]
- if p then
- p = P(k)/v + p
- else
- p = P(k)/v
- end
- end
- end
- return p
-end
+end -- of closure
--- inspect(lpeg.append({ a = "1", aa = "1", aaa = "1" } ,nil,true))
--- inspect(lpeg.append({ ["degree celsius"] = "1", celsius = "1", degree = "1" } ,nil,true))
+do -- create closure to overcome 200 locals limit
--- function lpeg.exact_match(words,case_insensitive)
--- local pattern = concat(words)
--- if case_insensitive then
--- local pattern = S(upper(characters)) + S(lower(characters))
--- local list = { }
--- for i=1,#words do
--- list[lower(words[i])] = true
--- end
--- return Cmt(pattern^1, function(_,i,s)
--- return list[lower(s)] and i
--- end)
--- else
--- local pattern = S(concat(words))
--- local list = { }
--- for i=1,#words do
--- list[words[i]] = true
--- end
--- return Cmt(pattern^1, function(_,i,s)
--- return list[s] and i
--- end)
--- end
--- end
+package.loaded["l-boolean"] = package.loaded["l-boolean"] or true
--- experiment:
+-- original size: 1781, stripped down to: 1503
-local function make(t)
- local p
--- for k, v in next, t do
- for k, v in table.sortedhash(t) do
- if not p then
- if next(v) then
- p = P(k) * make(v)
- else
- p = P(k)
- end
- else
- if next(v) then
- p = p + P(k) * make(v)
- else
- p = p + P(k)
- end
- end
- end
- return p
+if not modules then modules={} end modules ['l-boolean']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local type,tonumber=type,tonumber
+boolean=boolean or {}
+local boolean=boolean
+function boolean.tonumber(b)
+ if b then return 1 else return 0 end
end
-
-function lpeg.utfchartabletopattern(list)
- local tree = { }
- for i=1,#list do
- local t = tree
- for c in gmatch(list[i],".") do
- if not t[c] then
- t[c] = { }
- end
- t = t[c]
- end
+function toboolean(str,tolerant)
+ if str==nil then
+ return false
+ elseif str==false then
+ return false
+ elseif str==true then
+ return true
+ elseif str=="true" then
+ return true
+ elseif str=="false" then
+ return false
+ elseif not tolerant then
+ return false
+ elseif str==0 then
+ return false
+ elseif (tonumber(str) or 0)>0 then
+ return true
+ else
+ return str=="yes" or str=="on" or str=="t"
+ end
+end
+string.toboolean=toboolean
+function string.booleanstring(str)
+ if str=="0" then
+ return false
+ elseif str=="1" then
+ return true
+ elseif str=="" then
+ return false
+ elseif str=="false" then
+ return false
+ elseif str=="true" then
+ return true
+ elseif (tonumber(str) or 0)>0 then
+ return true
+ else
+ return str=="yes" or str=="on" or str=="t"
+ end
+end
+function string.is_boolean(str,default)
+ if type(str)=="string" then
+ if str=="true" or str=="yes" or str=="on" or str=="t" then
+ return true
+ elseif str=="false" or str=="no" or str=="off" or str=="f" then
+ return false
end
- return make(tree)
+ end
+ return default
end
--- inspect ( lpeg.utfchartabletopattern {
--- utfchar(0x00A0), -- nbsp
--- utfchar(0x2000), -- enquad
--- utfchar(0x2001), -- emquad
--- utfchar(0x2002), -- enspace
--- utfchar(0x2003), -- emspace
--- utfchar(0x2004), -- threeperemspace
--- utfchar(0x2005), -- fourperemspace
--- utfchar(0x2006), -- sixperemspace
--- utfchar(0x2007), -- figurespace
--- utfchar(0x2008), -- punctuationspace
--- utfchar(0x2009), -- breakablethinspace
--- utfchar(0x200A), -- hairspace
--- utfchar(0x200B), -- zerowidthspace
--- utfchar(0x202F), -- narrownobreakspace
--- utfchar(0x205F), -- math thinspace
--- } )
-
end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-io'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local io = io
-local byte, find, gsub, format = string.byte, string.find, string.gsub, string.format
-local concat = table.concat
-local type = type
+package.loaded["l-unicode"] = package.loaded["l-unicode"] or true
-if string.find(os.getenv("PATH"),";") then
- io.fileseparator, io.pathseparator = "\\", ";"
-else
- io.fileseparator, io.pathseparator = "/" , ":"
-end
+-- original size: 26810, stripped down to: 11943
-function io.loaddata(filename,textmode)
- local f = io.open(filename,(textmode and 'r') or 'rb')
- if f then
- local data = f:read('*all')
- f:close()
- return data
+if not modules then modules={} end modules ['l-unicode']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+utf=utf or (unicode and unicode.utf8) or {}
+utf.characters=utf.characters or string.utfcharacters
+utf.values=utf.values or string.utfvalues
+local type=type
+local char,byte,format,sub=string.char,string.byte,string.format,string.sub
+local concat=table.concat
+local P,C,R,Cs,Ct,Cmt,Cc,Carg,Cp=lpeg.P,lpeg.C,lpeg.R,lpeg.Cs,lpeg.Ct,lpeg.Cmt,lpeg.Cc,lpeg.Carg,lpeg.Cp
+local lpegmatch,patterns=lpeg.match,lpeg.patterns
+local bytepairs=string.bytepairs
+local finder=lpeg.finder
+local replacer=lpeg.replacer
+local utfvalues=utf.values
+local utfgmatch=utf.gmatch
+local p_utftype=patterns.utftype
+local p_utfoffset=patterns.utfoffset
+local p_utf8char=patterns.utf8char
+local p_utf8byte=patterns.utf8byte
+local p_utfbom=patterns.utfbom
+local p_newline=patterns.newline
+local p_whitespace=patterns.whitespace
+if not unicode then
+ unicode={ utf=utf }
+end
+if not utf.char then
+ local floor,char=math.floor,string.char
+ function utf.char(n)
+ if n<0x80 then
+ return char(n)
+ elseif n<0x800 then
+ return char(
+ 0xC0+floor(n/0x40),
+ 0x80+(n%0x40)
+ )
+ elseif n<0x10000 then
+ return char(
+ 0xE0+floor(n/0x1000),
+ 0x80+(floor(n/0x40)%0x40),
+ 0x80+(n%0x40)
+ )
+ elseif n<0x200000 then
+ return char(
+ 0xF0+floor(n/0x40000),
+ 0x80+(floor(n/0x1000)%0x40),
+ 0x80+(floor(n/0x40)%0x40),
+ 0x80+(n%0x40)
+ )
else
- return nil
+ return ""
+ end
+ end
+end
+if not utf.byte then
+ local utf8byte=patterns.utf8byte
+ function utf.byte(c)
+ return lpegmatch(utf8byte,c)
+ end
+end
+local utfchar,utfbyte=utf.char,utf.byte
+function utf.filetype(data)
+ return data and lpegmatch(p_utftype,data) or "unknown"
+end
+local toentities=Cs (
+ (
+ patterns.utf8one+(
+ patterns.utf8two+patterns.utf8three+patterns.utf8four
+ )/function(s) local b=utfbyte(s) if b<127 then return s else return format("%X;",b) end end
+ )^0
+)
+patterns.toentities=toentities
+function utf.toentities(str)
+ return lpegmatch(toentities,str)
+end
+local one=P(1)
+local two=C(1)*C(1)
+local four=C(R(utfchar(0xD8),utfchar(0xFF)))*C(1)*C(1)*C(1)
+local pattern=P("\254\255")*Cs((
+ four/function(a,b,c,d)
+ local ab=0xFF*byte(a)+byte(b)
+ local cd=0xFF*byte(c)+byte(d)
+ return utfchar((ab-0xD800)*0x400+(cd-0xDC00)+0x10000)
+ end+two/function(a,b)
+ return utfchar(byte(a)*256+byte(b))
+ end+one
+ )^1 )+P("\255\254")*Cs((
+ four/function(b,a,d,c)
+ local ab=0xFF*byte(a)+byte(b)
+ local cd=0xFF*byte(c)+byte(d)
+ return utfchar((ab-0xD800)*0x400+(cd-0xDC00)+0x10000)
+ end+two/function(b,a)
+ return utfchar(byte(a)*256+byte(b))
+ end+one
+ )^1 )
+function string.toutf(s)
+ return lpegmatch(pattern,s) or s
+end
+local validatedutf=Cs (
+ (
+ patterns.utf8one+patterns.utf8two+patterns.utf8three+patterns.utf8four+P(1)/"�"
+ )^0
+)
+patterns.validatedutf=validatedutf
+function utf.is_valid(str)
+ return type(str)=="string" and lpegmatch(validatedutf,str) or false
+end
+if not utf.len then
+ local n,f=0,1
+ local utfcharcounter=patterns.utfbom^-1*Cmt (
+ Cc(1)*patterns.utf8one^1+Cc(2)*patterns.utf8two^1+Cc(3)*patterns.utf8three^1+Cc(4)*patterns.utf8four^1,
+ function(_,t,d)
+ n=n+(t-f)/d
+ f=t
+ return true
+ end
+ )^0
+ function utf.len(str)
+ n,f=0,1
+ lpegmatch(utfcharcounter,str or "")
+ return n
+ end
+end
+utf.length=utf.len
+if not utf.sub then
+ local utflength=utf.length
+ local b,e,n,first,last=0,0,0,0,0
+ local function slide_zero(s,p)
+ n=n+1
+ if n>=last then
+ e=p-1
+ else
+ return p
end
-end
-
-function io.savedata(filename,data,joiner)
- local f = io.open(filename,"wb")
- if f then
- if type(data) == "table" then
- f:write(concat(data,joiner or ""))
- elseif type(data) == "function" then
- data(f)
+ end
+ local function slide_one(s,p)
+ n=n+1
+ if n==first then
+ b=p
+ end
+ if n>=last then
+ e=p-1
+ else
+ return p
+ end
+ end
+ local function slide_two(s,p)
+ n=n+1
+ if n==first then
+ b=p
+ else
+ return true
+ end
+ end
+ local pattern_zero=Cmt(p_utf8char,slide_zero)^0
+ local pattern_one=Cmt(p_utf8char,slide_one )^0
+ local pattern_two=Cmt(p_utf8char,slide_two )^0
+ function utf.sub(str,start,stop)
+ if not start then
+ return str
+ end
+ if start==0 then
+ start=1
+ end
+ if not stop then
+ if start<0 then
+ local l=utflength(str)
+ start=l+start
+ else
+ start=start-1
+ end
+ b,n,first=0,0,start
+ lpegmatch(pattern_two,str)
+ if n>=first then
+ return sub(str,b)
+ else
+ return ""
+ end
+ end
+ if start<0 or stop<0 then
+ local l=utf.length(str)
+ if start<0 then
+ start=l+start
+ if start<=0 then
+ start=1
else
- f:write(data or "")
+ start=start+1
end
- f:close()
- io.flush()
- return true
+ end
+ if stop<0 then
+ stop=l+stop
+ if stop==0 then
+ stop=1
+ else
+ stop=stop+1
+ end
+ end
+ end
+ if start>stop then
+ return ""
+ elseif start>1 then
+ b,e,n,first,last=0,0,0,start-1,stop
+ lpegmatch(pattern_one,str)
+ if n>=first and e==0 then
+ e=#str
+ end
+ return sub(str,b,e)
else
- return false
- end
-end
-
-function io.exists(filename)
- local f = io.open(filename)
- if f == nil then
- return false
+ b,e,n,last=1,0,0,stop
+ lpegmatch(pattern_zero,str)
+ if e==0 then
+ e=#str
+ end
+ return sub(str,b,e)
+ end
+ end
+end
+function utf.remapper(mapping)
+ local pattern=Cs((p_utf8char/mapping)^0)
+ return function(str)
+ if not str or str=="" then
+ return ""
else
- assert(f:close())
- return true
- end
-end
-
-function io.size(filename)
- local f = io.open(filename)
- if f == nil then
- return 0
+ return lpegmatch(pattern,str)
+ end
+ end,pattern
+end
+function utf.replacer(t)
+ local r=replacer(t,false,false,true)
+ return function(str)
+ return lpegmatch(r,str)
+ end
+end
+function utf.subtituter(t)
+ local f=finder (t)
+ local r=replacer(t,false,false,true)
+ return function(str)
+ local i=lpegmatch(f,str)
+ if not i then
+ return str
+ elseif i>#str then
+ return str
else
- local s = f:seek("end")
- assert(f:close())
- return s
- end
+ return lpegmatch(r,str)
+ end
+ end
+end
+local utflinesplitter=p_utfbom^-1*lpeg.tsplitat(p_newline)
+local utfcharsplitter_ows=p_utfbom^-1*Ct(C(p_utf8char)^0)
+local utfcharsplitter_iws=p_utfbom^-1*Ct((p_whitespace^1+C(p_utf8char))^0)
+local utfcharsplitter_raw=Ct(C(p_utf8char)^0)
+patterns.utflinesplitter=utflinesplitter
+function utf.splitlines(str)
+ return lpegmatch(utflinesplitter,str or "")
+end
+function utf.split(str,ignorewhitespace)
+ if ignorewhitespace then
+ return lpegmatch(utfcharsplitter_iws,str or "")
+ else
+ return lpegmatch(utfcharsplitter_ows,str or "")
+ end
+end
+function utf.totable(str)
+ return lpegmatch(utfcharsplitter_raw,str)
+end
+function utf.magic(f)
+ local str=f:read(4) or ""
+ local off=lpegmatch(p_utfoffset,str)
+ if off<4 then
+ f:seek('set',off)
+ end
+ return lpegmatch(p_utftype,str)
end
-
-function io.noflines(f)
- if type(f) == "string" then
- local f = io.open(filename)
- local n = f and io.noflines(f) or 0
- assert(f:close())
- return n
- else
- local n = 0
- for _ in f:lines() do
- n = n + 1
+local function utf16_to_utf8_be(t)
+ if type(t)=="string" then
+ t=lpegmatch(utflinesplitter,t)
+ end
+ local result={}
+ for i=1,#t do
+ local r,more=0,0
+ for left,right in bytepairs(t[i]) do
+ if right then
+ local now=256*left+right
+ if more>0 then
+ now=(more-0xD800)*0x400+(now-0xDC00)+0x10000
+ more=0
+ r=r+1
+ result[r]=utfchar(now)
+ elseif now>=0xD800 and now<=0xDBFF then
+ more=now
+ else
+ r=r+1
+ result[r]=utfchar(now)
end
- f:seek('set',0)
- return n
+ end
end
+ t[i]=concat(result,"",1,r)
+ end
+ return t
end
-
-local nextchar = {
- [ 4] = function(f)
- return f:read(1,1,1,1)
- end,
- [ 2] = function(f)
- return f:read(1,1)
- end,
- [ 1] = function(f)
- return f:read(1)
- end,
- [-2] = function(f)
- local a, b = f:read(1,1)
- return b, a
- end,
- [-4] = function(f)
- local a, b, c, d = f:read(1,1,1,1)
- return d, c, b, a
- end
-}
-
-function io.characters(f,n)
- if f then
- return nextchar[n or 1], f
+local function utf16_to_utf8_le(t)
+ if type(t)=="string" then
+ t=lpegmatch(utflinesplitter,t)
+ end
+ local result={}
+ for i=1,#t do
+ local r,more=0,0
+ for left,right in bytepairs(t[i]) do
+ if right then
+ local now=256*right+left
+ if more>0 then
+ now=(more-0xD800)*0x400+(now-0xDC00)+0x10000
+ more=0
+ r=r+1
+ result[r]=utfchar(now)
+ elseif now>=0xD800 and now<=0xDBFF then
+ more=now
+ else
+ r=r+1
+ result[r]=utfchar(now)
+ end
+ end
end
+ t[i]=concat(result,"",1,r)
+ end
+ return t
end
-
-local nextbyte = {
- [4] = function(f)
- local a, b, c, d = f:read(1,1,1,1)
- if d then
- return byte(a), byte(b), byte(c), byte(d)
- end
- end,
- [3] = function(f)
- local a, b, c = f:read(1,1,1)
- if b then
- return byte(a), byte(b), byte(c)
- end
- end,
- [2] = function(f)
- local a, b = f:read(1,1)
- if b then
- return byte(a), byte(b)
- end
- end,
- [1] = function (f)
- local a = f:read(1)
- if a then
- return byte(a)
- end
- end,
- [-2] = function (f)
- local a, b = f:read(1,1)
- if b then
- return byte(b), byte(a)
- end
- end,
- [-3] = function(f)
- local a, b, c = f:read(1,1,1)
- if b then
- return byte(c), byte(b), byte(a)
- end
- end,
- [-4] = function(f)
- local a, b, c, d = f:read(1,1,1,1)
- if d then
- return byte(d), byte(c), byte(b), byte(a)
+local function utf32_to_utf8_be(t)
+ if type(t)=="string" then
+ t=lpegmatch(utflinesplitter,t)
+ end
+ local result={}
+ for i=1,#t do
+ local r,more=0,-1
+ for a,b in bytepairs(t[i]) do
+ if a and b then
+ if more<0 then
+ more=256*256*256*a+256*256*b
+ else
+ r=r+1
+ result[t]=utfchar(more+256*a+b)
+ more=-1
end
+ else
+ break
+ end
end
-}
-
-function io.bytes(f,n)
- if f then
- return nextbyte[n or 1], f
- else
- return nil, nil
- end
+ t[i]=concat(result,"",1,r)
+ end
+ return t
end
-
-function io.ask(question,default,options)
- while true do
- io.write(question)
- if options then
- io.write(format(" [%s]",concat(options,"|")))
- end
- if default then
- io.write(format(" [%s]",default))
- end
- io.write(format(" "))
- io.flush()
- local answer = io.read()
- answer = gsub(answer,"^%s*(.*)%s*$","%1")
- if answer == "" and default then
- return default
- elseif not options then
- return answer
+local function utf32_to_utf8_le(t)
+ if type(t)=="string" then
+ t=lpegmatch(utflinesplitter,t)
+ end
+ local result={}
+ for i=1,#t do
+ local r,more=0,-1
+ for a,b in bytepairs(t[i]) do
+ if a and b then
+ if more<0 then
+ more=256*b+a
else
- for k=1,#options do
- if options[k] == answer then
- return answer
- end
- end
- local pattern = "^" .. answer
- for k=1,#options do
- local v = options[k]
- if find(v,pattern) then
- return v
- end
- end
+ r=r+1
+ result[t]=utfchar(more+256*256*256*b+256*256*a)
+ more=-1
end
+ else
+ break
+ end
end
+ t[i]=concat(result,"",1,r)
+ end
+ return t
end
-
-local function readnumber(f,n,m)
- if m then
- f:seek("set",n)
- n = m
- end
- if n == 1 then
- return byte(f:read(1))
- elseif n == 2 then
- local a, b = byte(f:read(2),1,2)
- return 256 * a + b
- elseif n == 3 then
- local a, b, c = byte(f:read(3),1,3)
- return 256*256 * a + 256 * b + c
- elseif n == 4 then
- local a, b, c, d = byte(f:read(4),1,4)
- return 256*256*256 * a + 256*256 * b + 256 * c + d
- elseif n == 8 then
- local a, b = readnumber(f,4), readnumber(f,4)
- return 256 * a + b
- elseif n == 12 then
- local a, b, c = readnumber(f,4), readnumber(f,4), readnumber(f,4)
- return 256*256 * a + 256 * b + c
- elseif n == -2 then
- local b, a = byte(f:read(2),1,2)
- return 256*a + b
- elseif n == -3 then
- local c, b, a = byte(f:read(3),1,3)
- return 256*256 * a + 256 * b + c
- elseif n == -4 then
- local d, c, b, a = byte(f:read(4),1,4)
- return 256*256*256 * a + 256*256 * b + 256*c + d
- elseif n == -8 then
- local h, g, f, e, d, c, b, a = byte(f:read(8),1,8)
- return 256*256*256*256*256*256*256 * a +
- 256*256*256*256*256*256 * b +
- 256*256*256*256*256 * c +
- 256*256*256*256 * d +
- 256*256*256 * e +
- 256*256 * f +
- 256 * g +
- h
+utf.utf32_to_utf8_be=utf32_to_utf8_be
+utf.utf32_to_utf8_le=utf32_to_utf8_le
+utf.utf16_to_utf8_be=utf16_to_utf8_be
+utf.utf16_to_utf8_le=utf16_to_utf8_le
+function utf.utf8_to_utf8(t)
+ return type(t)=="string" and lpegmatch(utflinesplitter,t) or t
+end
+function utf.utf16_to_utf8(t,endian)
+ return endian and utf16_to_utf8_be(t) or utf16_to_utf8_le(t) or t
+end
+function utf.utf32_to_utf8(t,endian)
+ return endian and utf32_to_utf8_be(t) or utf32_to_utf8_le(t) or t
+end
+local function little(c)
+ local b=byte(c)
+ if b<0x10000 then
+ return char(b%256,b/256)
+ else
+ b=b-0x10000
+ local b1,b2=b/1024+0xD800,b%1024+0xDC00
+ return char(b1%256,b1/256,b2%256,b2/256)
+ end
+end
+local function big(c)
+ local b=byte(c)
+ if b<0x10000 then
+ return char(b/256,b%256)
+ else
+ b=b-0x10000
+ local b1,b2=b/1024+0xD800,b%1024+0xDC00
+ return char(b1/256,b1%256,b2/256,b2%256)
+ end
+end
+local _,l_remap=utf.remapper(little)
+local _,b_remap=utf.remapper(big)
+function utf.utf8_to_utf16(str,littleendian)
+ if littleendian then
+ return char(255,254)..lpegmatch(l_remap,str)
+ else
+ return char(254,255)..lpegmatch(b_remap,str)
+ end
+end
+local pattern=Cs (
+ (p_utf8byte/function(unicode ) return format("0x%04X",unicode) end)*(p_utf8byte*Carg(1)/function(unicode,separator) return format("%s0x%04X",separator,unicode) end)^0
+)
+function utf.tocodes(str,separator)
+ return lpegmatch(pattern,str,1,separator or " ")
+end
+function utf.ustring(s)
+ return format("U+%05X",type(s)=="number" and s or utfbyte(s))
+end
+function utf.xstring(s)
+ return format("0x%05X",type(s)=="number" and s or utfbyte(s))
+end
+local p_nany=p_utf8char/""
+if utfgmatch then
+ function utf.count(str,what)
+ if type(what)=="string" then
+ local n=0
+ for _ in utfgmatch(str,what) do
+ n=n+1
+ end
+ return n
+ else
+ return #lpegmatch(Cs((P(what)/" "+p_nany)^0),str)
+ end
+ end
+else
+ local cache={}
+ function utf.count(str,what)
+ if type(what)=="string" then
+ local p=cache[what]
+ if not p then
+ p=Cs((P(what)/" "+p_nany)^0)
+ cache[p]=p
+ end
+ return #lpegmatch(p,str)
+ else
+ return #lpegmatch(Cs((P(what)/" "+p_nany)^0),str)
+ end
+ end
+end
+if not utf.characters then
+ function utf.characters(str)
+ return gmatch(str,".[\128-\191]*")
+ end
+ string.utfcharacters=utf.characters
+end
+if not utf.values then
+ local find=string.find
+ local dummy=function()
+ end
+ function utf.values(str)
+ local n=#str
+ if n==0 then
+ return dummy
+ elseif n==1 then
+ return function() return utfbyte(str) end
else
- return 0
+ local p=1
+ return function()
+ local b,e=find(str,".[\128-\191]*",p)
+ if b then
+ p=e+1
+ return utfbyte(sub(str,b,e))
+ end
+ end
end
+ end
+ string.utfvalues=utf.values
end
-io.readnumber = readnumber
-function io.readstring(f,n,m)
- if m then
- f:seek("set",n)
- n = m
- end
- local str = gsub(f:read(n),"%z","")
- return str
-end
+end -- of closure
---
+do -- create closure to overcome 200 locals limit
+
+package.loaded["l-math"] = package.loaded["l-math"] or true
-if not io.i_limiter then function io.i_limiter() end end -- dummy so we can test safely
-if not io.o_limiter then function io.o_limiter() end end -- dummy so we can test safely
+-- original size: 915, stripped down to: 836
+
+if not modules then modules={} end modules ['l-math']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local floor,sin,cos,tan=math.floor,math.sin,math.cos,math.tan
+if not math.round then
+ function math.round(x) return floor(x+0.5) end
+end
+if not math.div then
+ function math.div(n,m) return floor(n/m) end
+end
+if not math.mod then
+ function math.mod(n,m) return n%m end
+end
+local pipi=2*math.pi/360
+if not math.sind then
+ function math.sind(d) return sin(d*pipi) end
+ function math.cosd(d) return cos(d*pipi) end
+ function math.tand(d) return tan(d*pipi) end
+end
+if not math.odd then
+ function math.odd (n) return n%2~=0 end
+ function math.even(n) return n%2==0 end
+end
end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-number'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
+package.loaded["util-str"] = package.loaded["util-str"] or true
--- this module will be replaced when we have the bit library
+-- original size: 22834, stripped down to: 12570
+if not modules then modules={} end modules ['util-str']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+utilities=utilities or {}
+utilities.strings=utilities.strings or {}
+local strings=utilities.strings
+local format,gsub,rep,sub=string.format,string.gsub,string.rep,string.sub
+local load,dump=load,string.dump
+local tonumber,type,tostring=tonumber,type,tostring
+local unpack,concat=table.unpack,table.concat
+local P,V,C,S,R,Ct,Cs,Cp,Carg,Cc=lpeg.P,lpeg.V,lpeg.C,lpeg.S,lpeg.R,lpeg.Ct,lpeg.Cs,lpeg.Cp,lpeg.Carg,lpeg.Cc
+local patterns,lpegmatch=lpeg.patterns,lpeg.match
+local utfchar,utfbyte=utf.char,utf.byte
+local loadstripped=_LUAVERSION<5.2 and load or function(str)
+ return load(dump(load(str),true))
+end
+if not number then number={} end
+local stripper=patterns.stripzeros
+local function points(n)
+ return (not n or n==0) and "0pt" or lpegmatch(stripper,format("%.5fpt",n/65536))
+end
+local function basepoints(n)
+ return (not n or n==0) and "0bp" or lpegmatch(stripper,format("%.5fbp",n*(7200/7227)/65536))
+end
+number.points=points
+number.basepoints=basepoints
+local rubish=patterns.spaceortab^0*patterns.newline
+local anyrubish=patterns.spaceortab+patterns.newline
+local anything=patterns.anything
+local stripped=(patterns.spaceortab^1/"")*patterns.newline
+local leading=rubish^0/""
+local trailing=(anyrubish^1*patterns.endofstring)/""
+local redundant=rubish^3/"\n"
+local pattern=Cs(leading*(trailing+redundant+stripped+anything)^0)
+function strings.collapsecrlf(str)
+ return lpegmatch(pattern,str)
+end
+local repeaters={}
+function strings.newrepeater(str,offset)
+ offset=offset or 0
+ local s=repeaters[str]
+ if not s then
+ s={}
+ repeaters[str]=s
+ end
+ local t=s[offset]
+ if t then
+ return t
+ end
+ t={}
+ setmetatable(t,{ __index=function(t,k)
+ if not k then
+ return ""
+ end
+ local n=k+offset
+ local s=n>0 and rep(str,n) or ""
+ t[k]=s
+ return s
+ end })
+ s[offset]=t
+ return t
+end
+local extra,tab,start=0,0,4,0
+local nspaces=strings.newrepeater(" ")
+string.nspaces=nspaces
+local pattern=Carg(1)/function(t)
+ extra,tab,start=0,t or 7,1
+ end*Cs((
+ Cp()*patterns.tab/function(position)
+ local current=(position-start+1)+extra
+ local spaces=tab-(current-1)%tab
+ if spaces>0 then
+ extra=extra+spaces-1
+ return nspaces[spaces]
+ else
+ return ""
+ end
+ end+patterns.newline*Cp()/function(position)
+ extra,start=0,position
+ end+patterns.anything
+ )^1)
+function strings.tabtospace(str,tab)
+ return lpegmatch(pattern,str,1,tab or 7)
+end
+function strings.striplong(str)
+ str=gsub(str,"^%s*","")
+ str=gsub(str,"[\n\r]+ *","\n")
+ return str
+end
+function strings.nice(str)
+ str=gsub(str,"[:%-+_]+"," ")
+ return str
+end
+local n=0
+local sequenced=table.sequenced
+function string.autodouble(s,sep)
+ if s==nil then
+ return '""'
+ end
+ local t=type(s)
+ if t=="number" then
+ return tostring(s)
+ end
+ if t=="table" then
+ return ('"'..sequenced(s,sep or ",")..'"')
+ end
+ return ('"'..tostring(s)..'"')
+end
+function string.autosingle(s,sep)
+ if s==nil then
+ return "''"
+ end
+ local t=type(s)
+ if t=="number" then
+ return tostring(s)
+ end
+ if t=="table" then
+ return ("'"..sequenced(s,sep or ",").."'")
+ end
+ return ("'"..tostring(s).."'")
+end
+local tracedchars={}
+string.tracedchars=tracedchars
+strings.tracers=tracedchars
+function string.tracedchar(b)
+ if type(b)=="number" then
+ return tracedchars[b] or (utfchar(b).." (U+"..format('%05X',b)..")")
+ else
+ local c=utfbyte(b)
+ return tracedchars[c] or (b.." (U+"..format('%05X',c)..")")
+ end
+end
+function number.signed(i)
+ if i>0 then
+ return "+",i
+ else
+ return "-",-i
+ end
+end
+local preamble=[[
+local type = type
local tostring = tostring
-local format, floor, match, rep = string.format, math.floor, string.match, string.rep
-local concat, insert = table.concat, table.insert
+local tonumber = tonumber
+local format = string.format
+local concat = table.concat
+local signed = number.signed
+local points = number.points
+local basepoints = number.basepoints
+local utfchar = utf.char
+local utfbyte = utf.byte
local lpegmatch = lpeg.match
-
-number = number or { }
-local number = number
-
--- a,b,c,d,e,f = number.toset(100101)
-
-function number.toset(n)
- return match(tostring(n),"(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.?)")
-end
-
-function number.toevenhex(n)
- local s = format("%X",n)
- if #s % 2 == 0 then
- return s
+local nspaces = string.nspaces
+local tracedchar = string.tracedchar
+local autosingle = string.autosingle
+local autodouble = string.autodouble
+local sequenced = table.sequenced
+]]
+local template=[[
+%s
+%s
+return function(%s) return %s end
+]]
+local arguments={ "a1" }
+setmetatable(arguments,{ __index=function(t,k)
+ local v=t[k-1]..",a"..k
+ t[k]=v
+ return v
+ end
+})
+local prefix_any=C((S("+- .")+R("09"))^0)
+local prefix_tab=C((1-R("az","AZ","09","%%"))^0)
+local format_s=function(f)
+ n=n+1
+ if f and f~="" then
+ return format("format('%%%ss',a%s)",f,n)
+ else
+ return format("(a%s or '')",n)
+ end
+end
+local format_S=function(f)
+ n=n+1
+ if f and f~="" then
+ return format("format('%%%ss',tostring(a%s))",f,n)
+ else
+ return format("tostring(a%s)",n)
+ end
+end
+local format_q=function()
+ n=n+1
+ return format("(a%s and format('%%q',a%s) or '')",n,n)
+end
+local format_Q=function()
+ n=n+1
+ return format("format('%%q',tostring(a%s))",n)
+end
+local format_i=function(f)
+ n=n+1
+ if f and f~="" then
+ return format("format('%%%si',a%s)",f,n)
+ else
+ return format("a%s",n)
+ end
+end
+local format_d=format_i
+local format_I=function(f)
+ n=n+1
+ return format("format('%%s%%%si',signed(a%s))",f,n)
+end
+local format_f=function(f)
+ n=n+1
+ return format("format('%%%sf',a%s)",f,n)
+end
+local format_g=function(f)
+ n=n+1
+ return format("format('%%%sg',a%s)",f,n)
+end
+local format_G=function(f)
+ n=n+1
+ return format("format('%%%sG',a%s)",f,n)
+end
+local format_e=function(f)
+ n=n+1
+ return format("format('%%%se',a%s)",f,n)
+end
+local format_E=function(f)
+ n=n+1
+ return format("format('%%%sE',a%s)",f,n)
+end
+local format_x=function(f)
+ n=n+1
+ return format("format('%%%sx',a%s)",f,n)
+end
+local format_X=function(f)
+ n=n+1
+ return format("format('%%%sX',a%s)",f,n)
+end
+local format_o=function(f)
+ n=n+1
+ return format("format('%%%so',a%s)",f,n)
+end
+local format_c=function()
+ n=n+1
+ return format("utfchar(a%s)",n)
+end
+local format_C=function()
+ n=n+1
+ return format("tracedchar(a%s)",n)
+end
+local format_r=function(f)
+ n=n+1
+ return format("format('%%%s.0f',a%s)",f,n)
+end
+local format_h=function(f)
+ n=n+1
+ if f=="-" then
+ f=sub(f,2)
+ return format("format('%%%sx',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n)
+ else
+ return format("format('0x%%%sx',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n)
+ end
+end
+local format_H=function(f)
+ n=n+1
+ if f=="-" then
+ f=sub(f,2)
+ return format("format('%%%sX',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n)
+ else
+ return format("format('0x%%%sX',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n)
+ end
+end
+local format_u=function(f)
+ n=n+1
+ if f=="-" then
+ f=sub(f,2)
+ return format("format('%%%sx',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n)
+ else
+ return format("format('u+%%%sx',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n)
+ end
+end
+local format_U=function(f)
+ n=n+1
+ if f=="-" then
+ f=sub(f,2)
+ return format("format('%%%sX',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n)
+ else
+ return format("format('U+%%%sX',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n)
+ end
+end
+local format_p=function()
+ n=n+1
+ return format("points(a%s)",n)
+end
+local format_b=function()
+ n=n+1
+ return format("basepoints(a%s)",n)
+end
+local format_t=function(f)
+ n=n+1
+ if f and f~="" then
+ return format("concat(a%s,%q)",n,f)
+ else
+ return format("concat(a%s)",n)
+ end
+end
+local format_T=function(f)
+ n=n+1
+ if f and f~="" then
+ return format("sequenced(a%s,%q)",n,f)
+ else
+ return format("sequenced(a%s)",n)
+ end
+end
+local format_l=function()
+ n=n+1
+ return format("(a%s and 'true' or 'false')",n)
+end
+local format_L=function()
+ n=n+1
+ return format("(a%s and 'TRUE' or 'FALSE')",n)
+end
+local format_N=function()
+ n=n+1
+ return format("tostring(tonumber(a%s) or a%s)",n,n)
+end
+local format_a=function(f)
+ n=n+1
+ if f and f~="" then
+ return format("autosingle(a%s,%q)",n,f)
+ else
+ return format("autosingle(a%s)",n)
+ end
+end
+local format_A=function(f)
+ n=n+1
+ if f and f~="" then
+ return format("autodouble(a%s,%q)",n,f)
+ else
+ return format("autodouble(a%s)",n)
+ end
+end
+local format_w=function(f)
+ n=n+1
+ f=tonumber(f)
+ if f then
+ return format("nspaces[%s+a%s]",f,n)
+ else
+ return format("nspaces[a%s]",n)
+ end
+end
+local format_W=function(f)
+ return format("nspaces[%s]",tonumber(f) or 0)
+end
+local format_rest=function(s)
+ return format("%q",s)
+end
+local format_extension=function(extensions,f,name)
+ local extension=extensions[name] or "tostring(%s)"
+ local f=tonumber(f) or 1
+ if f==0 then
+ return extension
+ elseif f==1 then
+ n=n+1
+ local a="a"..n
+ return format(extension,a,a)
+ elseif f<0 then
+ local a="a"..(n+f+1)
+ return format(extension,a,a)
+ else
+ local t={}
+ for i=1,f do
+ n=n+1
+ t[#t+1]="a"..n
+ end
+ return format(extension,unpack(t))
+ end
+end
+local builder=Cs { "start",
+ start=(
+ (
+ P("%")/""*(
+ V("!")
++V("s")+V("q")+V("i")+V("d")+V("f")+V("g")+V("G")+V("e")+V("E")+V("x")+V("X")+V("o")
++V("c")+V("C")+V("S")
++V("Q")
++V("N")
++V("r")+V("h")+V("H")+V("u")+V("U")+V("p")+V("b")+V("t")+V("T")+V("l")+V("L")+V("I")+V("h")
++V("w")
++V("W")
++V("a")
++V("A")
++V("*")
+ )+V("*")
+ )*(P(-1)+Carg(1))
+ )^0,
+ ["s"]=(prefix_any*P("s"))/format_s,
+ ["q"]=(prefix_any*P("q"))/format_q,
+ ["i"]=(prefix_any*P("i"))/format_i,
+ ["d"]=(prefix_any*P("d"))/format_d,
+ ["f"]=(prefix_any*P("f"))/format_f,
+ ["g"]=(prefix_any*P("g"))/format_g,
+ ["G"]=(prefix_any*P("G"))/format_G,
+ ["e"]=(prefix_any*P("e"))/format_e,
+ ["E"]=(prefix_any*P("E"))/format_E,
+ ["x"]=(prefix_any*P("x"))/format_x,
+ ["X"]=(prefix_any*P("X"))/format_X,
+ ["o"]=(prefix_any*P("o"))/format_o,
+ ["S"]=(prefix_any*P("S"))/format_S,
+ ["Q"]=(prefix_any*P("Q"))/format_S,
+ ["N"]=(prefix_any*P("N"))/format_N,
+ ["c"]=(prefix_any*P("c"))/format_c,
+ ["C"]=(prefix_any*P("C"))/format_C,
+ ["r"]=(prefix_any*P("r"))/format_r,
+ ["h"]=(prefix_any*P("h"))/format_h,
+ ["H"]=(prefix_any*P("H"))/format_H,
+ ["u"]=(prefix_any*P("u"))/format_u,
+ ["U"]=(prefix_any*P("U"))/format_U,
+ ["p"]=(prefix_any*P("p"))/format_p,
+ ["b"]=(prefix_any*P("b"))/format_b,
+ ["t"]=(prefix_tab*P("t"))/format_t,
+ ["T"]=(prefix_tab*P("T"))/format_T,
+ ["l"]=(prefix_tab*P("l"))/format_l,
+ ["L"]=(prefix_tab*P("L"))/format_L,
+ ["I"]=(prefix_any*P("I"))/format_I,
+ ["w"]=(prefix_any*P("w"))/format_w,
+ ["W"]=(prefix_any*P("W"))/format_W,
+ ["a"]=(prefix_any*P("a"))/format_a,
+ ["A"]=(prefix_any*P("A"))/format_A,
+ ["*"]=Cs(((1-P("%"))^1+P("%%")/"%%%%")^1)/format_rest,
+ ["!"]=Carg(2)*prefix_any*P("!")*C((1-P("!"))^1)*P("!")/format_extension,
+}
+local direct=Cs (
+ P("%")/""*Cc([[local format = string.format return function(str) return format("%]])*(S("+- .")+R("09"))^0*S("sqidfgGeExXo")*Cc([[",str) end]])*P(-1)
+ )
+local function make(t,str)
+ local f
+ local p
+ local p=lpegmatch(direct,str)
+ if p then
+ f=loadstripped(p)()
+ else
+ n=0
+ p=lpegmatch(builder,str,1,"..",t._extensions_)
+ if n>0 then
+ p=format(template,preamble,t._preamble_,arguments[n],p)
+ f=loadstripped(p)()
else
- return "0" .. s
+ f=function() return str end
end
+ end
+ t[str]=f
+ return f
end
-
--- the lpeg way is slower on 8 digits, but faster on 4 digits, some 7.5%
--- on
---
--- for i=1,1000000 do
--- local a,b,c,d,e,f,g,h = number.toset(12345678)
--- local a,b,c,d = number.toset(1234)
--- local a,b,c = number.toset(123)
--- end
---
--- of course dedicated "(.)(.)(.)(.)" matches are even faster
-
-local one = lpeg.C(1-lpeg.S(''))^1
-
-function number.toset(n)
- return lpegmatch(one,tostring(n))
+local function use(t,fmt,...)
+ return t[fmt](...)
end
-
-function number.bits(n,zero)
- local t, i = { }, (zero and 0) or 1
- while n > 0 do
- local m = n % 2
- if m > 0 then
- insert(t,1,i)
- end
- n = floor(n/2)
- i = i + 1
+strings.formatters={}
+function strings.formatters.new()
+ local t={ _extensions_={},_preamble_="",_type_="formatter" }
+ setmetatable(t,{ __index=make,__call=use })
+ return t
+end
+local formatters=strings.formatters.new()
+string.formatters=formatters
+string.formatter=function(str,...) return formatters[str](...) end
+local function add(t,name,template,preamble)
+ if type(t)=="table" and t._type_=="formatter" then
+ t._extensions_[name]=template or "%s"
+ if preamble then
+ t._preamble_=preamble.."\n"..t._preamble_
end
- return t
+ end
end
+strings.formatters.add=add
+lpeg.patterns.xmlescape=Cs((P("<")/"<"+P(">")/">"+P("&")/"&"+P('"')/"""+P(1))^0)
+lpeg.patterns.texescape=Cs((C(S("#$%\\{}"))/"\\%1"+P(1))^0)
+add(formatters,"xml",[[lpegmatch(xmlescape,%s)]],[[local xmlescape = lpeg.patterns.xmlescape]])
+add(formatters,"tex",[[lpegmatch(texescape,%s)]],[[local texescape = lpeg.patterns.texescape]])
-function number.bit(p)
- return 2 ^ (p - 1) -- 1-based indexing
-end
-
-function number.hasbit(x, p) -- typical call: if hasbit(x, bit(3)) then ...
- return x % (p + p) >= p
-end
+end -- of closure
-function number.setbit(x, p)
- return hasbit(x, p) and x or x + p
-end
+do -- create closure to overcome 200 locals limit
-function number.clearbit(x, p)
- return hasbit(x, p) and x - p or x
-end
+package.loaded["util-tab"] = package.loaded["util-tab"] or true
+-- original size: 14491, stripped down to: 8512
-function number.tobitstring(n,m)
- if n == 0 then
- if m then
- rep("00000000",m)
+if not modules then modules={} end modules ['util-tab']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+utilities=utilities or {}
+utilities.tables=utilities.tables or {}
+local tables=utilities.tables
+local format,gmatch,gsub=string.format,string.gmatch,string.gsub
+local concat,insert,remove=table.concat,table.insert,table.remove
+local setmetatable,getmetatable,tonumber,tostring=setmetatable,getmetatable,tonumber,tostring
+local type,next,rawset,tonumber,tostring,load,select=type,next,rawset,tonumber,tostring,load,select
+local lpegmatch,P,Cs,Cc=lpeg.match,lpeg.P,lpeg.Cs,lpeg.Cc
+local serialize,sortedkeys,sortedpairs=table.serialize,table.sortedkeys,table.sortedpairs
+local formatters=string.formatters
+local splitter=lpeg.tsplitat(".")
+function tables.definetable(target,nofirst,nolast)
+ local composed,shortcut,t=nil,nil,{}
+ local snippets=lpegmatch(splitter,target)
+ for i=1,#snippets-(nolast and 1 or 0) do
+ local name=snippets[i]
+ if composed then
+ composed=shortcut.."."..name
+ shortcut=shortcut.."_"..name
+ t[#t+1]=formatters["local %s = %s if not %s then %s = { } %s = %s end"](shortcut,composed,shortcut,shortcut,composed,shortcut)
+ else
+ composed=name
+ shortcut=name
+ if not nofirst then
+ t[#t+1]=formatters["%s = %s or { }"](composed,composed)
+ end
+ end
+ end
+ if nolast then
+ composed=shortcut.."."..snippets[#snippets]
+ end
+ return concat(t,"\n"),composed
+end
+function tables.definedtable(...)
+ local t=_G
+ for i=1,select("#",...) do
+ local li=select(i,...)
+ local tl=t[li]
+ if not tl then
+ tl={}
+ t[li]=tl
+ end
+ t=tl
+ end
+ return t
+end
+function tables.accesstable(target,root)
+ local t=root or _G
+ for name in gmatch(target,"([^%.]+)") do
+ t=t[name]
+ if not t then
+ return
+ end
+ end
+ return t
+end
+function tables.migratetable(target,v,root)
+ local t=root or _G
+ local names=string.split(target,".")
+ for i=1,#names-1 do
+ local name=names[i]
+ t[name]=t[name] or {}
+ t=t[name]
+ if not t then
+ return
+ end
+ end
+ t[names[#names]]=v
+end
+function tables.removevalue(t,value)
+ if value then
+ for i=1,#t do
+ if t[i]==value then
+ remove(t,i)
+ end
+ end
+ end
+end
+function tables.insertbeforevalue(t,value,extra)
+ for i=1,#t do
+ if t[i]==extra then
+ remove(t,i)
+ end
+ end
+ for i=1,#t do
+ if t[i]==value then
+ insert(t,i,extra)
+ return
+ end
+ end
+ insert(t,1,extra)
+end
+function tables.insertaftervalue(t,value,extra)
+ for i=1,#t do
+ if t[i]==extra then
+ remove(t,i)
+ end
+ end
+ for i=1,#t do
+ if t[i]==value then
+ insert(t,i+1,extra)
+ return
+ end
+ end
+ insert(t,#t+1,extra)
+end
+local escape=Cs(Cc('"')*((P('"')/'""'+P(1))^0)*Cc('"'))
+function table.tocsv(t,specification)
+ if t and #t>0 then
+ local result={}
+ local r={}
+ specification=specification or {}
+ local fields=specification.fields
+ if type(fields)~="string" then
+ fields=sortedkeys(t[1])
+ end
+ local separator=specification.separator or ","
+ if specification.preamble==true then
+ for f=1,#fields do
+ r[f]=lpegmatch(escape,tostring(fields[f]))
+ end
+ result[1]=concat(r,separator)
+ end
+ for i=1,#t do
+ local ti=t[i]
+ for f=1,#fields do
+ local field=ti[fields[f]]
+ if type(field)=="string" then
+ r[f]=lpegmatch(escape,field)
else
- return "00000000"
+ r[f]=tostring(field)
end
+ end
+ result[#result+1]=concat(r,separator)
+ end
+ return concat(result,"\n")
+ else
+ return ""
+ end
+end
+local nspaces=utilities.strings.newrepeater(" ")
+local function toxml(t,d,result,step)
+ for k,v in sortedpairs(t) do
+ local s=nspaces[d]
+ local tk=type(k)
+ local tv=type(v)
+ if tv=="table" then
+ if tk=="number" then
+ result[#result+1]=formatters["%s"](s,k)
+ toxml(v,d+step,result,step)
+ result[#result+1]=formatters["%s "](s,k)
+ else
+ result[#result+1]=formatters["%s<%s>"](s,k)
+ toxml(v,d+step,result,step)
+ result[#result+1]=formatters["%s%s>"](s,k)
+ end
+ elseif tv=="string" then
+ if tk=="number" then
+ result[#result+1]=formatters["%s%!xml! "](s,k,v,k)
+ else
+ result[#result+1]=formatters["%s<%s>%!xml!%s>"](s,k,v,k)
+ end
+ elseif tk=="number" then
+ result[#result+1]=formatters["%s%S "](s,k,v,k)
else
- local t = { }
- while n > 0 do
- insert(t,1,n % 2 > 0 and 1 or 0)
- n = floor(n/2)
- end
- local nn = 8 - #t % 8
- if nn > 0 and nn < 8 then
- for i=1,nn do
- insert(t,1,0)
- end
- end
- if m then
- m = m * 8 - #t
- if m > 0 then
- insert(t,1,rep("0",m))
- end
- end
- return concat(t)
+ result[#result+1]=formatters["%s<%s>%S%s>"](s,k,v,k)
+ end
+ end
+end
+function table.toxml(t,specification)
+ specification=specification or {}
+ local name=specification.name
+ local noroot=name==false
+ local result=(specification.nobanner or noroot) and {} or { "" }
+ local indent=specification.indent or 0
+ local spaces=specification.spaces or 1
+ if noroot then
+ toxml(t,indent,result,spaces)
+ else
+ toxml({ [name or "data"]=t },indent,result,spaces)
+ end
+ return concat(result,"\n")
+end
+function tables.encapsulate(core,capsule,protect)
+ if type(capsule)~="table" then
+ protect=true
+ capsule={}
+ end
+ for key,value in next,core do
+ if capsule[key] then
+ print(formatters["\ninvalid %s %a in %a"]("inheritance",key,core))
+ os.exit()
+ else
+ capsule[key]=value
+ end
+ end
+ if protect then
+ for key,value in next,core do
+ core[key]=nil
end
+ setmetatable(core,{
+ __index=capsule,
+ __newindex=function(t,key,value)
+ if capsule[key] then
+ print(formatters["\ninvalid %s %a' in %a"]("overload",key,core))
+ os.exit()
+ else
+ rawset(t,key,value)
+ end
+ end
+ } )
+ end
+end
+local function fastserialize(t,r,outer)
+ r[#r+1]="{"
+ local n=#t
+ if n>0 then
+ for i=1,n do
+ local v=t[i]
+ local tv=type(v)
+ if tv=="string" then
+ r[#r+1]=formatters["%q,"](v)
+ elseif tv=="number" then
+ r[#r+1]=formatters["%s,"](v)
+ elseif tv=="table" then
+ fastserialize(v,r)
+ elseif tv=="boolean" then
+ r[#r+1]=formatters["%S,"](v)
+ end
+ end
+ else
+ for k,v in next,t do
+ local tv=type(v)
+ if tv=="string" then
+ r[#r+1]=formatters["[%q]=%q,"](k,v)
+ elseif tv=="number" then
+ r[#r+1]=formatters["[%q]=%s,"](k,v)
+ elseif tv=="table" then
+ r[#r+1]=formatters["[%q]="](k)
+ fastserialize(v,r)
+ elseif tv=="boolean" then
+ r[#r+1]=formatters["[%q]=%S,"](k,v)
+ end
+ end
+ end
+ if outer then
+ r[#r+1]="}"
+ else
+ r[#r+1]="},"
+ end
+ return r
+end
+function table.fastserialize(t,prefix)
+ return concat(fastserialize(t,{ prefix or "return" },true))
+end
+function table.deserialize(str)
+ if not str or str=="" then
+ return
+ end
+ local code=load(str)
+ if not code then
+ return
+ end
+ code=code()
+ if not code then
+ return
+ end
+ return code
+end
+function table.load(filename)
+ if filename then
+ local t=io.loaddata(filename)
+ if t and t~="" then
+ t=load(t)
+ if type(t)=="function" then
+ t=t()
+ if type(t)=="table" then
+ return t
+ end
+ end
+ end
+ end
+end
+function table.save(filename,t,n,...)
+ io.savedata(filename,serialize(t,n==nil and true or n,...))
+end
+local function slowdrop(t)
+ local r={}
+ local l={}
+ for i=1,#t do
+ local ti=t[i]
+ local j=0
+ for k,v in next,ti do
+ j=j+1
+ l[j]=formatters["%s=%q"](k,v)
+ end
+ r[i]=formatters[" {%t},\n"](l)
+ end
+ return formatters["return {\n%st}"](r)
+end
+local function fastdrop(t)
+ local r={ "return {\n" }
+ for i=1,#t do
+ local ti=t[i]
+ r[#r+1]=" {"
+ for k,v in next,ti do
+ r[#r+1]=formatters["%s=%q"](k,v)
+ end
+ r[#r+1]="},\n"
+ end
+ r[#r+1]="}"
+ return concat(r)
+end
+function table.drop(t,slow)
+ if #t==0 then
+ return "return { }"
+ elseif slow==true then
+ return slowdrop(t)
+ else
+ return fastdrop(t)
+ end
+end
+function table.autokey(t,k)
+ local v={}
+ t[k]=v
+ return v
+end
+local selfmapper={ __index=function(t,k) t[k]=k return k end }
+function table.twowaymapper(t)
+ if not t then
+ t={}
+ else
+ for i=0,#t do
+ local ti=t[i]
+ if ti then
+ local i=tostring(i)
+ t[i]=ti
+ t[ti]=i
+ end
+ end
+ t[""]=t[0] or ""
+ end
+ setmetatable(t,selfmapper)
+ return t
end
-
end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-set'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- This will become obsolete when we have the bitset library embedded.
-
-set = set or { }
-
-local nums = { }
-local tabs = { }
-local concat = table.concat
-local next, type = next, type
+package.loaded["util-sto"] = package.loaded["util-sto"] or true
-set.create = table.tohash
+-- original size: 4432, stripped down to: 3123
-function set.tonumber(t)
- if next(t) then
- local s = ""
- -- we could save mem by sorting, but it slows down
- for k, v in next, t do
- if v then
- -- why bother about the leading space
- s = s .. " " .. k
- end
- end
- local n = nums[s]
- if not n then
- n = #tabs + 1
- tabs[n] = t
- nums[s] = n
- end
- return n
- else
- return 0
- end
+if not modules then modules={} end modules ['util-sto']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local setmetatable,getmetatable,type=setmetatable,getmetatable,type
+utilities=utilities or {}
+utilities.storage=utilities.storage or {}
+local storage=utilities.storage
+function storage.mark(t)
+ if not t then
+ print("\nfatal error: storage cannot be marked\n")
+ os.exit()
+ return
+ end
+ local m=getmetatable(t)
+ if not m then
+ m={}
+ setmetatable(t,m)
+ end
+ m.__storage__=true
+ return t
end
-
-function set.totable(n)
- if n == 0 then
- return { }
+function storage.allocate(t)
+ t=t or {}
+ local m=getmetatable(t)
+ if not m then
+ m={}
+ setmetatable(t,m)
+ end
+ m.__storage__=true
+ return t
+end
+function storage.marked(t)
+ local m=getmetatable(t)
+ return m and m.__storage__
+end
+function storage.checked(t)
+ if not t then
+ report("\nfatal error: storage has not been allocated\n")
+ os.exit()
+ return
+ end
+ return t
+end
+function storage.setinitializer(data,initialize)
+ local m=getmetatable(data) or {}
+ m.__index=function(data,k)
+ m.__index=nil
+ initialize()
+ return data[k]
+ end
+ setmetatable(data,m)
+end
+local keyisvalue={ __index=function(t,k)
+ t[k]=k
+ return k
+end }
+function storage.sparse(t)
+ t=t or {}
+ setmetatable(t,keyisvalue)
+ return t
+end
+local function f_empty () return "" end
+local function f_self (t,k) t[k]=k return k end
+local function f_table (t,k) local v={} t[k]=v return v end
+local function f_ignore() end
+local t_empty={ __index=f_empty }
+local t_self={ __index=f_self }
+local t_table={ __index=f_table }
+local t_ignore={ __newindex=f_ignore }
+function table.setmetatableindex(t,f)
+ if type(t)~="table" then
+ f,t=t,{}
+ end
+ local m=getmetatable(t)
+ if m then
+ if f=="empty" then
+ m.__index=f_empty
+ elseif f=="key" then
+ m.__index=f_self
+ elseif f=="table" then
+ m.__index=f_table
else
- return tabs[n] or { }
+ m.__index=f
+ end
+ else
+ if f=="empty" then
+ setmetatable(t,t_empty)
+ elseif f=="key" then
+ setmetatable(t,t_self)
+ elseif f=="table" then
+ setmetatable(t,t_table)
+ else
+ setmetatable(t,{ __index=f })
end
+ end
+ return t
end
-
-function set.tolist(n)
- if n == 0 or not tabs[n] then
- return ""
+function table.setmetatablenewindex(t,f)
+ if type(t)~="table" then
+ f,t=t,{}
+ end
+ local m=getmetatable(t)
+ if m then
+ if f=="ignore" then
+ m.__newindex=f_ignore
else
- local t, n = { }, 0
- for k, v in next, tabs[n] do
- if v then
- n = n + 1
- t[n] = k
- end
- end
- return concat(t," ")
+ m.__newindex=f
end
-end
-
-function set.contains(n,s)
- if type(n) == "table" then
- return n[s]
- elseif n == 0 then
- return false
+ else
+ if f=="ignore" then
+ setmetatable(t,t_ignore)
else
- local t = tabs[n]
- return t and t[s]
+ setmetatable(t,{ __newindex=f })
end
+ end
+ return t
+end
+function table.setmetatablecall(t,f)
+ if type(t)~="table" then
+ f,t=t,{}
+ end
+ local m=getmetatable(t)
+ if m then
+ m.__call=f
+ else
+ setmetatable(t,{ __call=f })
+ end
+ return t
+end
+function table.setmetatablekey(t,key,value)
+ local m=getmetatable(t)
+ if not m then
+ m={}
+ setmetatable(t,m)
+ end
+ m[key]=value
+ return t
+end
+function table.getmetatablekey(t,key,value)
+ local m=getmetatable(t)
+ return m and m[key]
end
-
-
end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-os'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- This file deals with some operating system issues. Please don't bother me
--- with the pros and cons of operating systems as they all have their flaws
--- and benefits. Bashing one of them won't help solving problems and fixing
--- bugs faster and is a waste of time and energy.
---
--- path separators: / or \ ... we can use / everywhere
--- suffixes : dll so exe ... no big deal
--- quotes : we can use "" in most cases
--- expansion : unless "" are used * might give side effects
--- piping/threads : somewhat different for each os
--- locations : specific user file locations and settings can change over time
---
--- os.type : windows | unix (new, we already guessed os.platform)
--- os.name : windows | msdos | linux | macosx | solaris | .. | generic (new)
--- os.platform : extended os.name with architecture
-
--- maybe build io.flush in os.execute
-
-local os = os
-local find, format, gsub, upper, gmatch = string.find, string.format, string.gsub, string.upper, string.gmatch
-local concat = table.concat
-local random, ceil = math.random, math.ceil
-local rawget, rawset, type, getmetatable, setmetatable, tonumber = rawget, rawset, type, getmetatable, setmetatable, tonumber
-
--- The following code permits traversing the environment table, at least
--- in luatex. Internally all environment names are uppercase.
-
-if not os.__getenv__ then
-
- os.__getenv__ = os.getenv
- os.__setenv__ = os.setenv
+package.loaded["util-prs"] = package.loaded["util-prs"] or true
- if os.env then
-
- local osgetenv = os.getenv
- local ossetenv = os.setenv
- local osenv = os.env local _ = osenv.PATH -- initialize the table
-
- function os.setenv(k,v)
- if v == nil then
- v = ""
- end
- local K = upper(k)
- osenv[K] = v
- if type(v) == "table" then
- v = concat(v,";") -- path
- end
- ossetenv(K,v)
- end
-
- function os.getenv(k)
- local K = upper(k)
- local v = osenv[K] or osenv[k] or osgetenv(K) or osgetenv(k)
- if v == "" then
- return nil
- else
- return v
- end
- end
+-- original size: 16976, stripped down to: 12143
+if not modules then modules={} end modules ['util-prs']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local lpeg,table,string=lpeg,table,string
+local P,R,V,S,C,Ct,Cs,Carg,Cc,Cg,Cf,Cp=lpeg.P,lpeg.R,lpeg.V,lpeg.S,lpeg.C,lpeg.Ct,lpeg.Cs,lpeg.Carg,lpeg.Cc,lpeg.Cg,lpeg.Cf,lpeg.Cp
+local lpegmatch,lpegpatterns=lpeg.match,lpeg.patterns
+local concat,format,gmatch,find=table.concat,string.format,string.gmatch,string.find
+local tostring,type,next,rawset=tostring,type,next,rawset
+utilities=utilities or {}
+local parsers=utilities.parsers or {}
+utilities.parsers=parsers
+local patterns=parsers.patterns or {}
+parsers.patterns=patterns
+local setmetatableindex=table.setmetatableindex
+local sortedhash=table.sortedhash
+local digit=R("09")
+local space=P(' ')
+local equal=P("=")
+local comma=P(",")
+local lbrace=P("{")
+local rbrace=P("}")
+local lparent=P("(")
+local rparent=P(")")
+local period=S(".")
+local punctuation=S(".,:;")
+local spacer=lpegpatterns.spacer
+local whitespace=lpegpatterns.whitespace
+local newline=lpegpatterns.newline
+local anything=lpegpatterns.anything
+local endofstring=lpegpatterns.endofstring
+local nobrace=1-(lbrace+rbrace )
+local noparent=1-(lparent+rparent)
+local escape,left,right=P("\\"),P('{'),P('}')
+lpegpatterns.balanced=P {
+ [1]=((escape*(left+right))+(1-(left+right))+V(2))^0,
+ [2]=left*V(1)*right
+}
+local nestedbraces=P { lbrace*(nobrace+V(1))^0*rbrace }
+local nestedparents=P { lparent*(noparent+V(1))^0*rparent }
+local spaces=space^0
+local argument=Cs((lbrace/"")*((nobrace+nestedbraces)^0)*(rbrace/""))
+local content=(1-endofstring)^0
+lpegpatterns.nestedbraces=nestedbraces
+lpegpatterns.nestedparents=nestedparents
+lpegpatterns.nested=nestedbraces
+lpegpatterns.argument=argument
+lpegpatterns.content=content
+local value=P(lbrace*C((nobrace+nestedbraces)^0)*rbrace)+C((nestedbraces+(1-comma))^0)
+local key=C((1-equal-comma)^1)
+local pattern_a=(space+comma)^0*(key*equal*value+key*C(""))
+local pattern_c=(space+comma)^0*(key*equal*value)
+local key=C((1-space-equal-comma)^1)
+local pattern_b=spaces*comma^0*spaces*(key*((spaces*equal*spaces*value)+C("")))
+local hash={}
+local function set(key,value)
+ hash[key]=value
+end
+local pattern_a_s=(pattern_a/set)^1
+local pattern_b_s=(pattern_b/set)^1
+local pattern_c_s=(pattern_c/set)^1
+patterns.settings_to_hash_a=pattern_a_s
+patterns.settings_to_hash_b=pattern_b_s
+patterns.settings_to_hash_c=pattern_c_s
+function parsers.make_settings_to_hash_pattern(set,how)
+ if how=="strict" then
+ return (pattern_c/set)^1
+ elseif how=="tolerant" then
+ return (pattern_b/set)^1
+ else
+ return (pattern_a/set)^1
+ end
+end
+function parsers.settings_to_hash(str,existing)
+ if str and str~="" then
+ hash=existing or {}
+ lpegmatch(pattern_a_s,str)
+ return hash
+ else
+ return {}
+ end
+end
+function parsers.settings_to_hash_tolerant(str,existing)
+ if str and str~="" then
+ hash=existing or {}
+ lpegmatch(pattern_b_s,str)
+ return hash
+ else
+ return {}
+ end
+end
+function parsers.settings_to_hash_strict(str,existing)
+ if str and str~="" then
+ hash=existing or {}
+ lpegmatch(pattern_c_s,str)
+ return next(hash) and hash
+ else
+ return nil
+ end
+end
+local separator=comma*space^0
+local value=P(lbrace*C((nobrace+nestedbraces)^0)*rbrace)+C((nestedbraces+(1-comma))^0)
+local pattern=spaces*Ct(value*(separator*value)^0)
+patterns.settings_to_array=pattern
+function parsers.settings_to_array(str,strict)
+ if not str or str=="" then
+ return {}
+ elseif strict then
+ if find(str,"{") then
+ return lpegmatch(pattern,str)
else
-
- local ossetenv = os.setenv
- local osgetenv = os.getenv
- local osenv = { }
-
- function os.setenv(k,v)
- if v == nil then
- v = ""
- end
- local K = upper(k)
- osenv[K] = v
- end
-
- function os.getenv(k)
- local K = upper(k)
- local v = osenv[K] or osgetenv(K) or osgetenv(k)
- if v == "" then
- return nil
- else
- return v
- end
- end
-
- local function __index(t,k)
- return os.getenv(k)
- end
- local function __newindex(t,k,v)
- os.setenv(k,v)
+ return { str }
+ end
+ else
+ return lpegmatch(pattern,str)
+ end
+end
+local function set(t,v)
+ t[#t+1]=v
+end
+local value=P(Carg(1)*value)/set
+local pattern=value*(separator*value)^0*Carg(1)
+function parsers.add_settings_to_array(t,str)
+ return lpegmatch(pattern,str,nil,t)
+end
+function parsers.hash_to_string(h,separator,yes,no,strict,omit)
+ if h then
+ local t,tn,s={},0,table.sortedkeys(h)
+ omit=omit and table.tohash(omit)
+ for i=1,#s do
+ local key=s[i]
+ if not omit or not omit[key] then
+ local value=h[key]
+ if type(value)=="boolean" then
+ if yes and no then
+ if value then
+ tn=tn+1
+ t[tn]=key..'='..yes
+ elseif not strict then
+ tn=tn+1
+ t[tn]=key..'='..no
+ end
+ elseif value or not strict then
+ tn=tn+1
+ t[tn]=key..'='..tostring(value)
+ end
+ else
+ tn=tn+1
+ t[tn]=key..'='..value
end
-
- os.env = { }
-
- setmetatable(os.env, { __index = __index, __newindex = __newindex } )
-
+ end
end
-
+ return concat(t,separator or ",")
+ else
+ return ""
+ end
end
-
--- end of environment hack
-
-local execute, spawn, exec, iopopen, ioflush = os.execute, os.spawn or os.execute, os.exec or os.execute, io.popen, io.flush
-
-function os.execute(...) ioflush() return execute(...) end
-function os.spawn (...) ioflush() return spawn (...) end
-function os.exec (...) ioflush() return exec (...) end
-function io.popen (...) ioflush() return iopopen(...) end
-
-function os.resultof(command)
- local handle = io.popen(command,"r")
- return handle and handle:read("*all") or ""
+function parsers.array_to_string(a,separator)
+ if a then
+ return concat(a,separator or ",")
+ else
+ return ""
+ end
+end
+function parsers.settings_to_set(str,t)
+ t=t or {}
+ for s in gmatch(str,"[^, ]+") do
+ t[s]=true
+ end
+ return t
+end
+function parsers.simple_hash_to_string(h,separator)
+ local t,tn={},0
+ for k,v in sortedhash(h) do
+ if v then
+ tn=tn+1
+ t[tn]=k
+ end
+ end
+ return concat(t,separator or ",")
end
-
-if not io.fileseparator then
- if find(os.getenv("PATH"),";") then
- io.fileseparator, io.pathseparator, os.type = "\\", ";", os.type or "mswin"
+local value=P(lbrace*C((nobrace+nestedbraces)^0)*rbrace)+C(digit^1*lparent*(noparent+nestedparents)^1*rparent)+C((nestedbraces+(1-comma))^1)
+local pattern_a=spaces*Ct(value*(separator*value)^0)
+local function repeater(n,str)
+ if not n then
+ return str
+ else
+ local s=lpegmatch(pattern_a,str)
+ if n==1 then
+ return unpack(s)
else
- io.fileseparator, io.pathseparator, os.type = "/" , ":", os.type or "unix"
- end
+ local t,tn={},0
+ for i=1,n do
+ for j=1,#s do
+ tn=tn+1
+ t[tn]=s[j]
+ end
+ end
+ return unpack(t)
+ end
+ end
+end
+local value=P(lbrace*C((nobrace+nestedbraces)^0)*rbrace)+(C(digit^1)/tonumber*lparent*Cs((noparent+nestedparents)^1)*rparent)/repeater+C((nestedbraces+(1-comma))^1)
+local pattern_b=spaces*Ct(value*(separator*value)^0)
+function parsers.settings_to_array_with_repeat(str,expand)
+ if expand then
+ return lpegmatch(pattern_b,str) or {}
+ else
+ return lpegmatch(pattern_a,str) or {}
+ end
+end
+local value=lbrace*C((nobrace+nestedbraces)^0)*rbrace
+local pattern=Ct((space+value)^0)
+function parsers.arguments_to_table(str)
+ return lpegmatch(pattern,str)
end
-
-os.type = os.type or (io.pathseparator == ";" and "windows") or "unix"
-os.name = os.name or (os.type == "windows" and "mswin" ) or "linux"
-
-if os.type == "windows" then
- os.libsuffix, os.binsuffix, os.binsuffixes = 'dll', 'exe', { 'exe', 'cmd', 'bat' }
-else
- os.libsuffix, os.binsuffix, os.binsuffixes = 'so', '', { '' }
+function parsers.getparameters(self,class,parentclass,settings)
+ local sc=self[class]
+ if not sc then
+ sc={}
+ self[class]=sc
+ if parentclass then
+ local sp=self[parentclass]
+ if not sp then
+ sp={}
+ self[parentclass]=sp
+ end
+ setmetatableindex(sc,sp)
+ end
+ end
+ parsers.settings_to_hash(settings,sc)
end
-
-function os.launch(str)
- if os.type == "windows" then
- os.execute("start " .. str) -- os.spawn ?
+function parsers.listitem(str)
+ return gmatch(str,"[^, ]+")
+end
+local pattern=Cs { "start",
+ start=V("one")+V("two")+V("three"),
+ rest=(Cc(",")*V("thousand"))^0*(P(".")+endofstring)*anything^0,
+ thousand=digit*digit*digit,
+ one=digit*V("rest"),
+ two=digit*digit*V("rest"),
+ three=V("thousand")*V("rest"),
+}
+lpegpatterns.splitthousands=pattern
+function parsers.splitthousands(str)
+ return lpegmatch(pattern,str) or str
+end
+local optionalwhitespace=whitespace^0
+lpegpatterns.words=Ct((Cs((1-punctuation-whitespace)^1)+anything)^1)
+lpegpatterns.sentences=Ct((optionalwhitespace*Cs((1-period)^0*period))^1)
+lpegpatterns.paragraphs=Ct((optionalwhitespace*Cs((whitespace^1*endofstring/""+1-(spacer^0*newline*newline))^1))^1)
+local dquote=P('"')
+local equal=P('=')
+local escape=P('\\')
+local separator=S(' ,')
+local key=C((1-equal)^1)
+local value=dquote*C((1-dquote-escape*dquote)^0)*dquote
+local pattern=Cf(Ct("")*Cg(key*equal*value)*separator^0,rawset)^0*P(-1)
+patterns.keq_to_hash_c=pattern
+function parsers.keq_to_hash(str)
+ if str and str~="" then
+ return lpegmatch(pattern,str)
+ else
+ return {}
+ end
+end
+local defaultspecification={ separator=",",quote='"' }
+function parsers.csvsplitter(specification)
+ specification=specification and table.setmetatableindex(specification,defaultspecification) or defaultspecification
+ local separator=specification.separator
+ local quotechar=specification.quote
+ local separator=S(separator~="" and separator or ",")
+ local whatever=C((1-separator-newline)^0)
+ if quotechar and quotechar~="" then
+ local quotedata=nil
+ for chr in gmatch(quotechar,".") do
+ local quotechar=P(chr)
+ local quoteword=quotechar*C((1-quotechar)^0)*quotechar
+ if quotedata then
+ quotedata=quotedata+quoteword
+ else
+ quotedata=quoteword
+ end
+ end
+ whatever=quotedata+whatever
+ end
+ local parser=Ct((Ct(whatever*(separator*whatever)^0)*S("\n\r"))^0 )
+ return function(data)
+ return lpegmatch(parser,data)
+ end
+end
+function parsers.rfc4180splitter(specification)
+ specification=specification and table.setmetatableindex(specification,defaultspecification) or defaultspecification
+ local separator=specification.separator
+ local quotechar=P(specification.quote)
+ local dquotechar=quotechar*quotechar
+/specification.quote
+ local separator=S(separator~="" and separator or ",")
+ local escaped=quotechar*Cs((dquotechar+(1-quotechar))^0)*quotechar
+ local non_escaped=C((1-quotechar-newline-separator)^1)
+ local field=escaped+non_escaped
+ local record=Ct((field*separator^-1)^1)
+ local headerline=record*Cp()
+ local wholeblob=Ct((newline^-1*record)^0)
+ return function(data,getheader)
+ if getheader then
+ local header,position=lpegmatch(headerline,data)
+ local data=lpegmatch(wholeblob,data,position)
+ return data,header
else
- os.execute(str .. " &") -- os.spawn ?
+ return lpegmatch(wholeblob,data)
+ end
+ end
+end
+local function ranger(first,last,n,action)
+ if not first then
+ elseif last==true then
+ for i=first,n or first do
+ action(i)
+ end
+ elseif last then
+ for i=first,last do
+ action(i)
+ end
+ else
+ action(first)
+ end
+end
+local cardinal=lpegpatterns.cardinal/tonumber
+local spacers=lpegpatterns.spacer^0
+local endofstring=lpegpatterns.endofstring
+local stepper=spacers*(C(cardinal)*(spacers*S(":-")*spacers*(C(cardinal)+Cc(true) )+Cc(false) )*Carg(1)*Carg(2)/ranger*S(", ")^0 )^1
+local stepper=spacers*(C(cardinal)*(spacers*S(":-")*spacers*(C(cardinal)+(P("*")+endofstring)*Cc(true) )+Cc(false) )*Carg(1)*Carg(2)/ranger*S(", ")^0 )^1*endofstring
+function parsers.stepper(str,n,action)
+ if type(n)=="function" then
+ lpegmatch(stepper,str,1,false,n or print)
+ else
+ lpegmatch(stepper,str,1,n,action or print)
+ end
+end
+local pattern_math=Cs((P("%")/"\\percent "+P("^")*Cc("{")*lpegpatterns.integer*Cc("}")+P(1))^0)
+local pattern_text=Cs((P("%")/"\\percent "+(P("^")/"\\high")*Cc("{")*lpegpatterns.integer*Cc("}")+P(1))^0)
+patterns.unittotex=pattern
+function parsers.unittotex(str,textmode)
+ return lpegmatch(textmode and pattern_text or pattern_math,str)
+end
+local pattern=Cs((P("^")/""*lpegpatterns.integer*Cc(" ")+P(1))^0)
+function parsers.unittoxml(str)
+ return lpegmatch(pattern,str)
+end
+local cache={}
+local spaces=lpeg.patterns.space^0
+local dummy=function() end
+table.setmetatableindex(cache,function(t,k)
+ local separator=P(k)
+ local value=(1-separator)^0
+ local pattern=spaces*C(value)*separator^0*Cp()
+ t[k]=pattern
+ return pattern
+end)
+local commalistiterator=cache[","]
+function utilities.parsers.iterator(str,separator)
+ local n=#str
+ if n==0 then
+ return dummy
+ else
+ local pattern=separator and cache[separator] or commalistiterator
+ local p=1
+ return function()
+ if p<=n then
+ local s,e=lpegmatch(pattern,str,p)
+ if e then
+ p=e
+ return s
+ end
+ end
end
+ end
end
-
-if not os.times then
- -- utime = user time
- -- stime = system time
- -- cutime = children user time
- -- cstime = children system time
- function os.times()
- return {
- utime = os.gettimeofday(), -- user
- stime = 0, -- system
- cutime = 0, -- children user
- cstime = 0, -- children system
- }
+local function initialize(t,name)
+ local source=t[name]
+ if source then
+ local result={}
+ for k,v in next,t[name] do
+ result[k]=v
end
+ return result
+ else
+ return {}
+ end
end
-
-os.gettimeofday = os.gettimeofday or os.clock
-
-local startuptime = os.gettimeofday()
-
-function os.runtime()
- return os.gettimeofday() - startuptime
+local function fetch(t,name)
+ return t[name] or {}
end
-
-
--- no need for function anymore as we have more clever code and helpers now
--- this metatable trickery might as well disappear
-
-os.resolvers = os.resolvers or { } -- will become private
-
-local resolvers = os.resolvers
-
-local osmt = getmetatable(os) or { __index = function(t,k) t[k] = "unset" return "unset" end } -- maybe nil
-local osix = osmt.__index
-
-osmt.__index = function(t,k)
- return (resolvers[k] or osix)(t,k)
+function process(result,more)
+ for k,v in next,more do
+ result[k]=v
+ end
+ return result
end
-
-setmetatable(os,osmt)
-
--- we can use HOSTTYPE on some platforms
-
-local name, platform = os.name or "linux", os.getenv("MTX_PLATFORM") or ""
-
-local function guess()
- local architecture = os.resultof("uname -m") or ""
- if architecture ~= "" then
- return architecture
- end
- architecture = os.getenv("HOSTTYPE") or ""
- if architecture ~= "" then
- return architecture
- end
- return os.resultof("echo $HOSTTYPE") or ""
+local name=C((1-S(", "))^1)
+local parser=(Carg(1)*name/initialize)*(S(", ")^1*(Carg(1)*name/fetch))^0
+local merge=Cf(parser,process)
+function utilities.parsers.mergehashes(hash,list)
+ return lpegmatch(merge,list,1,hash)
end
-if platform ~= "" then
-
- os.platform = platform
-elseif os.type == "windows" then
+end -- of closure
- -- we could set the variable directly, no function needed here
+do -- create closure to overcome 200 locals limit
- function os.resolvers.platform(t,k)
- local platform, architecture = "", os.getenv("PROCESSOR_ARCHITECTURE") or ""
- if find(architecture,"AMD64") then
- platform = "mswin-64"
- else
- platform = "mswin"
- end
- os.setenv("MTX_PLATFORM",platform)
- os.platform = platform
- return platform
- end
+package.loaded["util-fmt"] = package.loaded["util-fmt"] or true
-elseif name == "linux" then
+-- original size: 2274, stripped down to: 1781
- function os.resolvers.platform(t,k)
- -- we sometimes have HOSTTYPE set so let's check that first
- local platform, architecture = "", os.getenv("HOSTTYPE") or os.resultof("uname -m") or ""
- if find(architecture,"x86_64") then
- platform = "linux-64"
- elseif find(architecture,"ppc") then
- platform = "linux-ppc"
- else
- platform = "linux"
- end
- os.setenv("MTX_PLATFORM",platform)
- os.platform = platform
- return platform
- end
-
-elseif name == "macosx" then
-
- --[[
- Identifying the architecture of OSX is quite a mess and this
- is the best we can come up with. For some reason $HOSTTYPE is
- a kind of pseudo environment variable, not known to the current
- environment. And yes, uname cannot be trusted either, so there
- is a change that you end up with a 32 bit run on a 64 bit system.
- Also, some proper 64 bit intel macs are too cheap (low-end) and
- therefore not permitted to run the 64 bit kernel.
- ]]--
-
- function os.resolvers.platform(t,k)
- -- local platform, architecture = "", os.getenv("HOSTTYPE") or ""
- -- if architecture == "" then
- -- architecture = os.resultof("echo $HOSTTYPE") or ""
- -- end
- local platform, architecture = "", os.resultof("echo $HOSTTYPE") or ""
- if architecture == "" then
- -- print("\nI have no clue what kind of OSX you're running so let's assume an 32 bit intel.\n")
- platform = "osx-intel"
- elseif find(architecture,"i386") then
- platform = "osx-intel"
- elseif find(architecture,"x86_64") then
- platform = "osx-64"
+if not modules then modules={} end modules ['util-fmt']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+utilities=utilities or {}
+utilities.formatters=utilities.formatters or {}
+local formatters=utilities.formatters
+local concat,format=table.concat,string.format
+local tostring,type=tostring,type
+local strip=string.strip
+local lpegmatch=lpeg.match
+local stripper=lpeg.patterns.stripzeros
+function formatters.stripzeros(str)
+ return lpegmatch(stripper,str)
+end
+function formatters.formatcolumns(result,between)
+ if result and #result>0 then
+ between=between or " "
+ local widths,numbers={},{}
+ local first=result[1]
+ local n=#first
+ for i=1,n do
+ widths[i]=0
+ end
+ for i=1,#result do
+ local r=result[i]
+ for j=1,n do
+ local rj=r[j]
+ local tj=type(rj)
+ if tj=="number" then
+ numbers[j]=true
+ end
+ if tj~="string" then
+ rj=tostring(rj)
+ r[j]=rj
+ end
+ local w=#rj
+ if w>widths[j] then
+ widths[j]=w
+ end
+ end
+ end
+ for i=1,n do
+ local w=widths[i]
+ if numbers[i] then
+ if w>80 then
+ widths[i]="%s"..between
+ else
+ widths[i]="%0"..w.."i"..between
+ end
+ else
+ if w>80 then
+ widths[i]="%s"..between
+ elseif w>0 then
+ widths[i]="%-"..w.."s"..between
else
- platform = "osx-ppc"
+ widths[i]="%s"
end
- os.setenv("MTX_PLATFORM",platform)
- os.platform = platform
- return platform
+ end
+ end
+ local template=strip(concat(widths))
+ for i=1,#result do
+ local str=format(template,unpack(result[i]))
+ result[i]=strip(str)
end
+ end
+ return result
+end
-elseif name == "sunos" then
- function os.resolvers.platform(t,k)
- local platform, architecture = "", os.resultof("uname -m") or ""
- if find(architecture,"sparc") then
- platform = "solaris-sparc"
- else -- if architecture == 'i86pc'
- platform = "solaris-intel"
- end
- os.setenv("MTX_PLATFORM",platform)
- os.platform = platform
- return platform
- end
+end -- of closure
-elseif name == "freebsd" then
+do -- create closure to overcome 200 locals limit
- function os.resolvers.platform(t,k)
- local platform, architecture = "", os.resultof("uname -m") or ""
- if find(architecture,"amd64") then
- platform = "freebsd-amd64"
- else
- platform = "freebsd"
- end
- os.setenv("MTX_PLATFORM",platform)
- os.platform = platform
- return platform
- end
+package.loaded["trac-set"] = package.loaded["trac-set"] or true
-elseif name == "kfreebsd" then
+-- original size: 12365, stripped down to: 8799
- function os.resolvers.platform(t,k)
- -- we sometimes have HOSTTYPE set so let's check that first
- local platform, architecture = "", os.getenv("HOSTTYPE") or os.resultof("uname -m") or ""
- if find(architecture,"x86_64") then
- platform = "kfreebsd-amd64"
+if not modules then modules={} end modules ['trac-set']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local type,next,tostring=type,next,tostring
+local concat=table.concat
+local format,find,lower,gsub,topattern=string.format,string.find,string.lower,string.gsub,string.topattern
+local is_boolean=string.is_boolean
+local settings_to_hash=utilities.parsers.settings_to_hash
+local allocate=utilities.storage.allocate
+utilities=utilities or {}
+local utilities=utilities
+local setters=utilities.setters or {}
+utilities.setters=setters
+local data={}
+local trace_initialize=false
+function setters.initialize(filename,name,values)
+ local setter=data[name]
+ if setter then
+ frozen=true
+ local data=setter.data
+ if data then
+ for key,newvalue in next,values do
+ local newvalue=is_boolean(newvalue,newvalue)
+ local functions=data[key]
+ if functions then
+ local oldvalue=functions.value
+ if functions.frozen then
+ if trace_initialize then
+ setter.report("%s: %a is %s to %a",filename,key,"frozen",oldvalue)
+ end
+ elseif #functions>0 and not oldvalue then
+ if trace_initialize then
+ setter.report("%s: %a is %s to %a",filename,key,"set",newvalue)
+ end
+ for i=1,#functions do
+ functions[i](newvalue)
+ end
+ functions.value=newvalue
+ functions.frozen=functions.frozen or frozen
+ else
+ if trace_initialize then
+ setter.report("%s: %a is %s as %a",filename,key,"kept",oldvalue)
+ end
+ end
else
- platform = "kfreebsd-i386"
+ functions={ default=newvalue,frozen=frozen }
+ data[key]=functions
+ if trace_initialize then
+ setter.report("%s: %a is %s to %a",filename,key,"defaulted",newvalue)
+ end
end
- os.setenv("MTX_PLATFORM",platform)
- os.platform = platform
- return platform
+ end
+ return true
end
-
-else
-
- -- platform = "linux"
- -- os.setenv("MTX_PLATFORM",platform)
- -- os.platform = platform
-
- function os.resolvers.platform(t,k)
- local platform = "linux"
- os.setenv("MTX_PLATFORM",platform)
- os.platform = platform
- return platform
- end
-
+ end
end
-
--- beware, we set the randomseed
-
--- from wikipedia: Version 4 UUIDs use a scheme relying only on random numbers. This algorithm sets the
--- version number as well as two reserved bits. All other bits are set using a random or pseudorandom
--- data source. Version 4 UUIDs have the form xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx with hexadecimal
--- digits x and hexadecimal digits 8, 9, A, or B for y. e.g. f47ac10b-58cc-4372-a567-0e02b2c3d479.
---
--- as we don't call this function too often there is not so much risk on repetition
-
-local t = { 8, 9, "a", "b" }
-
-function os.uuid()
- return format("%04x%04x-4%03x-%s%03x-%04x-%04x%04x%04x",
- random(0xFFFF),random(0xFFFF),
- random(0x0FFF),
- t[ceil(random(4))] or 8,random(0x0FFF),
- random(0xFFFF),
- random(0xFFFF),random(0xFFFF),random(0xFFFF)
- )
+local function set(t,what,newvalue)
+ local data=t.data
+ if not data.frozen then
+ local done=t.done
+ if type(what)=="string" then
+ what=settings_to_hash(what)
+ end
+ if type(what)~="table" then
+ return
+ end
+ if not done then
+ done={}
+ t.done=done
+ end
+ for w,value in next,what do
+ if value=="" then
+ value=newvalue
+ elseif not value then
+ value=false
+ else
+ value=is_boolean(value,value)
+ end
+ w=topattern(w,true,true)
+ for name,functions in next,data do
+ if done[name] then
+ elseif find(name,w) then
+ done[name]=true
+ for i=1,#functions do
+ functions[i](value)
+ end
+ functions.value=value
+ end
+ end
+ end
+ end
end
-
-local d
-
-function os.timezone(delta)
- d = d or tonumber(tonumber(os.date("%H")-os.date("!%H")))
- if delta then
- if d > 0 then
- return format("+%02i:00",d)
- else
- return format("-%02i:00",-d)
- end
+local function reset(t)
+ local data=t.data
+ if not data.frozen then
+ for name,functions in next,data do
+ for i=1,#functions do
+ functions[i](false)
+ end
+ functions.value=false
+ end
+ end
+end
+local function enable(t,what)
+ set(t,what,true)
+end
+local function disable(t,what)
+ local data=t.data
+ if not what or what=="" then
+ t.done={}
+ reset(t)
+ else
+ set(t,what,false)
+ end
+end
+function setters.register(t,what,...)
+ local data=t.data
+ what=lower(what)
+ local functions=data[what]
+ if not functions then
+ functions={}
+ data[what]=functions
+ if trace_initialize then
+ t.report("defining %a",what)
+ end
+ end
+ local default=functions.default
+ for i=1,select("#",...) do
+ local fnc=select(i,...)
+ local typ=type(fnc)
+ if typ=="string" then
+ if trace_initialize then
+ t.report("coupling %a to %a",what,fnc)
+ end
+ local s=fnc
+ fnc=function(value) set(t,s,value) end
+ elseif typ~="function" then
+ fnc=nil
+ end
+ if fnc then
+ functions[#functions+1]=fnc
+ local value=functions.value or default
+ if value~=nil then
+ fnc(value)
+ functions.value=value
+ end
+ end
+ end
+ return false
+end
+function setters.enable(t,what)
+ local e=t.enable
+ t.enable,t.done=enable,{}
+ enable(t,what)
+ t.enable,t.done=e,{}
+end
+function setters.disable(t,what)
+ local e=t.disable
+ t.disable,t.done=disable,{}
+ disable(t,what)
+ t.disable,t.done=e,{}
+end
+function setters.reset(t)
+ t.done={}
+ reset(t)
+end
+function setters.list(t)
+ local list=table.sortedkeys(t.data)
+ local user,system={},{}
+ for l=1,#list do
+ local what=list[l]
+ if find(what,"^%*") then
+ system[#system+1]=what
else
- return 1
+ user[#user+1]=what
end
+ end
+ return user,system
end
-
-local memory = { }
-
-local function which(filename)
- local fullname = memory[filename]
- if fullname == nil then
- local suffix = file.suffix(filename)
- local suffixes = suffix == "" and os.binsuffixes or { suffix }
- for directory in gmatch(os.getenv("PATH"),"[^" .. io.pathseparator .."]+") do
- local df = file.join(directory,filename)
- for i=1,#suffixes do
- local dfs = file.addsuffix(df,suffixes[i])
- if io.exists(dfs) then
- fullname = dfs
- break
- end
- end
- end
- if not fullname then
- fullname = false
- end
- memory[filename] = fullname
+function setters.show(t)
+ local category=t.name
+ local list=setters.list(t)
+ t.report()
+ for k=1,#list do
+ local name=list[k]
+ local functions=t.data[name]
+ if functions then
+ local value,default,modules=functions.value,functions.default,#functions
+ value=value==nil and "unset" or tostring(value)
+ default=default==nil and "unset" or tostring(default)
+ t.report("%-50s modules: %2i default: %-12s value: %-12s",name,modules,default,value)
+ end
+ end
+ t.report()
+end
+local enable,disable,register,list,show=setters.enable,setters.disable,setters.register,setters.list,setters.show
+function setters.report(setter,...)
+ print(format("%-15s : %s\n",setter.name,format(...)))
+end
+local function default(setter,name)
+ local d=setter.data[name]
+ return d and d.default
+end
+local function value(setter,name)
+ local d=setter.data[name]
+ return d and (d.value or d.default)
+end
+function setters.new(name)
+ local setter
+ setter={
+ data=allocate(),
+ name=name,
+ report=function(...) setters.report (setter,...) end,
+ enable=function(...) enable (setter,...) end,
+ disable=function(...) disable (setter,...) end,
+ register=function(...) register(setter,...) end,
+ list=function(...) list (setter,...) end,
+ show=function(...) show (setter,...) end,
+ default=function(...) return default (setter,...) end,
+ value=function(...) return value (setter,...) end,
+ }
+ data[name]=setter
+ return setter
+end
+trackers=setters.new("trackers")
+directives=setters.new("directives")
+experiments=setters.new("experiments")
+local t_enable,t_disable=trackers .enable,trackers .disable
+local d_enable,d_disable=directives .enable,directives .disable
+local e_enable,e_disable=experiments.enable,experiments.disable
+local trace_directives=false local trace_directives=false trackers.register("system.directives",function(v) trace_directives=v end)
+local trace_experiments=false local trace_experiments=false trackers.register("system.experiments",function(v) trace_experiments=v end)
+function directives.enable(...)
+ if trace_directives then
+ directives.report("enabling: % t",{...})
+ end
+ d_enable(...)
+end
+function directives.disable(...)
+ if trace_directives then
+ directives.report("disabling: % t",{...})
+ end
+ d_disable(...)
+end
+function experiments.enable(...)
+ if trace_experiments then
+ experiments.report("enabling: % t",{...})
+ end
+ e_enable(...)
+end
+function experiments.disable(...)
+ if trace_experiments then
+ experiments.report("disabling: % t",{...})
+ end
+ e_disable(...)
+end
+directives.register("system.nostatistics",function(v)
+ if statistics then
+ statistics.enable=not v
+ else
+ end
+end)
+directives.register("system.nolibraries",function(v)
+ if libraries then
+ libraries=nil
+ else
+ end
+end)
+if environment then
+ local engineflags=environment.engineflags
+ if engineflags then
+ local list=engineflags["c:trackers"] or engineflags["trackers"]
+ if type(list)=="string" then
+ setters.initialize("commandline flags","trackers",settings_to_hash(list))
end
- return fullname
+ local list=engineflags["c:directives"] or engineflags["directives"]
+ if type(list)=="string" then
+ setters.initialize("commandline flags","directives",settings_to_hash(list))
+ end
+ end
+end
+if texconfig then
+ local function set(k,v)
+ v=tonumber(v)
+ if v then
+ texconfig[k]=v
+ end
+ end
+ directives.register("luatex.expanddepth",function(v) set("expand_depth",v) end)
+ directives.register("luatex.hashextra",function(v) set("hash_extra",v) end)
+ directives.register("luatex.nestsize",function(v) set("nest_size",v) end)
+ directives.register("luatex.maxinopen",function(v) set("max_in_open",v) end)
+ directives.register("luatex.maxprintline",function(v) set("max_print_line",v) end)
+ directives.register("luatex.maxstrings",function(v) set("max_strings",v) end)
+ directives.register("luatex.paramsize",function(v) set("param_size",v) end)
+ directives.register("luatex.savesize",function(v) set("save_size",v) end)
+ directives.register("luatex.stacksize",function(v) set("stack_size",v) end)
end
-
-os.which = which
-os.where = which
-
--- print(os.which("inkscape.exe"))
--- print(os.which("inkscape"))
--- print(os.which("gs.exe"))
--- print(os.which("ps2pdf"))
end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-file'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- needs a cleanup
-
-file = file or { }
-local file = file
-
-local insert, concat = table.insert, table.concat
-local find, gmatch, match, gsub, sub, char, lower = string.find, string.gmatch, string.match, string.gsub, string.sub, string.char, string.lower
-local lpegmatch = lpeg.match
-local getcurrentdir, attributes = lfs.currentdir, lfs.attributes
+package.loaded["trac-log"] = package.loaded["trac-log"] or true
-local P, R, S, C, Cs, Cp, Cc = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Cs, lpeg.Cp, lpeg.Cc
+-- original size: 21795, stripped down to: 14194
-local function dirname(name,default)
- return match(name,"^(.+)[/\\].-$") or (default or "")
+if not modules then modules={} end modules ['trac-log']={
+ version=1.001,
+ comment="companion to trac-log.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local write_nl,write=texio and texio.write_nl or print,texio and texio.write or io.write
+local format,gmatch,find=string.format,string.gmatch,string.find
+local concat,insert,remove=table.concat,table.insert,table.remove
+local topattern=string.topattern
+local texcount=tex and tex.count
+local next,type,select=next,type,select
+local utfchar=utf.char
+local setmetatableindex=table.setmetatableindex
+local formatters=string.formatters
+logs=logs or {}
+local logs=logs
+local moreinfo=[[
+More information about ConTeXt and the tools that come with it can be found at:
+]].."\n"..[[
+maillist : ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+webpage : http://www.pragma-ade.nl / http://tex.aanhet.net
+wiki : http://contextgarden.net
+]]
+utilities.strings.formatters.add (
+ formatters,"unichr",
+ [["U+" .. format("%%05X",%s) .. " (" .. utfchar(%s) .. ")"]]
+)
+utilities.strings.formatters.add (
+ formatters,"chruni",
+ [[utfchar(%s) .. " (U+" .. format("%%05X",%s) .. ")"]]
+)
+local function ignore() end
+setmetatableindex(logs,function(t,k) t[k]=ignore;return ignore end)
+local report,subreport,status,settarget,setformats,settranslations
+local direct,subdirect,writer,pushtarget,poptarget
+if tex and (tex.jobname or tex.formatname) then
+ local valueiskey={ __index=function(t,k) t[k]=k return k end }
+ local target="term and log"
+ logs.flush=io.flush
+ local formats={} setmetatable(formats,valueiskey)
+ local translations={} setmetatable(translations,valueiskey)
+ writer=function(...)
+ write_nl(target,...)
+ end
+ newline=function()
+ write_nl(target,"\n")
+ end
+ local f_one=formatters["%-15s > %s\n"]
+ local f_two=formatters["%-15s >\n"]
+ report=function(a,b,c,...)
+ if c then
+ write_nl(target,f_one(translations[a],formatters[formats[b]](c,...)))
+ elseif b then
+ write_nl(target,f_one(translations[a],formats[b]))
+ elseif a then
+ write_nl(target,f_two(translations[a]))
+ else
+ write_nl(target,"\n")
+ end
+ end
+ local f_one=formatters["%-15s > %s"]
+ local f_two=formatters["%-15s >"]
+ direct=function(a,b,c,...)
+ if c then
+ return f_one(translations[a],formatters[formats[b]](c,...))
+ elseif b then
+ return f_one(translations[a],formats[b])
+ elseif a then
+ return f_two(translations[a])
+ else
+ return ""
+ end
+ end
+ local f_one=formatters["%-15s > %s > %s\n"]
+ local f_two=formatters["%-15s > %s >\n"]
+ subreport=function(a,s,b,c,...)
+ if c then
+ write_nl(target,f_one(translations[a],translations[s],formatters[formats[b]](c,...)))
+ elseif b then
+ write_nl(target,f_one(translations[a],translations[s],formats[b]))
+ elseif a then
+ write_nl(target,f_two(translations[a],translations[s]))
+ else
+ write_nl(target,"\n")
+ end
+ end
+ local f_one=formatters["%-15s > %s > %s"]
+ local f_two=formatters["%-15s > %s >"]
+ subdirect=function(a,s,b,c,...)
+ if c then
+ return f_one(translations[a],translations[s],formatters[formats[b]](c,...))
+ elseif b then
+ return f_one(translations[a],translations[s],formats[b])
+ elseif a then
+ return f_two(translations[a],translations[s])
+ else
+ return ""
+ end
+ end
+ local f_one=formatters["%-15s : %s\n"]
+ local f_two=formatters["%-15s :\n"]
+ status=function(a,b,c,...)
+ if c then
+ write_nl(target,f_one(translations[a],formatters[formats[b]](c,...)))
+ elseif b then
+ write_nl(target,f_one(translations[a],formats[b]))
+ elseif a then
+ write_nl(target,f_two(translations[a]))
+ else
+ write_nl(target,"\n")
+ end
+ end
+ local targets={
+ logfile="log",
+ log="log",
+ file="log",
+ console="term",
+ terminal="term",
+ both="term and log",
+ }
+ settarget=function(whereto)
+ target=targets[whereto or "both"] or targets.both
+ if target=="term" or target=="term and log" then
+ logs.flush=io.flush
+ else
+ logs.flush=ignore
+ end
+ end
+ local stack={}
+ pushtarget=function(newtarget)
+ insert(stack,target)
+ settarget(newtarget)
+ end
+ poptarget=function()
+ if #stack>0 then
+ settarget(remove(stack))
+ end
+ end
+ setformats=function(f)
+ formats=f
+ end
+ settranslations=function(t)
+ translations=t
+ end
+else
+ logs.flush=ignore
+ writer=write_nl
+ newline=function()
+ write_nl("\n")
+ end
+ local f_one=formatters["%-15s | %s"]
+ local f_two=formatters["%-15s |"]
+ report=function(a,b,c,...)
+ if c then
+ write_nl(f_one(a,formatters[b](c,...)))
+ elseif b then
+ write_nl(f_one(a,b))
+ elseif a then
+ write_nl(f_two(a))
+ else
+ write_nl("")
+ end
+ end
+ local f_one=formatters["%-15s | %s | %s"]
+ local f_two=formatters["%-15s | %s |"]
+ subreport=function(a,sub,b,c,...)
+ if c then
+ write_nl(f_one(a,sub,formatters[b](c,...)))
+ elseif b then
+ write_nl(f_one(a,sub,b))
+ elseif a then
+ write_nl(f_two(a,sub))
+ else
+ write_nl("")
+ end
+ end
+ local f_one=formatters["%-15s : %s\n"]
+ local f_two=formatters["%-15s :\n"]
+ status=function(a,b,c,...)
+ if c then
+ write_nl(f_one(a,formatters[b](c,...)))
+ elseif b then
+ write_nl(f_one(a,b))
+ elseif a then
+ write_nl(f_two(a))
+ else
+ write_nl("\n")
+ end
+ end
+ direct=ignore
+ subdirect=ignore
+ settarget=ignore
+ pushtarget=ignore
+ poptarget=ignore
+ setformats=ignore
+ settranslations=ignore
+end
+logs.report=report
+logs.subreport=subreport
+logs.status=status
+logs.settarget=settarget
+logs.pushtarget=pushtarget
+logs.poptarget=poptarget
+logs.setformats=setformats
+logs.settranslations=settranslations
+logs.direct=direct
+logs.subdirect=subdirect
+logs.writer=writer
+logs.newline=newline
+local data,states={},nil
+function logs.reporter(category,subcategory)
+ local logger=data[category]
+ if not logger then
+ local state=false
+ if states==true then
+ state=true
+ elseif type(states)=="table" then
+ for c,_ in next,states do
+ if find(category,c) then
+ state=true
+ break
+ end
+ end
+ end
+ logger={
+ reporters={},
+ state=state,
+ }
+ data[category]=logger
+ end
+ local reporter=logger.reporters[subcategory or "default"]
+ if not reporter then
+ if subcategory then
+ reporter=function(...)
+ if not logger.state then
+ subreport(category,subcategory,...)
+ end
+ end
+ logger.reporters[subcategory]=reporter
+ else
+ local tag=category
+ reporter=function(...)
+ if not logger.state then
+ report(category,...)
+ end
+ end
+ logger.reporters.default=reporter
+ end
+ end
+ return reporter
end
-
-local function basename(name)
- return match(name,"^.+[/\\](.-)$") or name
+logs.new=logs.reporter
+local ctxreport=logs.writer
+function logs.setmessenger(m)
+ ctxreport=m
end
-
--- local function nameonly(name)
--- return (gsub(match(name,"^.+[/\\](.-)$") or name,"%..*$",""))
--- end
-
-local function nameonly(name)
- return (gsub(match(name,"^.+[/\\](.-)$") or name,"%.[%a%d]+$",""))
+function logs.messenger(category,subcategory)
+ if subcategory then
+ return function(...)
+ ctxreport(subdirect(category,subcategory,...))
+ end
+ else
+ return function(...)
+ ctxreport(direct(category,...))
+ end
+ end
end
-
-local function extname(name,default)
- return match(name,"^.+%.([^/\\]-)$") or default or ""
+local function setblocked(category,value)
+ if category==true then
+ category,value="*",true
+ elseif category==false then
+ category,value="*",false
+ elseif value==nil then
+ value=true
+ end
+ if category=="*" then
+ states=value
+ for k,v in next,data do
+ v.state=value
+ end
+ else
+ states=utilities.parsers.settings_to_hash(category)
+ for c,_ in next,states do
+ if data[c] then
+ v.state=value
+ else
+ c=topattern(c,true,true)
+ for k,v in next,data do
+ if find(k,c) then
+ v.state=value
+ end
+ end
+ end
+ end
+ end
end
-
-local function splitname(name)
- local n, s = match(name,"^(.+)%.([^/\\]-)$")
- return n or name, s or ""
+function logs.disable(category,value)
+ setblocked(category,value==nil and true or value)
end
-
-file.basename = basename
-file.dirname = dirname
-file.nameonly = nameonly
-file.extname = extname
-file.suffix = extname
-
-function file.removesuffix(filename)
- return (gsub(filename,"%.[%a%d]+$",""))
+function logs.enable(category)
+ setblocked(category,false)
end
-
-function file.addsuffix(filename, suffix, criterium)
- if not suffix or suffix == "" then
- return filename
- elseif criterium == true then
- return filename .. "." .. suffix
- elseif not criterium then
- local n, s = splitname(filename)
- if not s or s == "" then
- return filename .. "." .. suffix
- else
- return filename
- end
+function logs.categories()
+ return table.sortedkeys(data)
+end
+function logs.show()
+ local n,c,s,max=0,0,0,0
+ for category,v in table.sortedpairs(data) do
+ n=n+1
+ local state=v.state
+ local reporters=v.reporters
+ local nc=#category
+ if nc>c then
+ c=nc
+ end
+ for subcategory,_ in next,reporters do
+ local ns=#subcategory
+ if ns>c then
+ s=ns
+ end
+ local m=nc+ns
+ if m>max then
+ max=m
+ end
+ end
+ local subcategories=concat(table.sortedkeys(reporters),", ")
+ if state==true then
+ state="disabled"
+ elseif state==false then
+ state="enabled"
else
- local n, s = splitname(filename)
- if s and s ~= "" then
- local t = type(criterium)
- if t == "table" then
- -- keep if in criterium
- for i=1,#criterium do
- if s == criterium[i] then
- return filename
- end
- end
- elseif t == "string" then
- -- keep if criterium
- if s == criterium then
- return filename
- end
- end
- end
- return n .. "." .. suffix
+ state="unknown"
end
+ report("logging","category %a, subcategories %a, state %a",category,subcategories,state)
+ end
+ report("logging","categories: %s, max category: %s, max subcategory: %s, max combined: %s",n,c,s,max)
end
-
-
-function file.replacesuffix(filename, suffix)
- return (gsub(filename,"%.[%a%d]+$","")) .. "." .. suffix
+local delayed_reporters={}
+setmetatableindex(delayed_reporters,function(t,k)
+ local v=logs.reporter(k.name)
+ t[k]=v
+ return v
+end)
+function utilities.setters.report(setter,...)
+ delayed_reporters[setter](...)
end
-
-
-local trick_1 = char(1)
-local trick_2 = "^" .. trick_1 .. "/+"
-
-function file.join(...) -- rather dirty
- local lst = { ... }
- local a, b = lst[1], lst[2]
- if not a or a == "" then -- not a added
- lst[1] = trick_1
- elseif b and find(a,"^/+$") and find(b,"^/") then
- lst[1] = ""
- lst[2] = gsub(b,"^/+","")
- end
- local pth = concat(lst,"/")
- pth = gsub(pth,"\\","/")
- local a, b = match(pth,"^(.*://)(.*)$")
- if a and b then
- return a .. gsub(b,"//+","/")
+directives.register("logs.blocked",function(v)
+ setblocked(v,true)
+end)
+directives.register("logs.target",function(v)
+ settarget(v)
+end)
+local report_pages=logs.reporter("pages")
+local real,user,sub
+function logs.start_page_number()
+ real,user,sub=texcount.realpageno,texcount.userpageno,texcount.subpageno
+end
+local timing=false
+local starttime=nil
+local lasttime=nil
+trackers.register("pages.timing",function(v)
+ starttime=os.clock()
+ timing=true
+end)
+function logs.stop_page_number()
+ if timing then
+ local elapsed,average
+ local stoptime=os.clock()
+ if not lasttime or real<2 then
+ elapsed=stoptime
+ average=stoptime
+ starttime=stoptime
+ else
+ elapsed=stoptime-lasttime
+ average=(stoptime-starttime)/(real-1)
+ end
+ lasttime=stoptime
+ if real<=0 then
+ report_pages("flushing page, time %0.04f / %0.04f",elapsed,average)
+ elseif user<=0 then
+ report_pages("flushing realpage %s, time %0.04f / %0.04f",real,elapsed,average)
+ elseif sub<=0 then
+ report_pages("flushing realpage %s, userpage %s, time %0.04f / %0.04f",real,user,elapsed,average)
+ else
+ report_pages("flushing realpage %s, userpage %s, subpage %s, time %0.04f / %0.04f",real,user,sub,elapsed,average)
+ end
+ else
+ if real<=0 then
+ report_pages("flushing page")
+ elseif user<=0 then
+ report_pages("flushing realpage %s",real)
+ elseif sub<=0 then
+ report_pages("flushing realpage %s, userpage %s",real,user)
+ else
+ report_pages("flushing realpage %s, userpage %s, subpage %s",real,user,sub)
end
- a, b = match(pth,"^(//)(.*)$")
- if a and b then
- return a .. gsub(b,"//+","/")
+ end
+ logs.flush()
+end
+local report_files=logs.reporter("files")
+local nesting=0
+local verbose=false
+local hasscheme=url.hasscheme
+function logs.show_open(name)
+end
+function logs.show_close(name)
+end
+function logs.show_load(name)
+end
+local simple=logs.reporter("comment")
+logs.simple=simple
+logs.simpleline=simple
+function logs.setprogram () end
+function logs.extendbanner() end
+function logs.reportlines () end
+function logs.reportbanner() end
+function logs.reportline () end
+function logs.simplelines () end
+function logs.help () end
+local Carg,C,lpegmatch=lpeg.Carg,lpeg.C,lpeg.match
+local p_newline=lpeg.patterns.newline
+local linewise=(
+ Carg(1)*C((1-p_newline)^1)/function(t,s) t.report(s) end+Carg(1)*p_newline^2/function(t) t.report() end+p_newline
+)^1
+local function reportlines(t,str)
+ if str then
+ lpegmatch(linewise,str,1,t)
+ end
+end
+local function reportbanner(t)
+ local banner=t.banner
+ if banner then
+ t.report(banner)
+ t.report()
+ end
+end
+local function reportversion(t)
+ local banner=t.banner
+ if banner then
+ t.report(banner)
+ end
+end
+local function reporthelp(t,...)
+ local helpinfo=t.helpinfo
+ if type(helpinfo)=="string" then
+ reportlines(t,helpinfo)
+ elseif type(helpinfo)=="table" then
+ for i=1,select("#",...) do
+ reportlines(t,t.helpinfo[select(i,...)])
+ if i %s => %s => %s\r"](os.date("%d/%m/%y %H:%m:%S"),process,jobname,category,format(...))
+ for i=1,10 do
+ local f=io.open(whereto,"a")
+ if f then
+ f:write(message)
+ f:close()
+ break
else
- local f = io.open(name,"ab")
- if f then
- f:close()
- os.remove(name)
- return true
- end
+ sleep(0.1)
end
- return false
+ end
end
-
-function file.is_readable(name)
- local a = attributes(name)
- return a and sub(a.permissions,1,1) == "r"
+local report_system=logs.reporter("system","logs")
+function logs.obsolete(old,new)
+ local o=loadstring("return "..new)()
+ if type(o)=="function" then
+ return function(...)
+ report_system("function %a is obsolete, use %a",old,new)
+ loadstring(old.."="..new.." return "..old)()(...)
+ end
+ elseif type(o)=="table" then
+ local t,m={},{}
+ m.__index=function(t,k)
+ report_system("table %a is obsolete, use %a",old,new)
+ m.__index,m.__newindex=o,o
+ return o[k]
+ end
+ m.__newindex=function(t,k,v)
+ report_system("table %a is obsolete, use %a",old,new)
+ m.__index,m.__newindex=o,o
+ o[k]=v
+ end
+ if libraries then
+ libraries.obsolete[old]=t
+ end
+ setmetatable(t,m)
+ return t
+ end
end
-
-file.isreadable = file.is_readable -- depricated
-file.iswritable = file.is_writable -- depricated
-
--- todo: lpeg \\ / .. does not save much
-
-local checkedsplit = string.checkedsplit
-
-function file.splitpath(str,separator) -- string
- str = gsub(str,"\\","/")
- return checkedsplit(str,separator or io.pathseparator)
+if utilities then
+ utilities.report=report_system
end
-
-function file.joinpath(tab,separator) -- table
- return concat(tab,separator or io.pathseparator) -- can have trailing //
+if tex and tex.error then
+ function logs.texerrormessage(...)
+ tex.error(format(...),{})
+ end
+else
+ function logs.texerrormessage(...)
+ print(format(...))
+ end
end
+io.stdout:setvbuf('no')
+io.stderr:setvbuf('no')
--- we can hash them weakly
+end -- of closure
-function file.collapsepath(str,anchor)
- if anchor and not find(str,"^/") and not find(str,"^%a:") then
- str = getcurrentdir() .. "/" .. str
- end
- if str == "" or str =="." then
- return "."
- elseif find(str,"^%.%.") then
- str = gsub(str,"\\","/")
- return str
- elseif not find(str,"%.") then
- str = gsub(str,"\\","/")
- return str
- end
- str = gsub(str,"\\","/")
- local starter, rest = match(str,"^(%a+:/*)(.-)$")
- if starter then
- str = rest
- end
- local oldelements = checkedsplit(str,"/")
- local newelements = { }
- local i = #oldelements
- while i > 0 do
- local element = oldelements[i]
- if element == '.' then
- -- do nothing
- elseif element == '..' then
- local n = i - 1
- while n > 0 do
- local element = oldelements[n]
- if element ~= '..' and element ~= '.' then
- oldelements[n] = '.'
- break
- else
- n = n - 1
- end
- end
- if n < 1 then
- insert(newelements,1,'..')
- end
- elseif element ~= "" then
- insert(newelements,1,element)
- end
- i = i - 1
- end
- if #newelements == 0 then
- return starter or "."
- elseif starter then
- return starter .. concat(newelements, '/')
- elseif find(str,"^/") then
- return "/" .. concat(newelements,'/')
- else
- return concat(newelements, '/')
- end
-end
+do -- create closure to overcome 200 locals limit
+package.loaded["trac-inf"] = package.loaded["trac-inf"] or true
-function file.robustname(str,strict)
- str = gsub(str,"[^%a%d%/%-%.\\]+","-")
- if strict then
- return lower(gsub(str,"^%-*(.-)%-*$","%1"))
- else
- return str
+-- original size: 5791, stripped down to: 4540
+
+if not modules then modules={} end modules ['trac-inf']={
+ version=1.001,
+ comment="companion to trac-inf.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local type,tonumber=type,tonumber
+local format,lower=string.format,string.lower
+local concat=table.concat
+local clock=os.gettimeofday or os.clock
+statistics=statistics or {}
+local statistics=statistics
+statistics.enable=true
+statistics.threshold=0.01
+local statusinfo,n,registered,timers={},0,{},{}
+table.setmetatableindex(timers,function(t,k)
+ local v={ timing=0,loadtime=0 }
+ t[k]=v
+ return v
+end)
+local function hastiming(instance)
+ return instance and timers[instance]
+end
+local function resettiming(instance)
+ timers[instance or "notimer"]={ timing=0,loadtime=0 }
+end
+local function starttiming(instance)
+ local timer=timers[instance or "notimer"]
+ local it=timer.timing or 0
+ if it==0 then
+ timer.starttime=clock()
+ if not timer.loadtime then
+ timer.loadtime=0
+ end
+ end
+ timer.timing=it+1
+end
+local function stoptiming(instance,report)
+ local timer=timers[instance or "notimer"]
+ local it=timer.timing
+ if it>1 then
+ timer.timing=it-1
+ else
+ local starttime=timer.starttime
+ if starttime then
+ local stoptime=clock()
+ local loadtime=stoptime-starttime
+ timer.stoptime=stoptime
+ timer.loadtime=timer.loadtime+loadtime
+ if report then
+ statistics.report("load time %0.3f",loadtime)
+ end
+ timer.timing=0
+ return loadtime
+ end
+ end
+ return 0
+end
+local function elapsed(instance)
+ if type(instance)=="number" then
+ return instance or 0
+ else
+ local timer=timers[instance or "notimer"]
+ return timer and timer.loadtime or 0
+ end
+end
+local function elapsedtime(instance)
+ return format("%0.3f",elapsed(instance))
+end
+local function elapsedindeed(instance)
+ return elapsed(instance)>statistics.threshold
+end
+local function elapsedseconds(instance,rest)
+ if elapsedindeed(instance) then
+ return format("%0.3f seconds %s",elapsed(instance),rest or "")
+ end
+end
+statistics.hastiming=hastiming
+statistics.resettiming=resettiming
+statistics.starttiming=starttiming
+statistics.stoptiming=stoptiming
+statistics.elapsed=elapsed
+statistics.elapsedtime=elapsedtime
+statistics.elapsedindeed=elapsedindeed
+statistics.elapsedseconds=elapsedseconds
+function statistics.register(tag,fnc)
+ if statistics.enable and type(fnc)=="function" then
+ local rt=registered[tag] or (#statusinfo+1)
+ statusinfo[rt]={ tag,fnc }
+ registered[tag]=rt
+ if #tag>n then n=#tag end
+ end
+end
+local report=logs.reporter("mkiv lua stats")
+function statistics.show()
+ if statistics.enable then
+ local register=statistics.register
+ register("luatex banner",function()
+ return lower(status.banner)
+ end)
+ register("control sequences",function()
+ return format("%s of %s + %s",status.cs_count,status.hash_size,status.hash_extra)
+ end)
+ register("callbacks",function()
+ local total,indirect=status.callbacks or 0,status.indirect_callbacks or 0
+ return format("%s direct, %s indirect, %s total",total-indirect,indirect,total)
+ end)
+ if jit then
+ local status={ jit.status() }
+ if status[1] then
+ register("luajit status",function()
+ return concat(status," ",2)
+ end)
+ end
+ end
+ register("current memory usage",statistics.memused)
+ register("runtime",statistics.runtime)
+ logs.newline()
+ for i=1,#statusinfo do
+ local s=statusinfo[i]
+ local r=s[2]()
+ if r then
+ report("%s: %s",s[1],r)
+ end
end
+ statistics.enable=false
+ end
end
-
-file.readdata = io.loaddata
-file.savedata = io.savedata
-
-function file.copy(oldname,newname)
- file.savedata(newname,io.loaddata(oldname))
+function statistics.memused()
+ local round=math.round or math.floor
+ return format("%s MB (ctx: %s MB)",round(collectgarbage("count")/1000),round(status.luastate_bytes/1000000))
+end
+starttiming(statistics)
+function statistics.formatruntime(runtime)
+ return format("%s seconds",runtime)
+end
+function statistics.runtime()
+ stoptiming(statistics)
+ return statistics.formatruntime(elapsedtime(statistics))
+end
+local report=logs.reporter("system")
+function statistics.timed(action)
+ starttiming("run")
+ action()
+ stoptiming("run")
+ report("total runtime: %s",elapsedtime("run"))
+end
+commands=commands or {}
+function commands.resettimer(name)
+ resettiming(name or "whatever")
+ starttiming(name or "whatever")
+end
+function commands.elapsedtime(name)
+ stoptiming(name or "whatever")
+ context(elapsedtime(name or "whatever"))
end
-
--- lpeg variants, slightly faster, not always
+end -- of closure
+do -- create closure to overcome 200 locals limit
+package.loaded["trac-pro"] = package.loaded["trac-pro"] or true
+-- original size: 5773, stripped down to: 3453
+if not modules then modules={} end modules ['trac-pro']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local getmetatable,setmetatable,rawset,type=getmetatable,setmetatable,rawset,type
+local trace_namespaces=false trackers.register("system.namespaces",function(v) trace_namespaces=v end)
+local report_system=logs.reporter("system","protection")
+namespaces=namespaces or {}
+local namespaces=namespaces
+local registered={}
+local function report_index(k,name)
+ if trace_namespaces then
+ report_system("reference to %a in protected namespace %a: %s",k,name,debug.traceback())
+ else
+ report_system("reference to %a in protected namespace %a",k,name)
+ end
+end
+local function report_newindex(k,name)
+ if trace_namespaces then
+ report_system("assignment to %a in protected namespace %a: %s",k,name,debug.traceback())
+ else
+ report_system("assignment to %a in protected namespace %a",k,name)
+ end
+end
+local function register(name)
+ local data=name=="global" and _G or _G[name]
+ if not data then
+ return
+ end
+ registered[name]=data
+ local m=getmetatable(data)
+ if not m then
+ m={}
+ setmetatable(data,m)
+ end
+ local index,newindex={},{}
+ m.__saved__index=m.__index
+ m.__no__index=function(t,k)
+ if not index[k] then
+ index[k]=true
+ report_index(k,name)
+ end
+ return nil
+ end
+ m.__saved__newindex=m.__newindex
+ m.__no__newindex=function(t,k,v)
+ if not newindex[k] then
+ newindex[k]=true
+ report_newindex(k,name)
+ end
+ rawset(t,k,v)
+ end
+ m.__protection__depth=0
+end
+local function private(name)
+ local data=registered[name]
+ if not data then
+ data=_G[name]
+ if not data then
+ data={}
+ _G[name]=data
+ end
+ register(name)
+ end
+ return data
+end
+local function protect(name)
+ local data=registered[name]
+ if not data then
+ return
+ end
+ local m=getmetatable(data)
+ local pd=m.__protection__depth
+ if pd>0 then
+ m.__protection__depth=pd+1
+ else
+ m.__save_d_index,m.__saved__newindex=m.__index,m.__newindex
+ m.__index,m.__newindex=m.__no__index,m.__no__newindex
+ m.__protection__depth=1
+ end
+end
+local function unprotect(name)
+ local data=registered[name]
+ if not data then
+ return
+ end
+ local m=getmetatable(data)
+ local pd=m.__protection__depth
+ if pd>1 then
+ m.__protection__depth=pd-1
+ else
+ m.__index,m.__newindex=m.__saved__index,m.__saved__newindex
+ m.__protection__depth=0
+ end
+end
+local function protectall()
+ for name,_ in next,registered do
+ if name~="global" then
+ protect(name)
+ end
+ end
+end
+local function unprotectall()
+ for name,_ in next,registered do
+ if name~="global" then
+ unprotect(name)
+ end
+ end
+end
+namespaces.register=register
+namespaces.private=private
+namespaces.protect=protect
+namespaces.unprotect=unprotect
+namespaces.protectall=protectall
+namespaces.unprotectall=unprotectall
+namespaces.private("namespaces") registered={} register("global")
+directives.register("system.protect",function(v)
+ if v then
+ protectall()
+ else
+ unprotectall()
+ end
+end)
+directives.register("system.checkglobals",function(v)
+ if v then
+ report_system("enabling global namespace guard")
+ protect("global")
+ else
+ report_system("disabling global namespace guard")
+ unprotect("global")
+ end
+end)
+end -- of closure
+do -- create closure to overcome 200 locals limit
+package.loaded["util-lua"] = package.loaded["util-lua"] or true
+-- original size: 12575, stripped down to: 8700
-
-
-
-
-
-
-
--- also rewrite previous
-
-local letter = R("az","AZ") + S("_-+")
-local separator = P("://")
-
-local qualified = P(".")^0 * P("/") + letter*P(":") + letter^1*separator + letter^1 * P("/")
-local rootbased = P("/") + letter*P(":")
-
-lpeg.patterns.qualified = qualified
-lpeg.patterns.rootbased = rootbased
-
--- ./name ../name /name c: :// name/name
-
-function file.is_qualified_path(filename)
- return lpegmatch(qualified,filename) ~= nil
+if not modules then modules={} end modules ['util-lua']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ comment="the strip code is written by Peter Cawley",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local rep,sub,byte,dump,format=string.rep,string.sub,string.byte,string.dump,string.format
+local load,loadfile,type=load,loadfile,type
+utilities=utilities or {}
+utilities.lua=utilities.lua or {}
+local luautilities=utilities.lua
+local report_lua=logs.reporter("system","lua")
+local tracestripping=false
+local forcestupidcompile=true
+luautilities.stripcode=true
+luautilities.alwaysstripcode=false
+luautilities.nofstrippedchunks=0
+luautilities.nofstrippedbytes=0
+local strippedchunks={}
+luautilities.strippedchunks=strippedchunks
+luautilities.suffixes={
+ tma="tma",
+ tmc=jit and "tmb" or "tmc",
+ lua="lua",
+ luc=jit and "lub" or "luc",
+ lui="lui",
+ luv="luv",
+ luj="luj",
+ tua="tua",
+ tuc="tuc",
+}
+if jit or status.luatex_version>=74 then
+ local function register(name)
+ if tracestripping then
+ report_lua("stripped bytecode from %a",name or "unknown")
+ end
+ strippedchunks[#strippedchunks+1]=name
+ luautilities.nofstrippedchunks=luautilities.nofstrippedchunks+1
+ end
+ local function stupidcompile(luafile,lucfile,strip)
+ local code=io.loaddata(luafile)
+ if code and code~="" then
+ code=load(code)
+ if code then
+ code=dump(code,strip and luautilities.stripcode or luautilities.alwaysstripcode)
+ if code and code~="" then
+ register(name)
+ io.savedata(lucfile,code)
+ return true,0
+ end
+ else
+ report_lua("fatal error %a in file %a",1,luafile)
+ end
+ else
+ report_lua("fatal error %a in file %a",2,luafile)
+ end
+ return false,0
+ end
+ function luautilities.loadedluacode(fullname,forcestrip,name)
+ name=name or fullname
+ local code=environment.loadpreprocessedfile and environment.loadpreprocessedfile(fullname) or loadfile(fullname)
+ if code then
+ code()
+ end
+ if forcestrip and luautilities.stripcode then
+ if type(forcestrip)=="function" then
+ forcestrip=forcestrip(fullname)
+ end
+ if forcestrip or luautilities.alwaysstripcode then
+ register(name)
+ return load(dump(code,true)),0
+ else
+ return code,0
+ end
+ elseif luautilities.alwaysstripcode then
+ register(name)
+ return load(dump(code,true)),0
+ else
+ return code,0
+ end
+ end
+ function luautilities.strippedloadstring(code,forcestrip,name)
+ if forcestrip and luautilities.stripcode or luautilities.alwaysstripcode then
+ code=load(code)
+ if not code then
+ report_lua("fatal error %a in file %a",3,name)
+ end
+ register(name)
+ code=dump(code,true)
+ end
+ return load(code),0
+ end
+ function luautilities.compile(luafile,lucfile,cleanup,strip,fallback)
+ report_lua("compiling %a into %a",luafile,lucfile)
+ os.remove(lucfile)
+ local done=stupidcompile(luafile,lucfile,strip~=false)
+ if done then
+ report_lua("dumping %a into %a stripped",luafile,lucfile)
+ if cleanup==true and lfs.isfile(lucfile) and lfs.isfile(luafile) then
+ report_lua("removing %a",luafile)
+ os.remove(luafile)
+ end
+ end
+ return done
+ end
+ function luautilities.loadstripped(...)
+ local l=load(...)
+ if l then
+ return load(dump(l,true))
+ end
+ end
+else
+ local function register(name,before,after)
+ local delta=before-after
+ if tracestripping then
+ report_lua("bytecodes stripped from %a, # before %s, # after %s, delta %s",name,before,after,delta)
+ end
+ strippedchunks[#strippedchunks+1]=name
+ luautilities.nofstrippedchunks=luautilities.nofstrippedchunks+1
+ luautilities.nofstrippedbytes=luautilities.nofstrippedbytes+delta
+ return delta
+ end
+ local strip_code_pc
+ if _MAJORVERSION==5 and _MINORVERSION==1 then
+ strip_code_pc=function(dump,name)
+ local before=#dump
+ local version,format,endian,int,size,ins,num=byte(dump,5,11)
+ local subint
+ if endian==1 then
+ subint=function(dump,i,l)
+ local val=0
+ for n=l,1,-1 do
+ val=val*256+byte(dump,i+n-1)
+ end
+ return val,i+l
+ end
+ else
+ subint=function(dump,i,l)
+ local val=0
+ for n=1,l,1 do
+ val=val*256+byte(dump,i+n-1)
+ end
+ return val,i+l
+ end
+ end
+ local strip_function
+ strip_function=function(dump)
+ local count,offset=subint(dump,1,size)
+ local stripped,dirty=rep("\0",size),offset+count
+ offset=offset+count+int*2+4
+ offset=offset+int+subint(dump,offset,int)*ins
+ count,offset=subint(dump,offset,int)
+ for n=1,count do
+ local t
+ t,offset=subint(dump,offset,1)
+ if t==1 then
+ offset=offset+1
+ elseif t==4 then
+ offset=offset+size+subint(dump,offset,size)
+ elseif t==3 then
+ offset=offset+num
+ end
+ end
+ count,offset=subint(dump,offset,int)
+ stripped=stripped..sub(dump,dirty,offset-1)
+ for n=1,count do
+ local proto,off=strip_function(sub(dump,offset,-1))
+ stripped,offset=stripped..proto,offset+off-1
+ end
+ offset=offset+subint(dump,offset,int)*int+int
+ count,offset=subint(dump,offset,int)
+ for n=1,count do
+ offset=offset+subint(dump,offset,size)+size+int*2
+ end
+ count,offset=subint(dump,offset,int)
+ for n=1,count do
+ offset=offset+subint(dump,offset,size)+size
+ end
+ stripped=stripped..rep("\0",int*3)
+ return stripped,offset
+ end
+ dump=sub(dump,1,12)..strip_function(sub(dump,13,-1))
+ local after=#dump
+ local delta=register(name,before,after)
+ return dump,delta
+ end
+ else
+ strip_code_pc=function(dump,name)
+ return dump,0
+ end
+ end
+ function luautilities.loadedluacode(fullname,forcestrip,name)
+ local code=environment.loadpreprocessedfile and environment.preprocessedloadfile(fullname) or loadfile(fullname)
+ if code then
+ code()
+ end
+ if forcestrip and luautilities.stripcode then
+ if type(forcestrip)=="function" then
+ forcestrip=forcestrip(fullname)
+ end
+ if forcestrip then
+ local code,n=strip_code_pc(dump(code),name)
+ return load(code),n
+ elseif luautilities.alwaysstripcode then
+ return load(strip_code_pc(dump(code),name))
+ else
+ return code,0
+ end
+ elseif luautilities.alwaysstripcode then
+ return load(strip_code_pc(dump(code),name))
+ else
+ return code,0
+ end
+ end
+ function luautilities.strippedloadstring(code,forcestrip,name)
+ local n=0
+ if (forcestrip and luautilities.stripcode) or luautilities.alwaysstripcode then
+ code=load(code)
+ if not code then
+ report_lua("fatal error in file %a",name)
+ end
+ code,n=strip_code_pc(dump(code),name)
+ end
+ return load(code),n
+ end
+ local function stupidcompile(luafile,lucfile,strip)
+ local code=io.loaddata(luafile)
+ local n=0
+ if code and code~="" then
+ code=load(code)
+ if not code then
+ report_lua("fatal error in file %a",luafile)
+ end
+ code=dump(code)
+ if strip then
+ code,n=strip_code_pc(code,luautilities.stripcode or luautilities.alwaysstripcode,luafile)
+ end
+ if code and code~="" then
+ io.savedata(lucfile,code)
+ end
+ end
+ return n
+ end
+ local luac_normal="texluac -o %q %q"
+ local luac_strip="texluac -s -o %q %q"
+ function luautilities.compile(luafile,lucfile,cleanup,strip,fallback)
+ report_lua("compiling %a into %a",luafile,lucfile)
+ os.remove(lucfile)
+ local done=false
+ if strip~=false then
+ strip=true
+ end
+ if forcestupidcompile then
+ fallback=true
+ elseif strip then
+ done=os.spawn(format(luac_strip,lucfile,luafile))==0
+ else
+ done=os.spawn(format(luac_normal,lucfile,luafile))==0
+ end
+ if not done and fallback then
+ local n=stupidcompile(luafile,lucfile,strip)
+ if n>0 then
+ report_lua("%a dumped into %a (%i bytes stripped)",luafile,lucfile,n)
+ else
+ report_lua("%a dumped into %a (unstripped)",luafile,lucfile)
+ end
+ cleanup=false
+ done=true
+ end
+ if done and cleanup==true and lfs.isfile(lucfile) and lfs.isfile(luafile) then
+ report_lua("removing %a",luafile)
+ os.remove(luafile)
+ end
+ return done
+ end
+ luautilities.loadstripped=loadstring
end
-function file.is_rootbased_path(filename)
- return lpegmatch(rootbased,filename) ~= nil
-end
--- actually these are schemes
+end -- of closure
-local slash = S("\\/")
-local period = P(".")
-local drive = C(R("az","AZ")) * P(":")
-local path = C(((1-slash)^0 * slash)^0)
-local suffix = period * C(P(1-period)^0 * P(-1))
-local base = C((1-suffix)^0)
+do -- create closure to overcome 200 locals limit
-drive = drive + Cc("")
-path = path + Cc("")
-base = base + Cc("")
-suffix = suffix + Cc("")
+package.loaded["util-deb"] = package.loaded["util-deb"] or true
-local pattern_a = drive * path * base * suffix
-local pattern_b = path * base * suffix
-local pattern_c = C(drive * path) * C(base * suffix)
+-- original size: 3708, stripped down to: 2568
-function file.splitname(str,splitdrive)
- if splitdrive then
- return lpegmatch(pattern_a,str) -- returns drive, path, base, suffix
+if not modules then modules={} end modules ['util-deb']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local debug=require "debug"
+local getinfo=debug.getinfo
+local type,next,tostring=type,next,tostring
+local format,find=string.format,string.find
+local is_boolean=string.is_boolean
+utilities=utilities or {}
+local debugger=utilities.debugger or {}
+utilities.debugger=debugger
+local counters={}
+local names={}
+local report=logs.reporter("debugger")
+local function hook()
+ local f=getinfo(2)
+ if f then
+ local n="unknown"
+ if f.what=="C" then
+ n=f.name or ''
+ if not names[n] then
+ names[n]=format("%42s",n)
+ end
else
- return lpegmatch(pattern_b,str) -- returns path, base, suffix
- end
+ n=f.name or f.namewhat or f.what
+ if not n or n=="" then
+ n="?"
+ end
+ if not names[n] then
+ names[n]=format("%42s : % 5i : %s",n,f.linedefined or 0,f.short_src or "unknown source")
+ end
+ end
+ counters[n]=(counters[n] or 0)+1
+ end
+end
+function debugger.showstats(printer,threshold)
+ printer=printer or report
+ threshold=threshold or 0
+ local total,grandtotal,functions=0,0,0
+ local dataset={}
+ for name,count in next,counters do
+ dataset[#dataset+1]={ name,count }
+ end
+ table.sort(dataset,function(a,b) return a[2]==b[2] and b[1]>a[1] or a[2]>b[2] end)
+ for i=1,#dataset do
+ local d=dataset[i]
+ local name=d[1]
+ local count=d[2]
+ if count>threshold and not find(name,"for generator") then
+ printer(format("%8i %s\n",count,names[name]))
+ total=total+count
+ end
+ grandtotal=grandtotal+count
+ functions=functions+1
+ end
+ printer("\n")
+ printer(format("functions : % 10i\n",functions))
+ printer(format("total : % 10i\n",total))
+ printer(format("grand total: % 10i\n",grandtotal))
+ printer(format("threshold : % 10i\n",threshold))
end
-
-function file.nametotable(str,splitdrive) -- returns table
- local path, drive, subpath, name, base, suffix = lpegmatch(pattern_c,str)
- if splitdrive then
- return {
- path = path,
- drive = drive,
- subpath = subpath,
- name = name,
- base = base,
- suffix = suffix,
- }
+function debugger.savestats(filename,threshold)
+ local f=io.open(filename,'w')
+ if f then
+ debugger.showstats(function(str) f:write(str) end,threshold)
+ f:close()
+ end
+end
+function debugger.enable()
+ debug.sethook(hook,"c")
+end
+function debugger.disable()
+ debug.sethook()
+end
+function traceback()
+ local level=1
+ while true do
+ local info=debug.getinfo(level,"Sl")
+ if not info then
+ break
+ elseif info.what=="C" then
+ print(format("%3i : C function",level))
else
- return {
- path = path,
- name = name,
- base = base,
- suffix = suffix,
- }
+ print(format("%3i : [%s]:%d",level,info.short_src,info.currentline))
end
-end
-
--- function test(t) for k, v in next, t do print(v, "=>", file.splitname(v)) end end
---
--- test { "c:", "c:/aa", "c:/aa/bb", "c:/aa/bb/cc", "c:/aa/bb/cc.dd", "c:/aa/bb/cc.dd.ee" }
--- test { "c:", "c:aa", "c:aa/bb", "c:aa/bb/cc", "c:aa/bb/cc.dd", "c:aa/bb/cc.dd.ee" }
--- test { "/aa", "/aa/bb", "/aa/bb/cc", "/aa/bb/cc.dd", "/aa/bb/cc.dd.ee" }
--- test { "aa", "aa/bb", "aa/bb/cc", "aa/bb/cc.dd", "aa/bb/cc.dd.ee" }
-
-
--- for myself:
-
-function file.strip(name,dir)
- local b, a = match(name,"^(.-)" .. dir .. "(.*)$")
- return a ~= "" and a or name
+ level=level+1
+ end
end
@@ -3060,64 +7388,292 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-md5'] = {
- version = 1.001,
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
+package.loaded["util-mrg"] = package.loaded["util-mrg"] or true
+
+-- original size: 7294, stripped down to: 5798
+
+if not modules then modules={} end modules ['util-mrg']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
}
+local gsub,format=string.gsub,string.format
+local concat=table.concat
+local type,next=type,next
+local P,R,S,V,Ct,C,Cs,Cc,Cp,Cmt,Cb,Cg=lpeg.P,lpeg.R,lpeg.S,lpeg.V,lpeg.Ct,lpeg.C,lpeg.Cs,lpeg.Cc,lpeg.Cp,lpeg.Cmt,lpeg.Cb,lpeg.Cg
+local lpegmatch,patterns=lpeg.match,lpeg.patterns
+utilities=utilities or {}
+local merger=utilities.merger or {}
+utilities.merger=merger
+merger.strip_comment=true
+local report=logs.reporter("system","merge")
+utilities.report=report
+local m_begin_merge="begin library merge"
+local m_end_merge="end library merge"
+local m_begin_closure="do -- create closure to overcome 200 locals limit"
+local m_end_closure="end -- of closure"
+local m_pattern="%c+".."%-%-%s+"..m_begin_merge.."%c+(.-)%c+".."%-%-%s+"..m_end_merge.."%c+"
+local m_format="\n\n-- "..m_begin_merge.."\n%s\n".."-- "..m_end_merge.."\n\n"
+local m_faked="-- ".."created merged file".."\n\n".."-- "..m_begin_merge.."\n\n".."-- "..m_end_merge.."\n\n"
+local m_report=[[
+-- used libraries : %s
+-- skipped libraries : %s
+-- original bytes : %s
+-- stripped bytes : %s
+]]
+local m_preloaded=[[package.loaded[%q] = package.loaded[%q] or true]]
+local function self_fake()
+ return m_faked
+end
+local function self_nothing()
+ return ""
+end
+local function self_load(name)
+ local data=io.loaddata(name) or ""
+ if data=="" then
+ report("unknown file %a",name)
+ else
+ report("inserting file %a",name)
+ end
+ return data or ""
+end
+local space=patterns.space
+local eol=patterns.newline
+local equals=P("=")^0
+local open=P("[")*Cg(equals,"init")*P("[")*P("\n")^-1
+local close=P("]")*C(equals)*P("]")
+local closeeq=Cmt(close*Cb("init"),function(s,i,a,b) return a==b end)
+local longstring=open*(1-closeeq)^0*close
+local quoted=patterns.quoted
+local emptyline=space^0*eol
+local operator1=P("<=")+P(">=")+P("~=")+P("..")+S("/^<>=*+%%")
+local operator2=S("*+/")
+local operator3=S("-")
+local separator=S(",;")
+local ignore=(P("]")*space^1*P("=")*space^1*P("]"))/"]=["+(P("=")*space^1*P("{"))/"={"+(P("(")*space^1)/"("+(P("{")*(space+eol)^1*P("}"))/"{}"
+local strings=quoted
+local longcmt=(emptyline^0*P("--")*longstring*emptyline^0)/""
+local longstr=longstring
+local comment=emptyline^0*P("--")*P("-")^0*(1-eol)^0*emptyline^1/"\n"
+local pack=((eol+space)^0/"")*operator1*((eol+space)^0/"")+((eol+space)^0/"")*operator2*((space)^0/"")+((eol+space)^1/"")*operator3*((space)^1/"")+((space)^0/"")*separator*((space)^0/"")
+local lines=emptyline^2/"\n"
+local spaces=(space*space)/" "
+local compact=Cs ((
+ ignore+strings+longcmt+longstr+comment+pack+lines+spaces+1
+)^1 )
+local strip=Cs((emptyline^2/"\n"+1)^0)
+local stripreturn=Cs((1-P("return")*space^1*P(1-space-eol)^1*(space+eol)^0*P(-1))^1)
+function merger.compact(data)
+ return lpegmatch(strip,lpegmatch(compact,data))
+end
+local function self_compact(data)
+ local delta=0
+ if merger.strip_comment then
+ local before=#data
+ data=lpegmatch(compact,data)
+ data=lpegmatch(strip,data)
+ local after=#data
+ delta=before-after
+ report("original size %s, compacted to %s, stripped %s",before,after,delta)
+ data=format("-- original size: %s, stripped down to: %s\n\n%s",before,after,data)
+ end
+ return lpegmatch(stripreturn,data) or data,delta
+end
+local function self_save(name,data)
+ if data~="" then
+ io.savedata(name,data)
+ report("saving %s with size %s",name,#data)
+ end
+end
+local function self_swap(data,code)
+ return data~="" and (gsub(data,m_pattern,function() return format(m_format,code) end,1)) or ""
+end
+local function self_libs(libs,list)
+ local result,f,frozen,foundpath={},nil,false,nil
+ result[#result+1]="\n"
+ if type(libs)=='string' then libs={ libs } end
+ if type(list)=='string' then list={ list } end
+ for i=1,#libs do
+ local lib=libs[i]
+ for j=1,#list do
+ local pth=gsub(list[j],"\\","/")
+ report("checking library path %a",pth)
+ local name=pth.."/"..lib
+ if lfs.isfile(name) then
+ foundpath=pth
+ end
+ end
+ if foundpath then break end
+ end
+ if foundpath then
+ report("using library path %a",foundpath)
+ local right,wrong,original,stripped={},{},0,0
+ for i=1,#libs do
+ local lib=libs[i]
+ local fullname=foundpath.."/"..lib
+ if lfs.isfile(fullname) then
+ report("using library %a",fullname)
+ local preloaded=file.nameonly(lib)
+ local data=io.loaddata(fullname,true)
+ original=original+#data
+ local data,delta=self_compact(data)
+ right[#right+1]=lib
+ result[#result+1]=m_begin_closure
+ result[#result+1]=format(m_preloaded,preloaded,preloaded)
+ result[#result+1]=data
+ result[#result+1]=m_end_closure
+ stripped=stripped+delta
+ else
+ report("skipping library %a",fullname)
+ wrong[#wrong+1]=lib
+ end
+ end
+ right=#right>0 and concat(right," ") or "-"
+ wrong=#wrong>0 and concat(wrong," ") or "-"
+ report("used libraries: %a",right)
+ report("skipped libraries: %a",wrong)
+ report("original bytes: %a",original)
+ report("stripped bytes: %a",stripped)
+ result[#result+1]=format(m_report,right,wrong,original,stripped)
+ else
+ report("no valid library path found")
+ end
+ return concat(result,"\n\n")
+end
+function merger.selfcreate(libs,list,target)
+ if target then
+ self_save(target,self_swap(self_fake(),self_libs(libs,list)))
+ end
+end
+function merger.selfmerge(name,libs,list,target)
+ self_save(target or name,self_swap(self_load(name),self_libs(libs,list)))
+end
+function merger.selfclean(name)
+ self_save(name,self_swap(self_load(name),self_nothing()))
+end
--- This also provides file checksums and checkers.
-local md5, file = md5, file
-local gsub, format, byte = string.gsub, string.format, string.byte
+end -- of closure
-local function convert(str,fmt)
- return (gsub(md5.sum(str),".",function(chr) return format(fmt,byte(chr)) end))
-end
+do -- create closure to overcome 200 locals limit
-if not md5.HEX then function md5.HEX(str) return convert(str,"%02X") end end
-if not md5.hex then function md5.hex(str) return convert(str,"%02x") end end
-if not md5.dec then function md5.dec(str) return convert(str,"%03i") end end
+package.loaded["util-tpl"] = package.loaded["util-tpl"] or true
+-- original size: 5655, stripped down to: 3242
-function file.needs_updating(oldname,newname,threshold) -- size modification access change
- local oldtime = lfs.attributes(oldname, modification)
- local newtime = lfs.attributes(newname, modification)
- if newtime >= oldtime then
- return false
- elseif oldtime - newtime < (threshold or 1) then
- return false
- else
- return true
+if not modules then modules={} end modules ['util-tpl']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+utilities.templates=utilities.templates or {}
+local templates=utilities.templates
+local trace_template=false trackers.register("templates.trace",function(v) trace_template=v end)
+local report_template=logs.reporter("template")
+local tostring=tostring
+local format,sub=string.format,string.sub
+local P,C,Cs,Carg,lpegmatch=lpeg.P,lpeg.C,lpeg.Cs,lpeg.Carg,lpeg.match
+local replacer
+local function replacekey(k,t,how,recursive)
+ local v=t[k]
+ if not v then
+ if trace_template then
+ report_template("unknown key %a",k)
end
-end
-
-function file.checksum(name)
- if md5 then
- local data = io.loaddata(name)
- if data then
- return md5.HEX(data)
- end
+ return ""
+ else
+ v=tostring(v)
+ if trace_template then
+ report_template("setting key %a to value %a",k,v)
end
- return nil
-end
-
-function file.loadchecksum(name)
- if md5 then
- local data = io.loaddata(name .. ".md5")
- return data and (gsub(data,"%s",""))
+ if recursive then
+ return lpegmatch(replacer,v,1,t,how,recursive)
+ else
+ return v
end
- return nil
+ end
end
-
-function file.savechecksum(name, checksum)
- if not checksum then checksum = file.checksum(name) end
- if checksum then
- io.savedata(name .. ".md5",checksum)
- return checksum
- end
- return nil
+local sqlescape=lpeg.replacer {
+ { "'","''" },
+ { "\\","\\\\" },
+ { "\r\n","\\n" },
+ { "\r","\\n" },
+}
+local sqlquotedescape=lpeg.Cs(lpeg.Cc("'")*sqlescape*lpeg.Cc("'"))
+local escapers={
+ lua=function(s)
+ return sub(format("%q",s),2,-2)
+ end,
+ sql=function(s)
+ return lpegmatch(sqlescape,s)
+ end,
+}
+local quotedescapers={
+ lua=function(s)
+ return format("%q",s)
+ end,
+ sql=function(s)
+ return lpegmatch(sqlquotedescape,s)
+ end,
+}
+lpeg.patterns.sqlescape=sqlescape
+lpeg.patterns.sqlescape=sqlquotedescape
+local luaescaper=escapers.lua
+local quotedluaescaper=quotedescapers.lua
+local function replacekeyunquoted(s,t,how,recurse)
+ local escaper=how and escapers[how] or luaescaper
+ return escaper(replacekey(s,t,how,recurse))
+end
+local function replacekeyquoted(s,t,how,recurse)
+ local escaper=how and quotedescapers[how] or quotedluaescaper
+ return escaper(replacekey(s,t,how,recurse))
+end
+local single=P("%")
+local double=P("%%")
+local lquoted=P("%[")
+local rquoted=P("]%")
+local lquotedq=P("%(")
+local rquotedq=P(")%")
+local escape=double/'%%'
+local nosingle=single/''
+local nodouble=double/''
+local nolquoted=lquoted/''
+local norquoted=rquoted/''
+local nolquotedq=lquotedq/''
+local norquotedq=rquotedq/''
+local key=nosingle*((C((1-nosingle )^1)*Carg(1)*Carg(2)*Carg(3))/replacekey )*nosingle
+local quoted=nolquotedq*((C((1-norquotedq)^1)*Carg(1)*Carg(2)*Carg(3))/replacekeyquoted )*norquotedq
+local unquoted=nolquoted*((C((1-norquoted )^1)*Carg(1)*Carg(2)*Carg(3))/replacekeyunquoted)*norquoted
+local any=P(1)
+ replacer=Cs((unquoted+quoted+escape+key+any)^0)
+local function replace(str,mapping,how,recurse)
+ if mapping and str then
+ return lpegmatch(replacer,str,1,mapping,how or "lua",recurse or false) or str
+ else
+ return str
+ end
+end
+templates.replace=replace
+function templates.load(filename,mapping,how,recurse)
+ local data=io.loaddata(filename) or ""
+ if mapping and next(mapping) then
+ return replace(data,mapping,how,recurse)
+ else
+ return data
+ end
+end
+function templates.resolve(t,mapping,how,recurse)
+ if not mapping then
+ mapping=t
+ end
+ for k,v in next,t do
+ t[k]=replace(v,mapping,how,recurse)
+ end
+ return t
end
@@ -3125,1225 +7681,1316 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-url'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local char, gmatch, gsub, format, byte, find = string.char, string.gmatch, string.gsub, string.format, string.byte, string.find
-local concat = table.concat
-local tonumber, type = tonumber, type
-local P, C, R, S, Cs, Cc, Ct = lpeg.P, lpeg.C, lpeg.R, lpeg.S, lpeg.Cs, lpeg.Cc, lpeg.Ct
-local lpegmatch, lpegpatterns, replacer = lpeg.match, lpeg.patterns, lpeg.replacer
+package.loaded["util-env"] = package.loaded["util-env"] or true
--- from wikipedia:
---
--- foo://username:password@example.com:8042/over/there/index.dtb?type=animal;name=narwhal#nose
--- \_/ \_______________/ \_________/ \__/ \___/ \_/ \______________________/ \__/
--- | | | | | | | |
--- | userinfo hostname port | | query fragment
--- | \________________________________/\_____________|____|/
--- scheme | | | |
--- | authority path | |
--- | | |
--- | path interpretable as filename
--- | ___________|____________ |
--- / \ / \ |
--- urn:example:animal:ferret:nose interpretable as extension
-
-url = url or { }
-local url = url
-
-local tochar = function(s) return char(tonumber(s,16)) end
-
-local colon = P(":")
-local qmark = P("?")
-local hash = P("#")
-local slash = P("/")
-local percent = P("%")
-local endofstring = P(-1)
-
-local hexdigit = R("09","AF","af")
-local plus = P("+")
-local nothing = Cc("")
-local escaped = (plus / " ") + (percent * C(hexdigit * hexdigit) / tochar)
-
--- we assume schemes with more than 1 character (in order to avoid problems with windows disks)
--- we also assume that when we have a scheme, we also have an authority
-
-local schemestr = Cs((escaped+(1-colon-slash-qmark-hash))^2)
-local authoritystr = Cs((escaped+(1- slash-qmark-hash))^0)
-local pathstr = Cs((escaped+(1- qmark-hash))^0)
-local querystr = Cs((escaped+(1- hash))^0)
-local fragmentstr = Cs((escaped+(1- endofstring))^0)
-
-local scheme = schemestr * colon + nothing
-local authority = slash * slash * authoritystr + nothing
-local path = slash * pathstr + nothing
-local query = qmark * querystr + nothing
-local fragment = hash * fragmentstr + nothing
-
-local validurl = scheme * authority * path * query * fragment
-local parser = Ct(validurl)
-
-lpegpatterns.url = validurl
-lpegpatterns.urlsplitter = parser
-
-local escapes = { } ; for i=0,255 do escapes[i] = format("%%%02X",i) end
-
-local escaper = Cs((R("09","AZ","az") + S("-./_") + P(1) / escapes)^0)
-
-lpegpatterns.urlescaper = escaper
-
--- todo: reconsider Ct as we can as well have five return values (saves a table)
--- so we can have two parsers, one with and one without
+-- original size: 7702, stripped down to: 4701
-local function split(str)
- return (type(str) == "string" and lpegmatch(parser,str)) or str
+if not modules then modules={} end modules ['util-env']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local allocate,mark=utilities.storage.allocate,utilities.storage.mark
+local format,sub,match,gsub,find=string.format,string.sub,string.match,string.gsub,string.find
+local unquoted,quoted=string.unquoted,string.quoted
+local concat,insert,remove=table.concat,table.insert,table.remove
+environment=environment or {}
+local environment=environment
+os.setlocale(nil,nil)
+function os.setlocale()
end
-
-local isscheme = schemestr * colon * slash * slash -- this test also assumes authority
-
-local function hasscheme(str)
- local scheme = lpegmatch(isscheme,str) -- at least one character
- return scheme ~= "" and scheme or false
-end
-
-
--- todo: cache them
-
-local rootletter = R("az","AZ")
- + S("_-+")
-local separator = P("://")
-local qualified = P(".")^0 * P("/")
- + rootletter * P(":")
- + rootletter^1 * separator
- + rootletter^1 * P("/")
-local rootbased = P("/")
- + rootletter * P(":")
-
-local barswapper = replacer("|",":")
-local backslashswapper = replacer("\\","/")
-
-local function hashed(str) -- not yet ok (/test?test)
- local s = split(str)
- local somescheme = s[1] ~= ""
- local somequery = s[4] ~= ""
- if not somescheme and not somequery then
- s = {
- scheme = "file",
- authority = "",
- path = str,
- query = "",
- fragment = "",
- original = str,
- noscheme = true,
- filename = str,
- }
- else -- not always a filename but handy anyway
- local authority, path, filename = s[2], s[3]
- if authority == "" then
- filename = path
+local validengines=allocate {
+ ["luatex"]=true,
+ ["luajittex"]=true,
+}
+local basicengines=allocate {
+ ["luatex"]="luatex",
+ ["texlua"]="luatex",
+ ["texluac"]="luatex",
+ ["luajittex"]="luajittex",
+ ["texluajit"]="luajittex",
+}
+local luaengines=allocate {
+ ["lua"]=true,
+ ["luajit"]=true,
+}
+environment.validengines=validengines
+environment.basicengines=basicengines
+if not arg then
+elseif luaengines[file.removesuffix(arg[-1])] then
+elseif validengines[file.removesuffix(arg[0])] then
+ if arg[1]=="--luaonly" then
+ arg[-1]=arg[0]
+ arg[ 0]=arg[2]
+ for k=3,#arg do
+ arg[k-2]=arg[k]
+ end
+ remove(arg)
+ remove(arg)
+ else
+ end
+ local originalzero=file.basename(arg[0])
+ local specialmapping={ luatools=="base" }
+ if originalzero~="mtxrun" and originalzero~="mtxrun.lua" then
+ arg[0]=specialmapping[originalzero] or originalzero
+ insert(arg,0,"--script")
+ insert(arg,0,"mtxrun")
+ end
+end
+environment.arguments=allocate()
+environment.files=allocate()
+environment.sortedflags=nil
+function environment.initializearguments(arg)
+ local arguments,files={},{}
+ environment.arguments,environment.files,environment.sortedflags=arguments,files,nil
+ for index=1,#arg do
+ local argument=arg[index]
+ if index>0 then
+ local flag,value=match(argument,"^%-+(.-)=(.-)$")
+ if flag then
+ flag=gsub(flag,"^c:","")
+ arguments[flag]=unquoted(value or "")
+ else
+ flag=match(argument,"^%-+(.+)")
+ if flag then
+ flag=gsub(flag,"^c:","")
+ arguments[flag]=true
else
- filename = authority .. "/" .. path
+ files[#files+1]=argument
end
- s = {
- scheme = s[1],
- authority = authority,
- path = path,
- query = s[4],
- fragment = s[5],
- original = str,
- noscheme = false,
- filename = filename,
- }
+ end
end
- return s
+ end
+ environment.ownname=file.reslash(environment.ownname or arg[0] or 'unknown.lua')
end
-
--- Here we assume:
---
--- files: /// = relative
--- files: //// = absolute (!)
-
-
-
-url.split = split
-url.hasscheme = hasscheme
-url.hashed = hashed
-
-function url.addscheme(str,scheme) -- no authority
- if hasscheme(str) then
- return str
- elseif not scheme then
- return "file:///" .. str
+function environment.setargument(name,value)
+ environment.arguments[name]=value
+end
+function environment.getargument(name,partial)
+ local arguments,sortedflags=environment.arguments,environment.sortedflags
+ if arguments[name] then
+ return arguments[name]
+ elseif partial then
+ if not sortedflags then
+ sortedflags=allocate(table.sortedkeys(arguments))
+ for k=1,#sortedflags do
+ sortedflags[k]="^"..sortedflags[k]
+ end
+ environment.sortedflags=sortedflags
+ end
+ for k=1,#sortedflags do
+ local v=sortedflags[k]
+ if find(name,v) then
+ return arguments[sub(v,2,#v)]
+ end
+ end
+ end
+ return nil
+end
+environment.argument=environment.getargument
+function environment.splitarguments(separator)
+ local done,before,after=false,{},{}
+ local originalarguments=environment.originalarguments
+ for k=1,#originalarguments do
+ local v=originalarguments[k]
+ if not done and v==separator then
+ done=true
+ elseif done then
+ after[#after+1]=v
else
- return scheme .. ":///" .. str
- end
-end
-
-function url.construct(hash) -- dodo: we need to escape !
- local fullurl, f = { }, 0
- local scheme, authority, path, query, fragment = hash.scheme, hash.authority, hash.path, hash.query, hash.fragment
- if scheme and scheme ~= "" then
- f = f + 1 ; fullurl[f] = scheme .. "://"
- end
- if authority and authority ~= "" then
- f = f + 1 ; fullurl[f] = authority
- end
- if path and path ~= "" then
- f = f + 1 ; fullurl[f] = "/" .. path
- end
- if query and query ~= "" then
- f = f + 1 ; fullurl[f] = "?".. query
+ before[#before+1]=v
end
- if fragment and fragment ~= "" then
- f = f + 1 ; fullurl[f] = "#".. fragment
- end
- return lpegmatch(escaper,concat(fullurl))
+ end
+ return before,after
end
-
-function url.filename(filename)
- local t = hashed(filename)
- return (t.scheme == "file" and (gsub(t.path,"^/([a-zA-Z])([:|])/)","%1:"))) or filename
+function environment.reconstructcommandline(arg,noquote)
+ arg=arg or environment.originalarguments
+ if noquote and #arg==1 then
+ local a=arg[1]
+ a=resolvers.resolve(a)
+ a=unquoted(a)
+ return a
+ elseif #arg>0 then
+ local result={}
+ for i=1,#arg do
+ local a=arg[i]
+ a=resolvers.resolve(a)
+ a=unquoted(a)
+ a=gsub(a,'"','\\"')
+ if find(a," ") then
+ result[#result+1]=quoted(a)
+ else
+ result[#result+1]=a
+ end
+ end
+ return concat(result," ")
+ else
+ return ""
+ end
end
-
-function url.query(str)
- if type(str) == "string" then
- local t = { }
- for k, v in gmatch(str,"([^&=]*)=([^&=]*)") do
- t[k] = v
- end
- return t
+if arg then
+ local newarg,instring={},false
+ for index=1,#arg do
+ local argument=arg[index]
+ if find(argument,"^\"") then
+ newarg[#newarg+1]=gsub(argument,"^\"","")
+ if not find(argument,"\"$") then
+ instring=true
+ end
+ elseif find(argument,"\"$") then
+ newarg[#newarg]=newarg[#newarg].." "..gsub(argument,"\"$","")
+ instring=false
+ elseif instring then
+ newarg[#newarg]=newarg[#newarg].." "..argument
else
- return str
+ newarg[#newarg+1]=argument
end
+ end
+ for i=1,-5,-1 do
+ newarg[i]=arg[i]
+ end
+ environment.initializearguments(newarg)
+ environment.originalarguments=mark(newarg)
+ environment.rawarguments=mark(arg)
+ arg={}
end
-
-
-
-
-
-
-
-
end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-dir'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- dir.expandname will be merged with cleanpath and collapsepath
-
-local type = type
-local find, gmatch, match, gsub = string.find, string.gmatch, string.match, string.gsub
-local concat, insert, remove = table.concat, table.insert, table.remove
-local lpegmatch = lpeg.match
-
-local P, S, R, C, Cc, Cs, Ct, Cv, V = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.Cc, lpeg.Cs, lpeg.Ct, lpeg.Cv, lpeg.V
+package.loaded["luat-env"] = package.loaded["luat-env"] or true
-dir = dir or { }
-local dir = dir
-local lfs = lfs
+-- original size: 5874, stripped down to: 4184
-local attributes = lfs.attributes
-local walkdir = lfs.dir
-local isdir = lfs.isdir
-local isfile = lfs.isfile
-local currentdir = lfs.currentdir
-
--- handy
-
-function dir.current()
- return (gsub(currentdir(),"\\","/"))
-end
-
--- optimizing for no find (*) does not save time
-
-
-local lfsisdir = isdir
-
-local function isdir(path)
- path = gsub(path,"[/\\]+$","")
- return lfsisdir(path)
+ if not modules then modules={} end modules ['luat-env']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local rawset,rawget,loadfile,assert=rawset,rawget,loadfile,assert
+local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end)
+local report_lua=logs.reporter("resolvers","lua")
+local luautilities=utilities.lua
+local luasuffixes=luautilities.suffixes
+environment=environment or {}
+local environment=environment
+local mt={
+ __index=function(_,k)
+ if k=="version" then
+ local version=tex.toks and tex.toks.contextversiontoks
+ if version and version~="" then
+ rawset(environment,"version",version)
+ return version
+ else
+ return "unknown"
+ end
+ elseif k=="kind" then
+ local kind=tex.toks and tex.toks.contextkindtoks
+ if kind and kind~="" then
+ rawset(environment,"kind",kind)
+ return kind
+ else
+ return "unknown"
+ end
+ elseif k=="jobname" or k=="formatname" then
+ local name=tex and tex[k]
+ if name or name=="" then
+ rawset(environment,k,name)
+ return name
+ else
+ return "unknown"
+ end
+ elseif k=="outputfilename" then
+ local name=environment.jobname
+ rawset(environment,k,name)
+ return name
+ end
+ end
+}
+setmetatable(environment,mt)
+function environment.texfile(filename)
+ return resolvers.findfile(filename,'tex')
+end
+function environment.luafile(filename)
+ local resolved=resolvers.findfile(filename,'tex') or ""
+ if resolved~="" then
+ return resolved
+ end
+ resolved=resolvers.findfile(filename,'texmfscripts') or ""
+ if resolved~="" then
+ return resolved
+ end
+ return resolvers.findfile(filename,'luatexlibs') or ""
+end
+local stripindeed=false directives.register("system.compile.strip",function(v) stripindeed=v end)
+local function strippable(filename)
+ if stripindeed then
+ local modu=modules[file.nameonly(filename)]
+ return modu and modu.dataonly
+ else
+ return false
+ end
end
-
-lfs.isdir = isdir
-
-local function globpattern(path,patt,recurse,action)
- if path == "/" then
- path = path .. "."
- elseif not find(path,"/$") then
- path = path .. '/'
- end
- if isdir(path) then -- lfs.isdir does not like trailing /
- for name in walkdir(path) do -- lfs.dir accepts trailing /
- local full = path .. name
- local mode = attributes(full,'mode')
- if mode == 'file' then
- if find(full,patt) then
- action(full)
- end
- elseif recurse and (mode == "directory") and (name ~= '.') and (name ~= "..") then
- globpattern(full,patt,recurse,action)
- end
- end
+function environment.luafilechunk(filename,silent)
+ filename=file.replacesuffix(filename,"lua")
+ local fullname=environment.luafile(filename)
+ if fullname and fullname~="" then
+ local data=luautilities.loadedluacode(fullname,strippable,filename)
+ if trace_locating then
+ report_lua("loading file %a %s",fullname,not data and "failed" or "succeeded")
+ elseif not silent then
+ texio.write("<",data and "+ " or "- ",fullname,">")
end
-end
-
-dir.globpattern = globpattern
-
-local function collectpattern(path,patt,recurse,result)
- local ok, scanner
- result = result or { }
- if path == "/" then
- ok, scanner, first = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe
- else
- ok, scanner, first = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
- end
- if ok and type(scanner) == "function" then
- if not find(path,"/$") then path = path .. '/' end
- for name in scanner, first do
- local full = path .. name
- local attr = attributes(full)
- local mode = attr.mode
- if mode == 'file' then
- if find(full,patt) then
- result[name] = attr
- end
- elseif recurse and (mode == "directory") and (name ~= '.') and (name ~= "..") then
- attr.list = collectpattern(full,patt,recurse)
- result[name] = attr
- end
- end
+ return data
+ else
+ if trace_locating then
+ report_lua("unknown file %a",filename)
end
- return result
-end
-
-dir.collectpattern = collectpattern
-
-local pattern = Ct {
- [1] = (C(P(".") + P("/")^1) + C(R("az","AZ") * P(":") * P("/")^0) + Cc("./")) * V(2) * V(3),
- [2] = C(((1-S("*?/"))^0 * P("/"))^0),
- [3] = C(P(1)^0)
-}
-
-local filter = Cs ( (
- P("**") / ".*" +
- P("*") / "[^/]*" +
- P("?") / "[^/]" +
- P(".") / "%%." +
- P("+") / "%%+" +
- P("-") / "%%-" +
- P(1)
-)^0 )
-
-local function glob(str,t)
- if type(t) == "function" then
- if type(str) == "table" then
- for s=1,#str do
- glob(str[s],t)
- end
- elseif isfile(str) then
- t(str)
- else
- local split = lpegmatch(pattern,str) -- we could use the file splitter
- if split then
- local root, path, base = split[1], split[2], split[3]
- local recurse = find(base,"%*%*")
- local start = root .. path
- local result = lpegmatch(filter,start .. base)
- globpattern(start,result,recurse,t)
- end
+ return nil
+ end
+end
+function environment.loadluafile(filename,version)
+ local lucname,luaname,chunk
+ local basename=file.removesuffix(filename)
+ if basename==filename then
+ luaname=file.addsuffix(basename,luasuffixes.lua)
+ lucname=file.addsuffix(basename,luasuffixes.luc)
+ else
+ luaname=basename
+ lucname=nil
+ end
+ local fullname=(lucname and environment.luafile(lucname)) or ""
+ if fullname~="" then
+ if trace_locating then
+ report_lua("loading %a",fullname)
+ end
+ chunk=loadfile(fullname)
+ end
+ if chunk then
+ assert(chunk)()
+ if version then
+ local v=version
+ if modules and modules[filename] then
+ v=modules[filename].version
+ elseif versions and versions[filename] then
+ v=versions[filename]
+ end
+ if v==version then
+ return true
+ else
+ if trace_locating then
+ report_lua("version mismatch for %a, lua version %a, luc version %a",filename,v,version)
end
+ environment.loadluafile(filename)
+ end
else
- if type(str) == "table" then
- local t = t or { }
- for s=1,#str do
- glob(str[s],t)
- end
- return t
- elseif isfile(str) then
- if t then
- t[#t+1] = str
- return t
- else
- return { str }
- end
- else
- local split = lpegmatch(pattern,str) -- we could use the file splitter
- if split then
- local t = t or { }
- local action = action or function(name) t[#t+1] = name end
- local root, path, base = split[1], split[2], split[3]
- local recurse = find(base,"%*%*")
- local start = root .. path
- local result = lpegmatch(filter,start .. base)
- globpattern(start,result,recurse,action)
- return t
- else
- return { }
- end
- end
+ return true
end
-end
-
-dir.glob = glob
-
-
-local function globfiles(path,recurse,func,files) -- func == pattern or function
- if type(func) == "string" then
- local s = func
- func = function(name) return find(name,s) end
+ end
+ fullname=(luaname and environment.luafile(luaname)) or ""
+ if fullname~="" then
+ if trace_locating then
+ report_lua("loading %a",fullname)
end
- files = files or { }
- local noffiles = #files
- for name in walkdir(path) do
- if find(name,"^%.") then
- --- skip
- else
- local mode = attributes(name,'mode')
- if mode == "directory" then
- if recurse then
- globfiles(path .. "/" .. name,recurse,func,files)
- end
- elseif mode == "file" then
- if not func or func(name) then
- noffiles = noffiles + 1
- files[noffiles] = path .. "/" .. name
- end
- end
- end
+ chunk=loadfile(fullname)
+ if not chunk then
+ if trace_locating then
+ report_lua("unknown file %a",filename)
+ end
+ else
+ assert(chunk)()
+ return true
end
- return files
+ end
+ return false
end
-dir.globfiles = globfiles
-
--- t = dir.glob("c:/data/develop/context/sources/**/????-*.tex")
--- t = dir.glob("c:/data/develop/tex/texmf/**/*.tex")
--- t = dir.glob("c:/data/develop/context/texmf/**/*.tex")
--- t = dir.glob("f:/minimal/tex/**/*")
--- print(dir.ls("f:/minimal/tex/**/*"))
--- print(dir.ls("*.tex"))
-
-function dir.ls(pattern)
- return concat(glob(pattern),"\n")
-end
+end -- of closure
-local make_indeed = true -- false
+do -- create closure to overcome 200 locals limit
-local onwindows = os.type == "windows" or find(os.getenv("PATH"),";")
+package.loaded["lxml-tab"] = package.loaded["lxml-tab"] or true
-if onwindows then
+-- original size: 42495, stripped down to: 26647
- function dir.mkdirs(...)
- local str, pth, t = "", "", { ... }
- for i=1,#t do
- local s = t[i]
- if s ~= "" then
- if str ~= "" then
- str = str .. "/" .. s
- else
- str = s
- end
- end
- end
- local first, middle, last
- local drive = false
- first, middle, last = match(str,"^(//)(//*)(.*)$")
- if first then
- -- empty network path == local path
- else
- first, last = match(str,"^(//)/*(.-)$")
- if first then
- middle, last = match(str,"([^/]+)/+(.-)$")
- if middle then
- pth = "//" .. middle
- else
- pth = "//" .. last
- last = ""
- end
- else
- first, middle, last = match(str,"^([a-zA-Z]:)(/*)(.-)$")
- if first then
- pth, drive = first .. middle, true
- else
- middle, last = match(str,"^(/*)(.-)$")
- if not middle then
- last = str
- end
- end
- end
- end
- for s in gmatch(last,"[^/]+") do
- if pth == "" then
- pth = s
- elseif drive then
- pth, drive = pth .. s, false
- else
- pth = pth .. "/" .. s
- end
- if make_indeed and not isdir(pth) then
- lfs.mkdir(pth)
- end
- end
- return pth, (isdir(pth) == true)
- end
-
-
-else
-
- function dir.mkdirs(...)
- local str, pth, t = "", "", { ... }
- for i=1,#t do
- local s = t[i]
- if s and s ~= "" then -- we catch nil and false
- if str ~= "" then
- str = str .. "/" .. s
- else
- str = s
- end
- end
- end
- str = gsub(str,"/+","/")
- if find(str,"^/") then
- pth = "/"
- for s in gmatch(str,"[^/]+") do
- local first = (pth == "/")
- if first then
- pth = pth .. s
- else
- pth = pth .. "/" .. s
- end
- if make_indeed and not first and not isdir(pth) then
- lfs.mkdir(pth)
- end
- end
- else
- pth = "."
- for s in gmatch(str,"[^/]+") do
- pth = pth .. "/" .. s
- if make_indeed and not isdir(pth) then
- lfs.mkdir(pth)
- end
- end
- end
- return pth, (isdir(pth) == true)
- end
-
-
+if not modules then modules={} end modules ['lxml-tab']={
+ version=1.001,
+ comment="this module is the basis for the lxml-* ones",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local trace_entities=false trackers.register("xml.entities",function(v) trace_entities=v end)
+local report_xml=logs and logs.reporter("xml","core") or function(...) print(string.format(...)) end
+xml=xml or {}
+local xml=xml
+local concat,remove,insert=table.concat,table.remove,table.insert
+local type,next,setmetatable,getmetatable,tonumber=type,next,setmetatable,getmetatable,tonumber
+local lower,find,match,gsub=string.lower,string.find,string.match,string.gsub
+local utfchar=utf.char
+local lpegmatch=lpeg.match
+local P,S,R,C,V,C,Cs=lpeg.P,lpeg.S,lpeg.R,lpeg.C,lpeg.V,lpeg.C,lpeg.Cs
+local formatters=string.formatters
+xml.xmlns=xml.xmlns or {}
+local check=P(false)
+local parse=check
+function xml.registerns(namespace,pattern)
+ check=check+C(P(lower(pattern)))/namespace
+ parse=P { P(check)+1*V(1) }
end
-
-dir.makedirs = dir.mkdirs
-
--- we can only define it here as it uses dir.current
-
-if onwindows then
-
- function dir.expandname(str) -- will be merged with cleanpath and collapsepath
- local first, nothing, last = match(str,"^(//)(//*)(.*)$")
- if first then
- first = dir.current() .. "/"
- end
- if not first then
- first, last = match(str,"^(//)/*(.*)$")
- end
- if not first then
- first, last = match(str,"^([a-zA-Z]:)(.*)$")
- if first and not find(last,"^/") then
- local d = currentdir()
- if lfs.chdir(first) then
- first = dir.current()
- end
- lfs.chdir(d)
- end
- end
- if not first then
- first, last = dir.current(), str
- end
- last = gsub(last,"//","/")
- last = gsub(last,"/%./","/")
- last = gsub(last,"^/*","")
- first = gsub(first,"/*$","")
- if last == "" or last == "." then
- return first
- else
- return first .. "/" .. last
- end
- end
-
-else
-
- function dir.expandname(str) -- will be merged with cleanpath and collapsepath
- if not find(str,"^/") then
- str = currentdir() .. "/" .. str
- end
- str = gsub(str,"//","/")
- str = gsub(str,"/%./","/")
- str = gsub(str,"(.)/%.$","%1")
- return str
- end
-
+function xml.checkns(namespace,url)
+ local ns=lpegmatch(parse,lower(url))
+ if ns and namespace~=ns then
+ xml.xmlns[namespace]=ns
+ end
end
-
-file.expandname = dir.expandname -- for convenience
-
-local stack = { }
-
-function dir.push(newdir)
- insert(stack,lfs.currentdir())
+function xml.resolvens(url)
+ return lpegmatch(parse,lower(url)) or ""
+end
+local nsremap,resolvens=xml.xmlns,xml.resolvens
+local stack={}
+local top={}
+local dt={}
+local at={}
+local xmlns={}
+local errorstr=nil
+local entities={}
+local strip=false
+local cleanup=false
+local utfize=false
+local resolve_predefined=false
+local unify_predefined=false
+local dcache={}
+local hcache={}
+local acache={}
+local mt={}
+local function initialize_mt(root)
+ mt={ __index=root }
end
-
-function dir.pop()
- local d = remove(stack)
- if d then
- lfs.chdir(d)
- end
- return d
+function xml.setproperty(root,k,v)
+ getmetatable(root).__index[k]=v
end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['l-boolean'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
+function xml.checkerror(top,toclose)
+ return ""
+end
+local function add_attribute(namespace,tag,value)
+ if cleanup and #value>0 then
+ value=cleanup(value)
+ end
+ if tag=="xmlns" then
+ xmlns[#xmlns+1]=resolvens(value)
+ at[tag]=value
+ elseif namespace=="" then
+ at[tag]=value
+ elseif namespace=="xmlns" then
+ xml.checkns(tag,value)
+ at["xmlns:"..tag]=value
+ else
+ at[namespace..":"..tag]=value
+ end
+end
+local function add_empty(spacing,namespace,tag)
+ if #spacing>0 then
+ dt[#dt+1]=spacing
+ end
+ local resolved=namespace=="" and xmlns[#xmlns] or nsremap[namespace] or namespace
+ top=stack[#stack]
+ dt=top.dt
+ local t={ ns=namespace or "",rn=resolved,tg=tag,at=at,dt={},__p__=top }
+ dt[#dt+1]=t
+ setmetatable(t,mt)
+ if at.xmlns then
+ remove(xmlns)
+ end
+ at={}
+end
+local function add_begin(spacing,namespace,tag)
+ if #spacing>0 then
+ dt[#dt+1]=spacing
+ end
+ local resolved=namespace=="" and xmlns[#xmlns] or nsremap[namespace] or namespace
+ top={ ns=namespace or "",rn=resolved,tg=tag,at=at,dt={},__p__=stack[#stack] }
+ setmetatable(top,mt)
+ dt=top.dt
+ stack[#stack+1]=top
+ at={}
+end
+local function add_end(spacing,namespace,tag)
+ if #spacing>0 then
+ dt[#dt+1]=spacing
+ end
+ local toclose=remove(stack)
+ top=stack[#stack]
+ if #stack<1 then
+ errorstr=formatters["unable to close %s %s"](tag,xml.checkerror(top,toclose) or "")
+ elseif toclose.tg~=tag then
+ errorstr=formatters["unable to close %s with %s %s"](toclose.tg,tag,xml.checkerror(top,toclose) or "")
+ end
+ dt=top.dt
+ dt[#dt+1]=toclose
+ if toclose.at.xmlns then
+ remove(xmlns)
+ end
+end
+local function add_text(text)
+ if cleanup and #text>0 then
+ dt[#dt+1]=cleanup(text)
+ else
+ dt[#dt+1]=text
+ end
+end
+local function add_special(what,spacing,text)
+ if #spacing>0 then
+ dt[#dt+1]=spacing
+ end
+ if strip and (what=="@cm@" or what=="@dt@") then
+ else
+ dt[#dt+1]={ special=true,ns="",tg=what,dt={ text } }
+ end
+end
+local function set_message(txt)
+ errorstr="garbage at the end of the file: "..gsub(txt,"([ \n\r\t]*)","")
+end
+local reported_attribute_errors={}
+local function attribute_value_error(str)
+ if not reported_attribute_errors[str] then
+ report_xml("invalid attribute value %a",str)
+ reported_attribute_errors[str]=true
+ at._error_=str
+ end
+ return str
+end
+local function attribute_specification_error(str)
+ if not reported_attribute_errors[str] then
+ report_xml("invalid attribute specification %a",str)
+ reported_attribute_errors[str]=true
+ at._error_=str
+ end
+ return str
+end
+xml.placeholders={
+ unknown_dec_entity=function(str) return str=="" and "&error;" or formatters["&%s;"](str) end,
+ unknown_hex_entity=function(str) return formatters["%s;"](str) end,
+ unknown_any_entity=function(str) return formatters["%s;"](str) end,
}
-
-local type, tonumber = type, tonumber
-
-boolean = boolean or { }
-local boolean = boolean
-
-function boolean.tonumber(b)
- if b then return 1 else return 0 end -- test and return or return
+local placeholders=xml.placeholders
+local function fromhex(s)
+ local n=tonumber(s,16)
+ if n then
+ return utfchar(n)
+ else
+ return formatters["h:%s"](s),true
+ end
end
-
-function toboolean(str,tolerant)
- if tolerant then
- local tstr = type(str)
- if tstr == "string" then
- return str == "true" or str == "yes" or str == "on" or str == "1" or str == "t"
- elseif tstr == "number" then
- return tonumber(str) ~= 0
- elseif tstr == "nil" then
- return false
- else
- return str
- end
- elseif str == "true" then
- return true
- elseif str == "false" then
- return false
+local function fromdec(s)
+ local n=tonumber(s)
+ if n then
+ return utfchar(n)
+ else
+ return formatters["d:%s"](s),true
+ end
+end
+local rest=(1-P(";"))^0
+local many=P(1)^0
+local parsedentity=P("&")*(P("#x")*(rest/fromhex)+P("#")*(rest/fromdec))*P(";")*P(-1)+(P("#x")*(many/fromhex)+P("#")*(many/fromdec))
+local predefined_unified={
+ [38]="&",
+ [42]=""",
+ [47]="'",
+ [74]="<",
+ [76]=">",
+}
+local predefined_simplified={
+ [38]="&",amp="&",
+ [42]='"',quot='"',
+ [47]="'",apos="'",
+ [74]="<",lt="<",
+ [76]=">",gt=">",
+}
+local nofprivates=0xF0000
+local privates_u={
+ [ [[&]] ]="&",
+ [ [["]] ]=""",
+ [ [[']] ]="'",
+ [ [[<]] ]="<",
+ [ [[>]] ]=">",
+}
+local privates_p={}
+local privates_n={
+}
+local escaped=utf.remapper(privates_u)
+local function unescaped(s)
+ local p=privates_n[s]
+ if not p then
+ nofprivates=nofprivates+1
+ p=utfchar(nofprivates)
+ privates_n[s]=p
+ s="&"..s..";"
+ privates_u[p]=s
+ privates_p[p]=s
+ end
+ return p
+end
+local unprivatized=utf.remapper(privates_p)
+xml.privatetoken=unescaped
+xml.unprivatized=unprivatized
+xml.privatecodes=privates_n
+local function handle_hex_entity(str)
+ local h=hcache[str]
+ if not h then
+ local n=tonumber(str,16)
+ h=unify_predefined and predefined_unified[n]
+ if h then
+ if trace_entities then
+ report_xml("utfize, converting hex entity %s; into %a",str,h)
+ end
+ elseif utfize then
+ h=(n and utfchar(n)) or xml.unknown_hex_entity(str) or ""
+ if not n then
+ report_xml("utfize, ignoring hex entity %s;",str)
+ elseif trace_entities then
+ report_xml("utfize, converting hex entity %s; into %a",str,h)
+ end
else
- return str
+ if trace_entities then
+ report_xml("found entity %s;",str)
+ end
+ h=""..str..";"
end
+ hcache[str]=h
+ end
+ return h
end
-
-string.toboolean = toboolean
-
-function string.is_boolean(str,default)
- if type(str) == "string" then
- if str == "true" or str == "yes" or str == "on" or str == "t" then
- return true
- elseif str == "false" or str == "no" or str == "off" or str == "f" then
- return false
- end
+local function handle_dec_entity(str)
+ local d=dcache[str]
+ if not d then
+ local n=tonumber(str)
+ d=unify_predefined and predefined_unified[n]
+ if d then
+ if trace_entities then
+ report_xml("utfize, converting dec entity %s; into %a",str,d)
+ end
+ elseif utfize then
+ d=(n and utfchar(n)) or placeholders.unknown_dec_entity(str) or ""
+ if not n then
+ report_xml("utfize, ignoring dec entity %s;",str)
+ elseif trace_entities then
+ report_xml("utfize, converting dec entity %s; into %a",str,d)
+ end
+ else
+ if trace_entities then
+ report_xml("found entity %s;",str)
+ end
+ d=""..str..";"
end
- return default
+ dcache[str]=d
+ end
+ return d
end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['l-unicode'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-if not unicode then
-
- unicode = { utf8 = { } }
-
- local floor, char = math.floor, string.char
-
- function unicode.utf8.utfchar(n)
- if n < 0x80 then
- return char(n)
- elseif n < 0x800 then
- return char(
- 0xC0 + floor(n/0x40),
- 0x80 + (n % 0x40)
- )
- elseif n < 0x10000 then
- return char(
- 0xE0 + floor(n/0x1000),
- 0x80 + (floor(n/0x40) % 0x40),
- 0x80 + (n % 0x40)
- )
- elseif n < 0x40000 then
- return char(
- 0xF0 + floor(n/0x40000),
- 0x80 + floor(n/0x1000),
- 0x80 + (floor(n/0x40) % 0x40),
- 0x80 + (n % 0x40)
- )
+xml.parsedentitylpeg=parsedentity
+local function handle_any_entity(str)
+ if resolve then
+ local a=acache[str]
+ if not a then
+ a=resolve_predefined and predefined_simplified[str]
+ if a then
+ if trace_entities then
+ report_xml("resolving entity &%s; to predefined %a",str,a)
+ end
+ else
+ if type(resolve)=="function" then
+ a=resolve(str) or entities[str]
else
- -- return char(
- -- 0xF1 + floor(n/0x1000000),
- -- 0x80 + floor(n/0x40000),
- -- 0x80 + floor(n/0x1000),
- -- 0x80 + (floor(n/0x40) % 0x40),
- -- 0x80 + (n % 0x40)
- -- )
- return "?"
+ a=entities[str]
end
- end
-
+ if a then
+ if type(a)=="function" then
+ if trace_entities then
+ report_xml("expanding entity &%s; to function call",str)
+ end
+ a=a(str) or ""
+ end
+ a=lpegmatch(parsedentity,a) or a
+ if trace_entities then
+ report_xml("resolving entity &%s; to internal %a",str,a)
+ end
+ else
+ local unknown_any_entity=placeholders.unknown_any_entity
+ if unknown_any_entity then
+ a=unknown_any_entity(str) or ""
+ end
+ if a then
+ if trace_entities then
+ report_xml("resolving entity &%s; to external %s",str,a)
+ end
+ else
+ if trace_entities then
+ report_xml("keeping entity &%s;",str)
+ end
+ if str=="" then
+ a="&error;"
+ else
+ a="&"..str..";"
+ end
+ end
+ end
+ end
+ acache[str]=a
+ elseif trace_entities then
+ if not acache[str] then
+ report_xml("converting entity &%s; to %a",str,a)
+ acache[str]=a
+ end
+ end
+ return a
+ else
+ local a=acache[str]
+ if not a then
+ a=resolve_predefined and predefined_simplified[str]
+ if a then
+ acache[str]=a
+ if trace_entities then
+ report_xml("entity &%s; becomes %a",str,a)
+ end
+ elseif str=="" then
+ if trace_entities then
+ report_xml("invalid entity &%s;",str)
+ end
+ a="&error;"
+ acache[str]=a
+ else
+ if trace_entities then
+ report_xml("entity &%s; is made private",str)
+ end
+ a=unescaped(str)
+ acache[str]=a
+ end
+ end
+ return a
+ end
end
-
-local unicode = unicode
-
-utf = utf or unicode.utf8
-
-local concat = table.concat
-local utfchar, utfbyte, utfgsub = utf.char, utf.byte, utf.gsub
-local char, byte, find, bytepairs, utfvalues, format = string.char, string.byte, string.find, string.bytepairs, string.utfvalues, string.format
-local type = type
-
-local utfsplitlines = string.utfsplitlines
-
--- 0 EF BB BF UTF-8
--- 1 FF FE UTF-16-little-endian
--- 2 FE FF UTF-16-big-endian
--- 3 FF FE 00 00 UTF-32-little-endian
--- 4 00 00 FE FF UTF-32-big-endian
-
-unicode.utfname = {
- [0] = 'utf-8',
- [1] = 'utf-16-le',
- [2] = 'utf-16-be',
- [3] = 'utf-32-le',
- [4] = 'utf-32-be'
+local function handle_end_entity(chr)
+ report_xml("error in entity, %a found instead of %a",chr,";")
+end
+local space=S(' \r\n\t')
+local open=P('<')
+local close=P('>')
+local squote=S("'")
+local dquote=S('"')
+local equal=P('=')
+local slash=P('/')
+local colon=P(':')
+local semicolon=P(';')
+local ampersand=P('&')
+local valid=R('az','AZ','09')+S('_-.')
+local name_yes=C(valid^1)*colon*C(valid^1)
+local name_nop=C(P(true))*C(valid^1)
+local name=name_yes+name_nop
+local utfbom=lpeg.patterns.utfbom
+local spacing=C(space^0)
+local anyentitycontent=(1-open-semicolon-space-close)^0
+local hexentitycontent=R("AF","af","09")^0
+local decentitycontent=R("09")^0
+local parsedentity=P("#")/""*(
+ P("x")/""*(hexentitycontent/handle_hex_entity)+(decentitycontent/handle_dec_entity)
+ )+(anyentitycontent/handle_any_entity)
+local entity=ampersand/""*parsedentity*((semicolon/"")+#(P(1)/handle_end_entity))
+local text_unparsed=C((1-open)^1)
+local text_parsed=Cs(((1-open-ampersand)^1+entity)^1)
+local somespace=space^1
+local optionalspace=space^0
+local value=(squote*Cs((entity+(1-squote))^0)*squote)+(dquote*Cs((entity+(1-dquote))^0)*dquote)
+local endofattributes=slash*close+close
+local whatever=space*name*optionalspace*equal
+local wrongvalue=Cs(P(entity+(1-space-endofattributes))^1)/attribute_value_error
+local attributevalue=value+wrongvalue
+local attribute=(somespace*name*optionalspace*equal*optionalspace*attributevalue)/add_attribute
+local attributes=(attribute+somespace^-1*(((1-endofattributes)^1)/attribute_specification_error))^0
+local parsedtext=text_parsed/add_text
+local unparsedtext=text_unparsed/add_text
+local balanced=P { "["*((1-S"[]")+V(1))^0*"]" }
+local emptyelement=(spacing*open*name*attributes*optionalspace*slash*close)/add_empty
+local beginelement=(spacing*open*name*attributes*optionalspace*close)/add_begin
+local endelement=(spacing*open*slash*name*optionalspace*close)/add_end
+local begincomment=open*P("!--")
+local endcomment=P("--")*close
+local begininstruction=open*P("?")
+local endinstruction=P("?")*close
+local begincdata=open*P("![CDATA[")
+local endcdata=P("]]")*close
+local someinstruction=C((1-endinstruction)^0)
+local somecomment=C((1-endcomment )^0)
+local somecdata=C((1-endcdata )^0)
+local function normalentity(k,v ) entities[k]=v end
+local function systementity(k,v,n) entities[k]=v end
+local function publicentity(k,v,n) entities[k]=v end
+local begindoctype=open*P("!DOCTYPE")
+local enddoctype=close
+local beginset=P("[")
+local endset=P("]")
+local doctypename=C((1-somespace-close)^0)
+local elementdoctype=optionalspace*P("=5.1 where %z is depricated
-
-function unicode.utftype(f)
- local str = f:read(4)
- if not str then
- f:seek('set')
- return 0
- -- elseif find(str,"^%z%z\254\255") then -- depricated
- -- elseif find(str,"^\000\000\254\255") then -- not permitted and bugged
- elseif find(str,"\000\000\254\255",1,true) then -- seems to work okay (TH)
- return 4
- -- elseif find(str,"^\255\254%z%z") then -- depricated
- -- elseif find(str,"^\255\254\000\000") then -- not permitted and bugged
- elseif find(str,"\255\254\000\000",1,true) then -- seems to work okay (TH)
- return 3
- elseif find(str,"^\254\255") then
- f:seek('set',2)
- return 2
- elseif find(str,"^\255\254") then
- f:seek('set',2)
- return 1
- elseif find(str,"^\239\187\191") then
- f:seek('set',3)
- return 0
+local grammar_unparsed_text=P { "preamble",
+ preamble=utfbom^0*instruction^0*(doctype+comment+instruction)^0*V("parent")*trailer,
+ parent=beginelement*V("children")^0*endelement,
+ children=unparsedtext+V("parent")+emptyelement+comment+cdata+instruction,
+}
+local function _xmlconvert_(data,settings)
+ settings=settings or {}
+ strip=settings.strip_cm_and_dt
+ utfize=settings.utfize_entities
+ resolve=settings.resolve_entities
+ resolve_predefined=settings.resolve_predefined_entities
+ unify_predefined=settings.unify_predefined_entities
+ cleanup=settings.text_cleanup
+ entities=settings.entities or {}
+ if utfize==nil then
+ settings.utfize_entities=true
+ utfize=true
+ end
+ if resolve_predefined==nil then
+ settings.resolve_predefined_entities=true
+ resolve_predefined=true
+ end
+ stack,top,at,xmlns,errorstr={},{},{},{},nil
+ acache,hcache,dcache={},{},{}
+ reported_attribute_errors={}
+ if settings.parent_root then
+ mt=getmetatable(settings.parent_root)
+ else
+ initialize_mt(top)
+ end
+ stack[#stack+1]=top
+ top.dt={}
+ dt=top.dt
+ if not data or data=="" then
+ errorstr="empty xml file"
+ elseif utfize or resolve then
+ if lpegmatch(grammar_parsed_text,data) then
+ errorstr=""
else
- f:seek('set')
- return 0
+ errorstr="invalid xml file - parsed text"
end
+ elseif type(data)=="string" then
+ if lpegmatch(grammar_unparsed_text,data) then
+ errorstr=""
+ else
+ errorstr="invalid xml file - unparsed text"
+ end
+ else
+ errorstr="invalid xml file - no text at all"
+ end
+ local result
+ if errorstr and errorstr~="" then
+ result={ dt={ { ns="",tg="error",dt={ errorstr },at={},er=true } } }
+ setmetatable(stack,mt)
+ local errorhandler=settings.error_handler
+ if errorhandler==false then
+ else
+ errorhandler=errorhandler or xml.errorhandler
+ if errorhandler then
+ local currentresource=settings.currentresource
+ if currentresource and currentresource~="" then
+ xml.errorhandler(formatters["load error in [%s]: %s"](currentresource,errorstr))
+ else
+ xml.errorhandler(formatters["load error: %s"](errorstr))
+ end
+ end
+ end
+ else
+ result=stack[1]
+ end
+ if not settings.no_root then
+ result={ special=true,ns="",tg='@rt@',dt=result.dt,at={},entities=entities,settings=settings }
+ setmetatable(result,mt)
+ local rdt=result.dt
+ for k=1,#rdt do
+ local v=rdt[k]
+ if type(v)=="table" and not v.special then
+ result.ri=k
+ v.__p__=result
+ break
+ end
+ end
+ end
+ if errorstr and errorstr~="" then
+ result.error=true
+ end
+ result.statistics={
+ entities={
+ decimals=dcache,
+ hexadecimals=hcache,
+ names=acache,
+ }
+ }
+ strip,utfize,resolve,resolve_predefined=nil,nil,nil,nil
+ unify_predefined,cleanup,entities=nil,nil,nil
+ stack,top,at,xmlns,errorstr=nil,nil,nil,nil,nil
+ acache,hcache,dcache=nil,nil,nil
+ reported_attribute_errors,mt,errorhandler=nil,nil,nil
+ return result
end
-
-
-
-local function utf16_to_utf8_be(t)
- if type(t) == "string" then
- t = utfsplitlines(str)
- end
- local result = { } -- we reuse result
- for i=1,#t do
- local r, more = 0, 0
- for left, right in bytepairs(t[i]) do
- if right then
- local now = 256*left + right
- if more > 0 then
- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
- more = 0
- r = r + 1
- result[r] = utfchar(now)
- elseif now >= 0xD800 and now <= 0xDBFF then
- more = now
- else
- r = r + 1
- result[r] = utfchar(now)
- end
- end
- end
- t[i] = concat(result,"",1,r) -- we reused tmp, hence t
- end
- return t
+function xmlconvert(data,settings)
+ local ok,result=pcall(function() return _xmlconvert_(data,settings) end)
+ if ok then
+ return result
+ else
+ return _xmlconvert_("",settings)
+ end
+end
+xml.convert=xmlconvert
+function xml.inheritedconvert(data,xmldata)
+ local settings=xmldata.settings
+ if settings then
+ settings.parent_root=xmldata
+ end
+ local xc=xmlconvert(data,settings)
+ return xc
end
-
-local function utf16_to_utf8_le(t)
- if type(t) == "string" then
- t = utfsplitlines(str)
- end
- local result = { } -- we reuse result
- for i=1,#t do
- local r, more = 0, 0
- for left, right in bytepairs(t[i]) do
- if right then
- local now = 256*right + left
- if more > 0 then
- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
- more = 0
- r = r + 1
- result[r] = utfchar(now)
- elseif now >= 0xD800 and now <= 0xDBFF then
- more = now
- else
- r = r + 1
- result[r] = utfchar(now)
- end
- end
- end
- t[i] = concat(result,"",1,r) -- we reused tmp, hence t
- end
- return t
+function xml.is_valid(root)
+ return root and root.dt and root.dt[1] and type(root.dt[1])=="table" and not root.dt[1].er
end
-
-local function utf32_to_utf8_be(t)
- if type(t) == "string" then
- t = utfsplitlines(t)
+function xml.package(tag,attributes,data)
+ local ns,tg=match(tag,"^(.-):?([^:]+)$")
+ local t={ ns=ns,tg=tg,dt=data or "",at=attributes or {} }
+ setmetatable(t,mt)
+ return t
+end
+function xml.is_valid(root)
+ return root and not root.error
+end
+xml.errorhandler=report_xml
+function xml.load(filename,settings)
+ local data=""
+ if type(filename)=="string" then
+ local f=io.open(filename,'r')
+ if f then
+ data=f:read("*all")
+ f:close()
+ end
+ elseif filename then
+ data=filename:read("*all")
+ end
+ if settings then
+ settings.currentresource=filename
+ local result=xmlconvert(data,settings)
+ settings.currentresource=nil
+ return result
+ else
+ return xmlconvert(data,{ currentresource=filename })
+ end
+end
+local no_root={ no_root=true }
+function xml.toxml(data)
+ if type(data)=="string" then
+ local root={ xmlconvert(data,no_root) }
+ return (#root>1 and root) or root[1]
+ else
+ return data
+ end
+end
+local function copy(old,tables)
+ if old then
+ tables=tables or {}
+ local new={}
+ if not tables[old] then
+ tables[old]=new
end
- local result = { } -- we reuse result
- for i=1,#t do
- local r, more = 0, -1
- for a,b in bytepairs(t[i]) do
- if a and b then
- if more < 0 then
- more = 256*256*256*a + 256*256*b
- else
- r = r + 1
- result[t] = utfchar(more + 256*a + b)
- more = -1
- end
- else
- break
- end
- end
- t[i] = concat(result,"",1,r)
+ for k,v in next,old do
+ new[k]=(type(v)=="table" and (tables[v] or copy(v,tables))) or v
end
- return t
-end
-
-local function utf32_to_utf8_le(t)
- if type(t) == "string" then
- t = utfsplitlines(t)
+ local mt=getmetatable(old)
+ if mt then
+ setmetatable(new,mt)
end
- local result = { } -- we reuse result
- for i=1,#t do
- local r, more = 0, -1
- for a,b in bytepairs(t[i]) do
- if a and b then
- if more < 0 then
- more = 256*b + a
- else
- r = r + 1
- result[t] = utfchar(more + 256*256*256*b + 256*256*a)
- more = -1
- end
- else
- break
- end
+ return new
+ else
+ return {}
+ end
+end
+xml.copy=copy
+function xml.checkbom(root)
+ if root.ri then
+ local dt=root.dt
+ for k=1,#dt do
+ local v=dt[k]
+ if type(v)=="table" and v.special and v.tg=="@pi@" and find(v.dt[1],"xml.*version=") then
+ return
+ end
+ end
+ insert(dt,1,{ special=true,ns="",tg="@pi@",dt={ "xml version='1.0' standalone='yes'" } } )
+ insert(dt,2,"\n" )
+ end
+end
+local function verbose_element(e,handlers)
+ local handle=handlers.handle
+ local serialize=handlers.serialize
+ local ens,etg,eat,edt,ern=e.ns,e.tg,e.at,e.dt,e.rn
+ local ats=eat and next(eat) and {}
+ if ats then
+ for k,v in next,eat do
+ ats[#ats+1]=formatters['%s=%q'](k,escaped(v))
+ end
+ end
+ if ern and trace_entities and ern~=ens then
+ ens=ern
+ end
+ if ens~="" then
+ if edt and #edt>0 then
+ if ats then
+ handle("<",ens,":",etg," ",concat(ats," "),">")
+ else
+ handle("<",ens,":",etg,">")
+ end
+ for i=1,#edt do
+ local e=edt[i]
+ if type(e)=="string" then
+ handle(escaped(e))
+ else
+ serialize(e,handlers)
+ end
+ end
+ handle("",ens,":",etg,">")
+ else
+ if ats then
+ handle("<",ens,":",etg," ",concat(ats," "),"/>")
+ else
+ handle("<",ens,":",etg,"/>")
+ end
+ end
+ else
+ if edt and #edt>0 then
+ if ats then
+ handle("<",etg," ",concat(ats," "),">")
+ else
+ handle("<",etg,">")
+ end
+ for i=1,#edt do
+ local e=edt[i]
+ if type(e)=="string" then
+ handle(escaped(e))
+ else
+ serialize(e,handlers)
end
- t[i] = concat(result,"",1,r)
+ end
+ handle("",etg,">")
+ else
+ if ats then
+ handle("<",etg," ",concat(ats," "),"/>")
+ else
+ handle("<",etg,"/>")
+ end
end
- return t
+ end
end
-
-unicode.utf32_to_utf8_be = utf32_to_utf8_be
-unicode.utf32_to_utf8_le = utf32_to_utf8_le
-unicode.utf16_to_utf8_be = utf16_to_utf8_be
-unicode.utf16_to_utf8_le = utf16_to_utf8_le
-
-function unicode.utf8_to_utf8(t)
- return type(t) == "string" and utfsplitlines(t) or t
+local function verbose_pi(e,handlers)
+ handlers.handle("",e.dt[1],"?>")
end
-
-function unicode.utf16_to_utf8(t,endian)
- return endian and utf16_to_utf8_be(t) or utf16_to_utf8_le(t) or t
+local function verbose_comment(e,handlers)
+ handlers.handle("")
end
-
-function unicode.utf32_to_utf8(t,endian)
- return endian and utf32_to_utf8_be(t) or utf32_to_utf8_le(t) or t
+local function verbose_cdata(e,handlers)
+ handlers.handle("")
end
-
-local function little(c)
- local b = byte(c)
- if b < 0x10000 then
- return char(b%256,b/256)
- else
- b = b - 0x10000
- local b1, b2 = b/1024 + 0xD800, b%1024 + 0xDC00
- return char(b1%256,b1/256,b2%256,b2/256)
- end
+local function verbose_doctype(e,handlers)
+ handlers.handle("")
end
-
-local function big(c)
- local b = byte(c)
- if b < 0x10000 then
- return char(b/256,b%256)
- else
- b = b - 0x10000
- local b1, b2 = b/1024 + 0xD800, b%1024 + 0xDC00
- return char(b1/256,b1%256,b2/256,b2%256)
- end
+local function verbose_root(e,handlers)
+ handlers.serialize(e.dt,handlers)
end
-
-function unicode.utf8_to_utf16(str,littleendian)
- if littleendian then
- return char(255,254) .. utfgsub(str,".",little)
+local function verbose_text(e,handlers)
+ handlers.handle(escaped(e))
+end
+local function verbose_document(e,handlers)
+ local serialize=handlers.serialize
+ local functions=handlers.functions
+ for i=1,#e do
+ local ei=e[i]
+ if type(ei)=="string" then
+ functions["@tx@"](ei,handlers)
else
- return char(254,255) .. utfgsub(str,".",big)
+ serialize(ei,handlers)
end
+ end
end
-
-function unicode.utfcodes(str)
- local t, n = { }, 0
- for u in utfvalues(str) do
- n = n + 1
- t[n] = format("0x%04X",u)
- end
- return concat(t,separator or " ")
+local function serialize(e,handlers,...)
+ local initialize=handlers.initialize
+ local finalize=handlers.finalize
+ local functions=handlers.functions
+ if initialize then
+ local state=initialize(...)
+ if not state==true then
+ return state
+ end
+ end
+ local etg=e.tg
+ if etg then
+ (functions[etg] or functions["@el@"])(e,handlers)
+ else
+ functions["@dc@"](e,handlers)
+ end
+ if finalize then
+ return finalize()
+ end
end
-
-function unicode.ustring(s)
- return format("U+%05X",type(s) == "number" and s or utfbyte(s))
+local function xserialize(e,handlers)
+ local functions=handlers.functions
+ local etg=e.tg
+ if etg then
+ (functions[etg] or functions["@el@"])(e,handlers)
+ else
+ functions["@dc@"](e,handlers)
+ end
+end
+local handlers={}
+local function newhandlers(settings)
+ local t=table.copy(handlers[settings and settings.parent or "verbose"] or {})
+ if settings then
+ for k,v in next,settings do
+ if type(v)=="table" then
+ local tk=t[k] if not tk then tk={} t[k]=tk end
+ for kk,vv in next,v do
+ tk[kk]=vv
+ end
+ else
+ t[k]=v
+ end
+ end
+ if settings.name then
+ handlers[settings.name]=t
+ end
+ end
+ utilities.storage.mark(t)
+ return t
+end
+local nofunction=function() end
+function xml.sethandlersfunction(handler,name,fnc)
+ handler.functions[name]=fnc or nofunction
end
-
-function unicode.xstring(s)
- return format("0x%05X",type(s) == "number" and s or utfbyte(s))
+function xml.gethandlersfunction(handler,name)
+ return handler.functions[name]
end
-
-
-local lpegmatch = lpeg.match
-local patterns = lpeg.patterns
-local utftype = patterns.utftype
-
-function unicode.filetype(data)
- return data and lpegmatch(utftype,data) or "unknown"
+function xml.gethandlers(name)
+ return handlers[name]
end
-
-local toentities = lpeg.Cs (
- (
- patterns.utf8one
- + (
- patterns.utf8two
- + patterns.utf8three
- + patterns.utf8four
- ) / function(s) local b = utfbyte(s) if b < 127 then return s else return format("%X;",b) end end
- )^0
-)
-
-patterns.toentities = toentities
-
-function utf.toentities(str)
- return lpegmatch(toentities,str)
-end
-
-
-
-
-local P, C, R, Cs = lpeg.P, lpeg.C, lpeg.R, lpeg.Cs
-
-local one = P(1)
-local two = C(1) * C(1)
-local four = C(R(utfchar(0xD8),utfchar(0xFF))) * C(1) * C(1) * C(1)
-
--- actually one of them is already utf ... sort of useless this one
-
-local pattern = P("\254\255") * Cs( (
- four / function(a,b,c,d)
- local ab = 0xFF * byte(a) + byte(b)
- local cd = 0xFF * byte(c) + byte(d)
- return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000)
- end
- + two / function(a,b)
- return utfchar(byte(a)*256 + byte(b))
- end
- + one
- )^1 )
- + P("\255\254") * Cs( (
- four / function(b,a,d,c)
- local ab = 0xFF * byte(a) + byte(b)
- local cd = 0xFF * byte(c) + byte(d)
- return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000)
- end
- + two / function(b,a)
- return utfchar(byte(a)*256 + byte(b))
- end
- + one
- )^1 )
-
-function string.toutf(s)
- return lpegmatch(pattern,s) or s -- todo: utf32
-end
-
-local validatedutf = Cs (
- (
- patterns.utf8one
- + patterns.utf8two
- + patterns.utf8three
- + patterns.utf8four
- + P(1) / "�"
- )^0
-)
-
-patterns.validatedutf = validatedutf
-
-function string.validutf(str)
- return lpegmatch(validatedutf,str)
-end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['l-math'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
+newhandlers {
+ name="verbose",
+ initialize=false,
+ finalize=false,
+ serialize=xserialize,
+ handle=print,
+ functions={
+ ["@dc@"]=verbose_document,
+ ["@dt@"]=verbose_doctype,
+ ["@rt@"]=verbose_root,
+ ["@el@"]=verbose_element,
+ ["@pi@"]=verbose_pi,
+ ["@cm@"]=verbose_comment,
+ ["@cd@"]=verbose_cdata,
+ ["@tx@"]=verbose_text,
+ }
}
-
-local floor, sin, cos, tan = math.floor, math.sin, math.cos, math.tan
-
-if not math.round then
- function math.round(x) return floor(x + 0.5) end
-end
-
-if not math.div then
- function math.div(n,m) return floor(n/m) end
+local result
+local xmlfilehandler=newhandlers {
+ name="file",
+ initialize=function(name)
+ result=io.open(name,"wb")
+ return result
+ end,
+ finalize=function()
+ result:close()
+ return true
+ end,
+ handle=function(...)
+ result:write(...)
+ end,
+}
+function xml.save(root,name)
+ serialize(root,xmlfilehandler,name)
end
-
-if not math.mod then
- function math.mod(n,m) return n % m end
+local result
+local xmlstringhandler=newhandlers {
+ name="string",
+ initialize=function()
+ result={}
+ return result
+ end,
+ finalize=function()
+ return concat(result)
+ end,
+ handle=function(...)
+ result[#result+1]=concat {... }
+ end,
+}
+local function xmltostring(root)
+ if not root then
+ return ""
+ elseif type(root)=="string" then
+ return root
+ else
+ return serialize(root,xmlstringhandler) or ""
+ end
end
-
-local pipi = 2*math.pi/360
-
-if not math.sind then
- function math.sind(d) return sin(d*pipi) end
- function math.cosd(d) return cos(d*pipi) end
- function math.tand(d) return tan(d*pipi) end
+local function __tostring(root)
+ return (root and xmltostring(root)) or ""
end
-
-if not math.odd then
- function math.odd (n) return n % 2 ~= 0 end
- function math.even(n) return n % 2 == 0 end
+initialize_mt=function(root)
+ mt={ __tostring=__tostring,__index=root }
end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['util-tab'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-utilities = utilities or {}
-utilities.tables = utilities.tables or { }
-local tables = utilities.tables
-
-local format, gmatch, rep = string.format, string.gmatch, string.rep
-local concat, insert, remove = table.concat, table.insert, table.remove
-local setmetatable, getmetatable, tonumber, tostring = setmetatable, getmetatable, tonumber, tostring
-local type, next, rawset, tonumber = type, next, rawset, tonumber
-
-function tables.definetable(target) -- defines undefined tables
- local composed, t, n = nil, { }, 0
- for name in gmatch(target,"([^%.]+)") do
- n = n + 1
- if composed then
- composed = composed .. "." .. name
- else
- composed = name
- end
- t[n] = format("%s = %s or { }",composed,composed)
+xml.defaulthandlers=handlers
+xml.newhandlers=newhandlers
+xml.serialize=serialize
+xml.tostring=xmltostring
+local function xmlstring(e,handle)
+ if not handle or (e.special and e.tg~="@rt@") then
+ elseif e.tg then
+ local edt=e.dt
+ if edt then
+ for i=1,#edt do
+ xmlstring(edt[i],handle)
+ end
end
- return concat(t,"\n")
+ else
+ handle(e)
+ end
end
-
-function tables.accesstable(target,root)
- local t = root or _G
- for name in gmatch(target,"([^%.]+)") do
- t = t[name]
- if not t then
- return
- end
+xml.string=xmlstring
+function xml.settings(e)
+ while e do
+ local s=e.settings
+ if s then
+ return s
+ else
+ e=e.__p__
end
- return t
+ end
+ return nil
end
-
-function tables.migratetable(target,v,root)
- local t = root or _G
- local names = string.split(target,".")
- for i=1,#names-1 do
- local name = names[i]
- t[name] = t[name] or { }
- t = t[name]
- if not t then
- return
- end
+function xml.root(e)
+ local r=e
+ while e do
+ e=e.__p__
+ if e then
+ r=e
end
- t[names[#names]] = v
+ end
+ return r
end
-
-function tables.removevalue(t,value) -- todo: n
- if value then
- for i=1,#t do
- if t[i] == value then
- remove(t,i)
- -- remove all, so no: return
- end
- end
- end
+function xml.parent(root)
+ return root.__p__
end
-
-function tables.insertbeforevalue(t,value,extra)
- for i=1,#t do
- if t[i] == extra then
- remove(t,i)
- end
- end
- for i=1,#t do
- if t[i] == value then
- insert(t,i,extra)
- return
- end
- end
- insert(t,1,extra)
+function xml.body(root)
+ return root.ri and root.dt[root.ri] or root
end
-
-function tables.insertaftervalue(t,value,extra)
- for i=1,#t do
- if t[i] == extra then
- remove(t,i)
- end
- end
- for i=1,#t do
- if t[i] == value then
- insert(t,i+1,extra)
- return
- end
- end
- insert(t,#t+1,extra)
+function xml.name(root)
+ if not root then
+ return ""
+ end
+ local ns=root.ns
+ local tg=root.tg
+ if ns=="" then
+ return tg
+ else
+ return ns..":"..tg
+ end
end
-
--- experimental
-
-local function toxml(t,d,result,step)
- for k, v in table.sortedpairs(t) do
- if type(v) == "table" then
- if type(k) == "number" then
- result[#result+1] = format("%s",d,k)
- toxml(v,d..step,result,step)
- result[#result+1] = format("%s ",d,k)
- else
- result[#result+1] = format("%s<%s>",d,k)
- toxml(v,d..step,result,step)
- result[#result+1] = format("%s%s>",d,k)
- end
- elseif type(k) == "number" then
- result[#result+1] = format("%s%s ",d,k,v,k)
- else
- result[#result+1] = format("%s<%s>%s%s>",d,k,tostring(v),k)
- end
- end
+function xml.erase(dt,k)
+ if dt then
+ if k then
+ dt[k]=""
+ else for k=1,#dt do
+ dt[1]={ "" }
+ end end
+ end
end
-
-function table.toxml(t,name,nobanner,indent,spaces)
- local noroot = name == false
- local result = (nobanner or noroot) and { } or { "" }
- local indent = rep(" ",indent or 0)
- local spaces = rep(" ",spaces or 1)
- if noroot then
- toxml( t, inndent, result, spaces)
- else
- toxml( { [name or "root"] = t }, indent, result, spaces)
- end
- return concat(result,"\n")
+function xml.assign(dt,k,root)
+ if dt and k then
+ dt[k]=type(root)=="table" and xml.body(root) or root
+ return dt[k]
+ else
+ return xml.body(root)
+ end
+end
+function xml.tocdata(e,wrapper)
+ local whatever=type(e)=="table" and xmltostring(e.dt) or e or ""
+ if wrapper then
+ whatever=formatters["<%s>%s%s>"](wrapper,whatever,wrapper)
+ end
+ local t={ special=true,ns="",tg="@cd@",at={},rn="",dt={ whatever },__p__=e }
+ setmetatable(t,getmetatable(e))
+ e.dt={ t }
end
-
--- also experimental
-
--- encapsulate(table,utilities.tables)
--- encapsulate(table,utilities.tables,true)
--- encapsulate(table,true)
-
-function tables.encapsulate(core,capsule,protect)
- if type(capsule) ~= "table" then
- protect = true
- capsule = { }
- end
- for key, value in next, core do
- if capsule[key] then
- print(format("\ninvalid inheritance '%s' in '%s': %s",key,tostring(core)))
- os.exit()
- else
- capsule[key] = value
- end
- end
- if protect then
- for key, value in next, core do
- core[key] = nil
+function xml.makestandalone(root)
+ if root.ri then
+ local dt=root.dt
+ for k=1,#dt do
+ local v=dt[k]
+ if type(v)=="table" and v.special and v.tg=="@pi@" then
+ local txt=v.dt[1]
+ if find(txt,"xml.*version=") then
+ v.dt[1]=txt.." standalone='yes'"
+ break
end
- setmetatable(core, {
- __index = capsule,
- __newindex = function(t,key,value)
- if capsule[key] then
- print(format("\ninvalid overload '%s' in '%s'",key,tostring(core)))
- os.exit()
- else
- rawset(t,key,value)
- end
- end
- } )
+ end
end
+ end
+ return root
+end
+function xml.kind(e)
+ local dt=e and e.dt
+ if dt then
+ local n=#dt
+ if n==1 then
+ local d=dt[1]
+ if d.special then
+ local tg=d.tg
+ if tg=="@cd@" then
+ return "cdata"
+ elseif tg=="@cm" then
+ return "comment"
+ elseif tg=="@pi@" then
+ return "instruction"
+ elseif tg=="@dt@" then
+ return "declaration"
+ end
+ elseif type(d)=="string" then
+ return "text"
+ end
+ return "element"
+ elseif n>0 then
+ return "mixed"
+ end
+ end
+ return "empty"
end
@@ -4351,9885 +8998,3514 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['util-sto'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local setmetatable, getmetatable = setmetatable, getmetatable
-
-utilities = utilities or { }
-utilities.storage = utilities.storage or { }
-local storage = utilities.storage
-
-function storage.mark(t)
- if not t then
- texio.write_nl("fatal error: storage cannot be marked")
- return -- os.exit()
- end
- local m = getmetatable(t)
- if not m then
- m = { }
- setmetatable(t,m)
- end
- m.__storage__ = true
- return t
-end
-
-function storage.allocate(t)
- t = t or { }
- local m = getmetatable(t)
- if not m then
- m = { }
- setmetatable(t,m)
- end
- m.__storage__ = true
- return t
-end
-
-function storage.marked(t)
- local m = getmetatable(t)
- return m and m.__storage__
-end
-
-function storage.checked(t)
- if not t then
- texio.write_nl("fatal error: storage has not been allocated")
- return -- os.exit()
- end
- return t
-end
+package.loaded["lxml-lpt"] = package.loaded["lxml-lpt"] or true
+-- original size: 48956, stripped down to: 30516
-function storage.setinitializer(data,initialize)
- local m = getmetatable(data) or { }
- m.__index = function(data,k)
- m.__index = nil -- so that we can access the entries during initializing
- initialize()
- return data[k]
- end
- setmetatable(data, m)
+if not modules then modules={} end modules ['lxml-lpt']={
+ version=1.001,
+ comment="this module is the basis for the lxml-* ones",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local concat,remove,insert=table.concat,table.remove,table.insert
+local type,next,tonumber,tostring,setmetatable,load,select=type,next,tonumber,tostring,setmetatable,load,select
+local format,upper,lower,gmatch,gsub,find,rep=string.format,string.upper,string.lower,string.gmatch,string.gsub,string.find,string.rep
+local lpegmatch,lpegpatterns=lpeg.match,lpeg.patterns
+local setmetatableindex=table.setmetatableindex
+local formatters=string.formatters
+local trace_lpath=false if trackers then trackers.register("xml.path",function(v) trace_lpath=v end) end
+local trace_lparse=false if trackers then trackers.register("xml.parse",function(v) trace_lparse=v end) end
+local trace_lprofile=false if trackers then trackers.register("xml.profile",function(v) trace_lpath=v trace_lparse=v trace_lprofile=v end) end
+local report_lpath=logs.reporter("xml","lpath")
+local xml=xml
+local lpathcalls=0 function xml.lpathcalls () return lpathcalls end
+local lpathcached=0 function xml.lpathcached() return lpathcached end
+xml.functions=xml.functions or {}
+local functions=xml.functions
+xml.expressions=xml.expressions or {}
+local expressions=xml.expressions
+xml.finalizers=xml.finalizers or {}
+local finalizers=xml.finalizers
+xml.specialhandler=xml.specialhandler or {}
+local specialhandler=xml.specialhandler
+lpegpatterns.xml=lpegpatterns.xml or {}
+local xmlpatterns=lpegpatterns.xml
+finalizers.xml=finalizers.xml or {}
+finalizers.tex=finalizers.tex or {}
+local function fallback (t,name)
+ local fn=finalizers[name]
+ if fn then
+ t[name]=fn
+ else
+ report_lpath("unknown sub finalizer %a",name)
+ fn=function() end
+ end
+ return fn
+end
+setmetatableindex(finalizers.xml,fallback)
+setmetatableindex(finalizers.tex,fallback)
+xml.defaultprotocol="xml"
+local apply_axis={}
+apply_axis['root']=function(list)
+ local collected={}
+ for l=1,#list do
+ local ll=list[l]
+ local rt=ll
+ while ll do
+ ll=ll.__p__
+ if ll then
+ rt=ll
+ end
+ end
+ collected[l]=rt
+ end
+ return collected
+end
+apply_axis['self']=function(list)
+ return list
+end
+apply_axis['child']=function(list)
+ local collected,c={},0
+ for l=1,#list do
+ local ll=list[l]
+ local dt=ll.dt
+ if dt then
+ local en=0
+ for k=1,#dt do
+ local dk=dt[k]
+ if dk.tg then
+ c=c+1
+ collected[c]=dk
+ dk.ni=k
+ en=en+1
+ dk.ei=en
+ end
+ end
+ ll.en=en
+ end
+ end
+ return collected
end
-
-local keyisvalue = { __index = function(t,k)
- t[k] = k
- return k
-end }
-
-function storage.sparse(t)
- t = t or { }
- setmetatable(t,keyisvalue)
- return t
+local function collect(list,collected,c)
+ local dt=list.dt
+ if dt then
+ local en=0
+ for k=1,#dt do
+ local dk=dt[k]
+ if dk.tg then
+ c=c+1
+ collected[c]=dk
+ dk.ni=k
+ en=en+1
+ dk.ei=en
+ c=collect(dk,collected,c)
+ end
+ end
+ list.en=en
+ end
+ return c
+end
+apply_axis['descendant']=function(list)
+ local collected,c={},0
+ for l=1,#list do
+ c=collect(list[l],collected,c)
+ end
+ return collected
end
-
--- table namespace ?
-
-local function f_empty () return "" end -- t,k
-local function f_self (t,k) t[k] = k return k end
-local function f_ignore() end -- t,k,v
-
-local t_empty = { __index = f_empty }
-local t_self = { __index = f_self }
-local t_ignore = { __newindex = f_ignore }
-
-function table.setmetatableindex(t,f)
- local m = getmetatable(t)
- if m then
- if f == "empty" then
- m.__index = f_empty
- elseif f == "key" then
- m.__index = f_self
- else
- m.__index = f
- end
+local function collect(list,collected,c)
+ local dt=list.dt
+ if dt then
+ local en=0
+ for k=1,#dt do
+ local dk=dt[k]
+ if dk.tg then
+ c=c+1
+ collected[c]=dk
+ dk.ni=k
+ en=en+1
+ dk.ei=en
+ c=collect(dk,collected,c)
+ end
+ end
+ list.en=en
+ end
+ return c
+end
+apply_axis['descendant-or-self']=function(list)
+ local collected,c={},0
+ for l=1,#list do
+ local ll=list[l]
+ if ll.special~=true then
+ c=c+1
+ collected[c]=ll
+ end
+ c=collect(ll,collected,c)
+ end
+ return collected
+end
+apply_axis['ancestor']=function(list)
+ local collected,c={},0
+ for l=1,#list do
+ local ll=list[l]
+ while ll do
+ ll=ll.__p__
+ if ll then
+ c=c+1
+ collected[c]=ll
+ end
+ end
+ end
+ return collected
+end
+apply_axis['ancestor-or-self']=function(list)
+ local collected,c={},0
+ for l=1,#list do
+ local ll=list[l]
+ c=c+1
+ collected[c]=ll
+ while ll do
+ ll=ll.__p__
+ if ll then
+ c=c+1
+ collected[c]=ll
+ end
+ end
+ end
+ return collected
+end
+apply_axis['parent']=function(list)
+ local collected,c={},0
+ for l=1,#list do
+ local pl=list[l].__p__
+ if pl then
+ c=c+1
+ collected[c]=pl
+ end
+ end
+ return collected
+end
+apply_axis['attribute']=function(list)
+ return {}
+end
+apply_axis['namespace']=function(list)
+ return {}
+end
+apply_axis['following']=function(list)
+ return {}
+end
+apply_axis['preceding']=function(list)
+ return {}
+end
+apply_axis['following-sibling']=function(list)
+ local collected,c={},0
+ for l=1,#list do
+ local ll=list[l]
+ local p=ll.__p__
+ local d=p.dt
+ for i=ll.ni+1,#d do
+ local di=d[i]
+ if type(di)=="table" then
+ c=c+1
+ collected[c]=di
+ end
+ end
+ end
+ return collected
+end
+apply_axis['preceding-sibling']=function(list)
+ local collected,c={},0
+ for l=1,#list do
+ local ll=list[l]
+ local p=ll.__p__
+ local d=p.dt
+ for i=1,ll.ni-1 do
+ local di=d[i]
+ if type(di)=="table" then
+ c=c+1
+ collected[c]=di
+ end
+ end
+ end
+ return collected
+end
+apply_axis['reverse-sibling']=function(list)
+ local collected,c={},0
+ for l=1,#list do
+ local ll=list[l]
+ local p=ll.__p__
+ local d=p.dt
+ for i=ll.ni-1,1,-1 do
+ local di=d[i]
+ if type(di)=="table" then
+ c=c+1
+ collected[c]=di
+ end
+ end
+ end
+ return collected
+end
+apply_axis['auto-descendant-or-self']=apply_axis['descendant-or-self']
+apply_axis['auto-descendant']=apply_axis['descendant']
+apply_axis['auto-child']=apply_axis['child']
+apply_axis['auto-self']=apply_axis['self']
+apply_axis['initial-child']=apply_axis['child']
+local function apply_nodes(list,directive,nodes)
+ local maxn=#nodes
+ if maxn==3 then
+ local nns,ntg=nodes[2],nodes[3]
+ if not nns and not ntg then
+ if directive then
+ return list
+ else
+ return {}
+ end
else
- if f == "empty" then
- setmetatable(t, t_empty)
- elseif f == "key" then
- setmetatable(t, t_self)
- else
- setmetatable(t,{ __index = f })
- end
- end
- return t
-end
-
-function table.setmetatablenewindex(t,f)
- local m = getmetatable(t)
- if m then
- if f == "ignore" then
- m.__newindex = f_ignore
- else
- m.__newindex = f
+ local collected,c,m,p={},0,0,nil
+ if not nns then
+ for l=1,#list do
+ local ll=list[l]
+ local ltg=ll.tg
+ if ltg then
+ if directive then
+ if ntg==ltg then
+ local llp=ll.__p__;if llp~=p then p,m=llp,1 else m=m+1 end
+ c=c+1
+ collected[c],ll.mi=ll,m
+ end
+ elseif ntg~=ltg then
+ local llp=ll.__p__;if llp~=p then p,m=llp,1 else m=m+1 end
+ c=c+1
+ collected[c],ll.mi=ll,m
+ end
+ end
+ end
+ elseif not ntg then
+ for l=1,#list do
+ local ll=list[l]
+ local lns=ll.rn or ll.ns
+ if lns then
+ if directive then
+ if lns==nns then
+ local llp=ll.__p__;if llp~=p then p,m=llp,1 else m=m+1 end
+ c=c+1
+ collected[c],ll.mi=ll,m
+ end
+ elseif lns~=nns then
+ local llp=ll.__p__;if llp~=p then p,m=llp,1 else m=m+1 end
+ c=c+1
+ collected[c],ll.mi=ll,m
+ end
+ end
+ end
+ else
+ for l=1,#list do
+ local ll=list[l]
+ local ltg=ll.tg
+ if ltg then
+ local lns=ll.rn or ll.ns
+ local ok=ltg==ntg and lns==nns
+ if directive then
+ if ok then
+ local llp=ll.__p__;if llp~=p then p,m=llp,1 else m=m+1 end
+ c=c+1
+ collected[c],ll.mi=ll,m
+ end
+ elseif not ok then
+ local llp=ll.__p__;if llp~=p then p,m=llp,1 else m=m+1 end
+ c=c+1
+ collected[c],ll.mi=ll,m
+ end
+ end
+ end
+ end
+ return collected
+ end
+ else
+ local collected,c,m,p={},0,0,nil
+ for l=1,#list do
+ local ll=list[l]
+ local ltg=ll.tg
+ if ltg then
+ local lns=ll.rn or ll.ns
+ local ok=false
+ for n=1,maxn,3 do
+ local nns,ntg=nodes[n+1],nodes[n+2]
+ ok=(not ntg or ltg==ntg) and (not nns or lns==nns)
+ if ok then
+ break
+ end
end
- else
- if f == "ignore" then
- setmetatable(t, t_ignore)
- else
- setmetatable(t,{ __newindex = f })
+ if directive then
+ if ok then
+ local llp=ll.__p__;if llp~=p then p,m=llp,1 else m=m+1 end
+ c=c+1
+ collected[c],ll.mi=ll,m
+ end
+ elseif not ok then
+ local llp=ll.__p__;if llp~=p then p,m=llp,1 else m=m+1 end
+ c=c+1
+ collected[c],ll.mi=ll,m
end
+ end
end
- return t
+ return collected
+ end
end
-
-function table.setmetatablecall(t,f)
- local m = getmetatable(t)
- if m then
- m.__call = f
+local quit_expression=false
+local function apply_expression(list,expression,order)
+ local collected,c={},0
+ quit_expression=false
+ for l=1,#list do
+ local ll=list[l]
+ if expression(list,ll,l,order) then
+ c=c+1
+ collected[c]=ll
+ end
+ if quit_expression then
+ break
+ end
+ end
+ return collected
+end
+local P,V,C,Cs,Cc,Ct,R,S,Cg,Cb=lpeg.P,lpeg.V,lpeg.C,lpeg.Cs,lpeg.Cc,lpeg.Ct,lpeg.R,lpeg.S,lpeg.Cg,lpeg.Cb
+local spaces=S(" \n\r\t\f")^0
+local lp_space=S(" \n\r\t\f")
+local lp_any=P(1)
+local lp_noequal=P("!=")/"~="+P("<=")+P(">=")+P("==")
+local lp_doequal=P("=")/"=="
+local lp_or=P("|")/" or "
+local lp_and=P("&")/" and "
+local lp_builtin=P (
+ P("text")/"(ll.dt[1] or '')"+
+ P("content")/"ll.dt"+
+ P("name")/"((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)"+P("tag")/"ll.tg"+P("position")/"l"+
+ P("firstindex")/"1"+P("lastindex")/"(#ll.__p__.dt or 1)"+P("firstelement")/"1"+P("lastelement")/"(ll.__p__.en or 1)"+P("first")/"1"+P("last")/"#list"+P("rootposition")/"order"+P("order")/"order"+P("element")/"(ll.ei or 1)"+P("index")/"(ll.ni or 1)"+P("match")/"(ll.mi or 1)"+
+ P("ns")/"ll.ns"
+ )*((spaces*P("(")*spaces*P(")"))/"")
+local lp_attribute=(P("@")+P("attribute::"))/""*Cc("(ll.at and ll.at['")*((R("az","AZ")+S("-_:"))^1)*Cc("'])")
+lp_fastpos_p=P("+")^0*R("09")^1*P(-1)/"l==%0"
+lp_fastpos_n=P("-")*R("09")^1*P(-1)/"(%0<0 and (#list+%0==l))"
+local lp_fastpos=lp_fastpos_n+lp_fastpos_p
+local lp_reserved=C("and")+C("or")+C("not")+C("div")+C("mod")+C("true")+C("false")
+local lp_lua_function=Cs((R("az","AZ","__")^1*(P(".")*R("az","AZ","__")^1)^1)*("("))/"%0"
+local lp_function=C(R("az","AZ","__")^1)*P("(")/function(t)
+ if expressions[t] then
+ return "expr."..t.."("
+ else
+ return "expr.error("
+ end
+end
+local lparent=P("(")
+local rparent=P(")")
+local noparent=1-(lparent+rparent)
+local nested=P{lparent*(noparent+V(1))^0*rparent}
+local value=P(lparent*C((noparent+nested)^0)*rparent)
+local lp_child=Cc("expr.child(ll,'")*R("az","AZ","--","__")^1*Cc("')")
+local lp_number=S("+-")*R("09")^1
+local lp_string=Cc("'")*R("az","AZ","--","__")^1*Cc("'")
+local lp_content=(P("'")*(1-P("'"))^0*P("'")+P('"')*(1-P('"'))^0*P('"'))
+local cleaner
+local lp_special=(C(P("name")+P("text")+P("tag")+P("count")+P("child")))*value/function(t,s)
+ if expressions[t] then
+ s=s and s~="" and lpegmatch(cleaner,s)
+ if s and s~="" then
+ return "expr."..t.."(ll,"..s..")"
else
- setmetatable(t,{ __call = f })
+ return "expr."..t.."(ll)"
end
- return t
+ else
+ return "expr.error("..t..")"
+ end
end
-
-function table.setmetatablekey(t,key,value)
- local m = getmetatable(t)
- if not m then
- m = { }
- setmetatable(t,m)
+local content=lp_builtin+lp_attribute+lp_special+lp_noequal+lp_doequal+lp_or+lp_and+lp_reserved+lp_lua_function+lp_function+lp_content+
+ lp_child+lp_any
+local converter=Cs (
+ lp_fastpos+(P { lparent*(V(1))^0*rparent+content } )^0
+)
+cleaner=Cs ((
+ lp_reserved+lp_number+lp_string+1 )^1 )
+local template_e=[[
+ local expr = xml.expressions
+ return function(list,ll,l,order)
+ return %s
end
- m[key] = value
- return t
+]]
+local template_f_y=[[
+ local finalizer = xml.finalizers['%s']['%s']
+ return function(collection)
+ return finalizer(collection,%s)
+ end
+]]
+local template_f_n=[[
+ return xml.finalizers['%s']['%s']
+]]
+local register_self={ kind="axis",axis="self" }
+local register_parent={ kind="axis",axis="parent" }
+local register_descendant={ kind="axis",axis="descendant" }
+local register_child={ kind="axis",axis="child" }
+local register_descendant_or_self={ kind="axis",axis="descendant-or-self" }
+local register_root={ kind="axis",axis="root" }
+local register_ancestor={ kind="axis",axis="ancestor" }
+local register_ancestor_or_self={ kind="axis",axis="ancestor-or-self" }
+local register_attribute={ kind="axis",axis="attribute" }
+local register_namespace={ kind="axis",axis="namespace" }
+local register_following={ kind="axis",axis="following" }
+local register_following_sibling={ kind="axis",axis="following-sibling" }
+local register_preceding={ kind="axis",axis="preceding" }
+local register_preceding_sibling={ kind="axis",axis="preceding-sibling" }
+local register_reverse_sibling={ kind="axis",axis="reverse-sibling" }
+local register_auto_descendant_or_self={ kind="axis",axis="auto-descendant-or-self" }
+local register_auto_descendant={ kind="axis",axis="auto-descendant" }
+local register_auto_self={ kind="axis",axis="auto-self" }
+local register_auto_child={ kind="axis",axis="auto-child" }
+local register_initial_child={ kind="axis",axis="initial-child" }
+local register_all_nodes={ kind="nodes",nodetest=true,nodes={ true,false,false } }
+local skip={}
+local function errorrunner_e(str,cnv)
+ if not skip[str] then
+ report_lpath("error in expression: %s => %s",str,cnv)
+ skip[str]=cnv or str
+ end
+ return false
end
-
-function table.getmetatablekey(t,key,value)
- local m = getmetatable(t)
- return m and m[key]
+local function errorrunner_f(str,arg)
+ report_lpath("error in finalizer: %s(%s)",str,arg or "")
+ return false
end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['util-mrg'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- hm, quite unreadable
-
-local gsub, format = string.gsub, string.format
-local concat = table.concat
-local type, next = type, next
-
-utilities = utilities or {}
-utilities.merger = utilities.merger or { } -- maybe mergers
-utilities.report = logs and logs.reporter("system") or print
-
-local merger = utilities.merger
-
-merger.strip_comment = true
-
-local m_begin_merge = "begin library merge"
-local m_end_merge = "end library merge"
-local m_begin_closure = "do -- create closure to overcome 200 locals limit"
-local m_end_closure = "end -- of closure"
-
-local m_pattern =
- "%c+" ..
- "%-%-%s+" .. m_begin_merge ..
- "%c+(.-)%c+" ..
- "%-%-%s+" .. m_end_merge ..
- "%c+"
-
-local m_format =
- "\n\n-- " .. m_begin_merge ..
- "\n%s\n" ..
- "-- " .. m_end_merge .. "\n\n"
-
-local m_faked =
- "-- " .. "created merged file" .. "\n\n" ..
- "-- " .. m_begin_merge .. "\n\n" ..
- "-- " .. m_end_merge .. "\n\n"
-
-local function self_fake()
- return m_faked
+local function register_nodes(nodetest,nodes)
+ return { kind="nodes",nodetest=nodetest,nodes=nodes }
end
-
-local function self_nothing()
- return ""
-end
-
-local function self_load(name)
- local data = io.loaddata(name) or ""
- if data == "" then
- utilities.report("merge: unknown file %s",name)
- else
- utilities.report("merge: inserting %s",name)
- end
- return data or ""
-end
-
-local function self_save(name, data)
- if data ~= "" then
- if merger.strip_comment then
- -- saves some 20K
- local n = #data
- data = gsub(data,"%-%-~[^\n\r]*[\r\n]","")
- utilities.report("merge: %s bytes of comment stripped, %s bytes of code left",n-#data,#data)
- end
- io.savedata(name,data)
- utilities.report("merge: saving %s",name)
- end
-end
-
-local function self_swap(data,code)
- return data ~= "" and (gsub(data,m_pattern, function() return format(m_format,code) end, 1)) or ""
-end
-
-local function self_libs(libs,list)
- local result, f, frozen, foundpath = { }, nil, false, nil
- result[#result+1] = "\n"
- if type(libs) == 'string' then libs = { libs } end
- if type(list) == 'string' then list = { list } end
- for i=1,#libs do
- local lib = libs[i]
- for j=1,#list do
- local pth = gsub(list[j],"\\","/") -- file.clean_path
- utilities.report("merge: checking library path %s",pth)
- local name = pth .. "/" .. lib
- if lfs.isfile(name) then
- foundpath = pth
- end
- end
- if foundpath then break end
- end
- if foundpath then
- utilities.report("merge: using library path %s",foundpath)
- local right, wrong = { }, { }
- for i=1,#libs do
- local lib = libs[i]
- local fullname = foundpath .. "/" .. lib
- if lfs.isfile(fullname) then
- utilities.report("merge: using library %s",fullname)
- right[#right+1] = lib
- result[#result+1] = m_begin_closure
- result[#result+1] = io.loaddata(fullname,true)
- result[#result+1] = m_end_closure
- else
- utilities.report("merge: skipping library %s",fullname)
- wrong[#wrong+1] = lib
- end
- end
- if #right > 0 then
- utilities.report("merge: used libraries: %s",concat(right," "))
- end
- if #wrong > 0 then
- utilities.report("merge: skipped libraries: %s",concat(wrong," "))
- end
- else
- utilities.report("merge: no valid library path found")
- end
- return concat(result, "\n\n")
-end
-
-function merger.selfcreate(libs,list,target)
- if target then
- self_save(target,self_swap(self_fake(),self_libs(libs,list)))
- end
-end
-
-function merger.selfmerge(name,libs,list,target)
- self_save(target or name,self_swap(self_load(name),self_libs(libs,list)))
-end
-
-function merger.selfclean(name)
- self_save(name,self_swap(self_load(name),self_nothing()))
-end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['util-lua'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-utilities = utilities or {}
-utilities.lua = utilities.lua or { }
-utilities.report = logs and logs.reporter("system") or print
-
-local function stupidcompile(luafile,lucfile)
- local data = io.loaddata(luafile)
- if data and data ~= "" then
- data = string.dump(data)
- if data and data ~= "" then
- io.savedata(lucfile,data)
- end
- end
-end
-
-function utilities.lua.compile(luafile,lucfile,cleanup,strip,fallback) -- defaults: cleanup=false strip=true
- utilities.report("lua: compiling %s into %s",luafile,lucfile)
- os.remove(lucfile)
- local command = "-o " .. string.quoted(lucfile) .. " " .. string.quoted(luafile)
- if strip ~= false then
- command = "-s " .. command
- end
- local done = os.spawn("texluac " .. command) == 0 -- or os.spawn("luac " .. command) == 0
- if not done and fallback then
- utilities.report("lua: dumping %s into %s (unstripped)",luafile,lucfile)
- stupidcompile(luafile,lucfile) -- maybe use the stripper we have elsewhere
- cleanup = false -- better see how worse it is
- end
- if done and cleanup == true and lfs.isfile(lucfile) and lfs.isfile(luafile) then
- utilities.report("lua: removing %s",luafile)
- os.remove(luafile)
- end
- return done
+local function register_expression(expression)
+ local converted=lpegmatch(converter,expression)
+ local runner=load(format(template_e,converted))
+ runner=(runner and runner()) or function() errorrunner_e(expression,converted) end
+ return { kind="expression",expression=expression,converted=converted,evaluator=runner }
end
-
-
-
-
-
-
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['util-prs'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local P, R, V, C, Ct, Cs, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Carg
-local lpegmatch = lpeg.match
-local concat, format, gmatch, find = table.concat, string.format, string.gmatch, string.find
-local tostring, type, next = tostring, type, next
-
-utilities = utilities or {}
-utilities.parsers = utilities.parsers or { }
-local parsers = utilities.parsers
-parsers.patterns = parsers.patterns or { }
-
-local setmetatableindex = table.setmetatableindex
-local sortedhash = table.sortedhash
-
--- we could use a Cf Cg construct
-
-local escape, left, right = P("\\"), P('{'), P('}')
-
-lpeg.patterns.balanced = P {
- [1] = ((escape * (left+right)) + (1 - (left+right)) + V(2))^0,
- [2] = left * V(1) * right
+local function register_finalizer(protocol,name,arguments)
+ local runner
+ if arguments and arguments~="" then
+ runner=load(format(template_f_y,protocol or xml.defaultprotocol,name,arguments))
+ else
+ runner=load(format(template_f_n,protocol or xml.defaultprotocol,name))
+ end
+ runner=(runner and runner()) or function() errorrunner_f(name,arguments) end
+ return { kind="finalizer",name=name,arguments=arguments,finalizer=runner }
+end
+local expression=P { "ex",
+ ex="["*C((V("sq")+V("dq")+(1-S("[]"))+V("ex"))^0)*"]",
+ sq="'"*(1-S("'"))^0*"'",
+ dq='"'*(1-S('"'))^0*'"',
}
-
-local space = P(' ')
-local equal = P("=")
-local comma = P(",")
-local lbrace = P("{")
-local rbrace = P("}")
-local nobrace = 1 - (lbrace+rbrace)
-local nested = P { lbrace * (nobrace + V(1))^0 * rbrace }
-local spaces = space^0
-local argument = Cs((lbrace/"") * ((nobrace + nested)^0) * (rbrace/""))
-local content = (1-P(-1))^0
-
-lpeg.patterns.nested = nested -- no capture
-lpeg.patterns.argument = argument -- argument after e.g. =
-lpeg.patterns.content = content -- rest after e.g =
-
-local value = P(lbrace * C((nobrace + nested)^0) * rbrace) + C((nested + (1-comma))^0)
-
-local key = C((1-equal-comma)^1)
-local pattern_a = (space+comma)^0 * (key * equal * value + key * C(""))
-local pattern_c = (space+comma)^0 * (key * equal * value)
-
-local key = C((1-space-equal-comma)^1)
-local pattern_b = spaces * comma^0 * spaces * (key * ((spaces * equal * spaces * value) + C("")))
-
--- "a=1, b=2, c=3, d={a{b,c}d}, e=12345, f=xx{a{b,c}d}xx, g={}" : outer {} removes, leading spaces ignored
-
-local hash = { }
-
-local function set(key,value)
- hash[key] = value
-end
-
-local function set(key,value)
- hash[key] = value
-end
-
-local pattern_a_s = (pattern_a/set)^1
-local pattern_b_s = (pattern_b/set)^1
-local pattern_c_s = (pattern_c/set)^1
-
-parsers.patterns.settings_to_hash_a = pattern_a_s
-parsers.patterns.settings_to_hash_b = pattern_b_s
-parsers.patterns.settings_to_hash_c = pattern_c_s
-
-function parsers.make_settings_to_hash_pattern(set,how)
- if how == "strict" then
- return (pattern_c/set)^1
- elseif how == "tolerant" then
- return (pattern_b/set)^1
- else
- return (pattern_a/set)^1
- end
-end
-
-function parsers.settings_to_hash(str,existing)
- if str and str ~= "" then
- hash = existing or { }
- lpegmatch(pattern_a_s,str)
- return hash
- else
- return { }
- end
-end
-
-function parsers.settings_to_hash_tolerant(str,existing)
- if str and str ~= "" then
- hash = existing or { }
- lpegmatch(pattern_b_s,str)
- return hash
- else
- return { }
- end
-end
-
-function parsers.settings_to_hash_strict(str,existing)
- if str and str ~= "" then
- hash = existing or { }
- lpegmatch(pattern_c_s,str)
- return next(hash) and hash
- else
- return nil
- end
-end
-
-local separator = comma * space^0
-local value = P(lbrace * C((nobrace + nested)^0) * rbrace) + C((nested + (1-comma))^0)
-local pattern = Ct(value*(separator*value)^0)
-
--- "aap, {noot}, mies" : outer {} removes, leading spaces ignored
-
-parsers.patterns.settings_to_array = pattern
-
--- we could use a weak table as cache
-
-function parsers.settings_to_array(str,strict)
- if not str or str == "" then
- return { }
- elseif strict then
- if find(str,"{") then
- return lpegmatch(pattern,str)
- else
- return { str }
- end
- else
- return lpegmatch(pattern,str)
- end
-end
-
-local function set(t,v)
- t[#t+1] = v
-end
-
-local value = P(Carg(1)*value) / set
-local pattern = value*(separator*value)^0 * Carg(1)
-
-function parsers.add_settings_to_array(t,str)
- return lpegmatch(pattern,str,nil,t)
-end
-
-function parsers.hash_to_string(h,separator,yes,no,strict,omit)
- if h then
- local t, tn, s = { }, 0, table.sortedkeys(h)
- omit = omit and table.tohash(omit)
- for i=1,#s do
- local key = s[i]
- if not omit or not omit[key] then
- local value = h[key]
- if type(value) == "boolean" then
- if yes and no then
- if value then
- tn = tn + 1
- t[tn] = key .. '=' .. yes
- elseif not strict then
- tn = tn + 1
- t[tn] = key .. '=' .. no
- end
- elseif value or not strict then
- tn = tn + 1
- t[tn] = key .. '=' .. tostring(value)
- end
- else
- tn = tn + 1
- t[tn] = key .. '=' .. value
- end
- end
- end
- return concat(t,separator or ",")
- else
- return ""
- end
-end
-
-function parsers.array_to_string(a,separator)
- if a then
- return concat(a,separator or ",")
- else
- return ""
- end
-end
-
-function parsers.settings_to_set(str,t) -- tohash? -- todo: lpeg -- duplicate anyway
- t = t or { }
--- for s in gmatch(str,"%s*([^, ]+)") do -- space added
- for s in gmatch(str,"[^, ]+") do -- space added
- t[s] = true
- end
- return t
-end
-
-function parsers.simple_hash_to_string(h, separator)
- local t, tn = { }, 0
- for k, v in sortedhash(h) do
- if v then
- tn = tn + 1
- t[tn] = k
- end
- end
- return concat(t,separator or ",")
-end
-
-local value = lbrace * C((nobrace + nested)^0) * rbrace
-local pattern = Ct((space + value)^0)
-
-function parsers.arguments_to_table(str)
- return lpegmatch(pattern,str)
-end
-
--- temporary here (unoptimized)
-
-function parsers.getparameters(self,class,parentclass,settings)
- local sc = self[class]
- if not sc then
- sc = { }
- self[class] = sc
- if parentclass then
- local sp = self[parentclass]
- if not sp then
- sp = { }
- self[parentclass] = sp
- end
- setmetatableindex(sc,sp)
- end
- end
- parsers.settings_to_hash(settings,sc)
-end
-
-function parsers.listitem(str)
- return gmatch(str,"[^, ]+")
-end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['util-fmt'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
+local arguments=P { "ar",
+ ar="("*Cs((V("sq")+V("dq")+V("nq")+P(1-P(")")))^0)*")",
+ nq=((1-S("),'\""))^1)/function(s) return format("%q",s) end,
+ sq=P("'")*(1-P("'"))^0*P("'"),
+ dq=P('"')*(1-P('"'))^0*P('"'),
}
-
-utilities = utilities or { }
-utilities.formatters = utilities.formatters or { }
-local formatters = utilities.formatters
-
-local concat, format = table.concat, string.format
-local tostring, type = tostring, type
-local strip = string.strip
-
-local P, R, Cs = lpeg.P, lpeg.R, lpeg.Cs
-local lpegmatch = lpeg.match
-
--- temporary here
-
-local digit = R("09")
-local period = P(".")
-local zero = P("0")
-local trailingzeros = zero^0 * -digit -- suggested by Roberto R
-local case_1 = period * trailingzeros / ""
-local case_2 = period * (digit - trailingzeros)^1 * (trailingzeros / "")
-local number = digit^1 * (case_1 + case_2)
-local stripper = Cs((number + 1)^0)
-
-
-lpeg.patterns.stripzeros = stripper
-
-function formatters.stripzeros(str)
- return lpegmatch(stripper,str)
-end
-
-function formatters.formatcolumns(result,between)
- if result and #result > 0 then
- between = between or " "
- local widths, numbers = { }, { }
- local first = result[1]
- local n = #first
- for i=1,n do
- widths[i] = 0
- end
- for i=1,#result do
- local r = result[i]
- for j=1,n do
- local rj = r[j]
- local tj = type(rj)
- if tj == "number" then
- numbers[j] = true
- end
- if tj ~= "string" then
- rj = tostring(rj)
- r[j] = rj
- end
- local w = #rj
- if w > widths[j] then
- widths[j] = w
- end
- end
- end
- for i=1,n do
- local w = widths[i]
- if numbers[i] then
- if w > 80 then
- widths[i] = "%s" .. between
- else
- widths[i] = "%0" .. w .. "i" .. between
- end
- else
- if w > 80 then
- widths[i] = "%s" .. between
- elseif w > 0 then
- widths[i] = "%-" .. w .. "s" .. between
- else
- widths[i] = "%s"
- end
- end
- end
- local template = strip(concat(widths))
- for i=1,#result do
- local str = format(template,unpack(result[i]))
- result[i] = strip(str)
- end
- end
- return result
-end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['util.deb'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
+local function register_error(str)
+ return { kind="error",error=format("unparsed: %s",str) }
+end
+local special_1=P("*")*Cc(register_auto_descendant)*Cc(register_all_nodes)
+local special_2=P("/")*Cc(register_auto_self)
+local special_3=P("")*Cc(register_auto_self)
+local no_nextcolon=P(-1)+#(1-P(":"))
+local no_nextlparent=P(-1)+#(1-P("("))
+local pathparser=Ct { "patterns",
+ patterns=spaces*V("protocol")*spaces*(
+ (V("special")*spaces*P(-1) )+(V("initial")*spaces*V("step")*spaces*(P("/")*spaces*V("step")*spaces)^0 )
+ ),
+ protocol=Cg(V("letters"),"protocol")*P("://")+Cg(Cc(nil),"protocol"),
+ step=((V("shortcuts")+P("/")+V("axis"))*spaces*V("nodes")^0+V("error"))*spaces*V("expressions")^0*spaces*V("finalizer")^0,
+ axis=V("descendant")+V("child")+V("parent")+V("self")+V("root")+V("ancestor")+V("descendant_or_self")+V("following_sibling")+V("following")+V("reverse_sibling")+V("preceding_sibling")+V("preceding")+V("ancestor_or_self")+#(1-P(-1))*Cc(register_auto_child),
+ special=special_1+special_2+special_3,
+ initial=(P("/")*spaces*Cc(register_initial_child))^-1,
+ error=(P(1)^1)/register_error,
+ shortcuts_a=V("s_descendant_or_self")+V("s_descendant")+V("s_child")+V("s_parent")+V("s_self")+V("s_root")+V("s_ancestor"),
+ shortcuts=V("shortcuts_a")*(spaces*"/"*spaces*V("shortcuts_a"))^0,
+ s_descendant_or_self=(P("***/")+P("/"))*Cc(register_descendant_or_self),
+ s_descendant=P("**")*Cc(register_descendant),
+ s_child=P("*")*no_nextcolon*Cc(register_child ),
+ s_parent=P("..")*Cc(register_parent ),
+ s_self=P("." )*Cc(register_self ),
+ s_root=P("^^")*Cc(register_root ),
+ s_ancestor=P("^")*Cc(register_ancestor ),
+ descendant=P("descendant::")*Cc(register_descendant ),
+ child=P("child::")*Cc(register_child ),
+ parent=P("parent::")*Cc(register_parent ),
+ self=P("self::")*Cc(register_self ),
+ root=P('root::')*Cc(register_root ),
+ ancestor=P('ancestor::')*Cc(register_ancestor ),
+ descendant_or_self=P('descendant-or-self::')*Cc(register_descendant_or_self ),
+ ancestor_or_self=P('ancestor-or-self::')*Cc(register_ancestor_or_self ),
+ following=P('following::')*Cc(register_following ),
+ following_sibling=P('following-sibling::')*Cc(register_following_sibling ),
+ preceding=P('preceding::')*Cc(register_preceding ),
+ preceding_sibling=P('preceding-sibling::')*Cc(register_preceding_sibling ),
+ reverse_sibling=P('reverse-sibling::')*Cc(register_reverse_sibling ),
+ nodes=(V("nodefunction")*spaces*P("(")*V("nodeset")*P(")")+V("nodetest")*V("nodeset"))/register_nodes,
+ expressions=expression/register_expression,
+ letters=R("az")^1,
+ name=(1-S("/[]()|:*!"))^1,
+ negate=P("!")*Cc(false),
+ nodefunction=V("negate")+P("not")*Cc(false)+Cc(true),
+ nodetest=V("negate")+Cc(true),
+ nodename=(V("negate")+Cc(true))*spaces*((V("wildnodename")*P(":")*V("wildnodename"))+(Cc(false)*V("wildnodename"))),
+ wildnodename=(C(V("name"))+P("*")*Cc(false))*no_nextlparent,
+ nodeset=spaces*Ct(V("nodename")*(spaces*P("|")*spaces*V("nodename"))^0)*spaces,
+ finalizer=(Cb("protocol")*P("/")^-1*C(V("name"))*arguments*P(-1))/register_finalizer,
}
-
--- the tag is kind of generic and used for functions that are not
--- bound to a variable, like node.new, node.copy etc (contrary to for instance
--- node.has_attribute which is bound to a has_attribute local variable in mkiv)
-
-local debug = require "debug"
-
-local getinfo = debug.getinfo
-local type, next, tostring = type, next, tostring
-local format, find = string.format, string.find
-local is_boolean = string.is_boolean
-
-utilities = utilities or { }
-utilities.debugger = utilities.debugger or { }
-local debugger = utilities.debugger
-
-local counters = { }
-local names = { }
-
--- one
-
-local function hook()
- local f = getinfo(2) -- "nS"
- if f then
- local n = "unknown"
- if f.what == "C" then
- n = f.name or ''
- if not names[n] then
- names[n] = format("%42s",n)
- end
- else
- -- source short_src linedefined what name namewhat nups func
- n = f.name or f.namewhat or f.what
- if not n or n == "" then
- n = "?"
- end
- if not names[n] then
- names[n] = format("%42s : % 5i : %s",n,f.linedefined or 0,f.short_src or "unknown source")
- end
- end
- counters[n] = (counters[n] or 0) + 1
- end
-end
-
-function debugger.showstats(printer,threshold) -- hm, something has changed, rubish now
- printer = printer or texio.write or print
- threshold = threshold or 0
- local total, grandtotal, functions = 0, 0, 0
- local dataset = { }
- for name, count in next, counters do
- dataset[#dataset+1] = { name, count }
- end
- table.sort(dataset,function(a,b) return a[2] == b[2] and b[1] > a[1] or a[2] > b[2] end)
- for i=1,#dataset do
- local d = dataset[i]
- local name = d[1]
- local count = d[2]
- if count > threshold and not find(name,"for generator") then -- move up
- printer(format("%8i %s\n", count, names[name]))
- total = total + count
- end
- grandtotal = grandtotal + count
- functions = functions + 1
- end
- printer("\n")
- printer(format("functions : % 10i\n", functions))
- printer(format("total : % 10i\n", total))
- printer(format("grand total: % 10i\n", grandtotal))
- printer(format("threshold : % 10i\n", threshold))
+xmlpatterns.pathparser=pathparser
+local cache={}
+local function nodesettostring(set,nodetest)
+ local t={}
+ for i=1,#set,3 do
+ local directive,ns,tg=set[i],set[i+1],set[i+2]
+ if not ns or ns=="" then ns="*" end
+ if not tg or tg=="" then tg="*" end
+ tg=(tg=="@rt@" and "[root]") or format("%s:%s",ns,tg)
+ t[i]=(directive and tg) or format("not(%s)",tg)
+ end
+ if nodetest==false then
+ return format("not(%s)",concat(t,"|"))
+ else
+ return concat(t,"|")
+ end
end
-
-function debugger.savestats(filename,threshold)
- local f = io.open(filename,'w')
- if f then
- debugger.showstats(function(str) f:write(str) end,threshold)
- f:close()
- end
-end
-
-function debugger.enable()
- debug.sethook(hook,"c")
-end
-
-function debugger.disable()
- debug.sethook()
-end
-
-
-
-
-
-local is_node = node and node.is_node
-local is_lpeg = lpeg and lpeg.type
-
-function inspect(i) -- global function
- local ti = type(i)
- if ti == "table" then
- table.print(i,"table")
- elseif is_node and is_node(i) then
- table.print(nodes.astable(i),tostring(i))
- elseif is_lpeg and is_lpeg(i) then
- lpeg.print(i)
- else
- print(tostring(i))
- end
-end
-
--- from the lua book:
-
-function traceback()
- local level = 1
- while true do
- local info = debug.getinfo(level, "Sl")
- if not info then
- break
- elseif info.what == "C" then
- print(format("%3i : C function",level))
- else
- print(format("%3i : [%s]:%d",level,info.short_src,info.currentline))
- end
- level = level + 1
- end
-end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['trac-inf'] = {
- version = 1.001,
- comment = "companion to trac-inf.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- As we want to protect the global tables, we no longer store the timing
--- in the tables themselves but in a hidden timers table so that we don't
--- get warnings about assignments. This is more efficient than using rawset
--- and rawget.
-
-local format, lower = string.format, string.lower
-local clock = os.gettimeofday or os.clock -- should go in environment
-local write_nl = texio.write_nl
-
-statistics = statistics or { }
-local statistics = statistics
-
-statistics.enable = true
-statistics.threshold = 0.05
-
-local statusinfo, n, registered, timers = { }, 0, { }, { }
-
-local function hastiming(instance)
- return instance and timers[instance]
-end
-
-local function resettiming(instance)
- timers[instance or "notimer"] = { timing = 0, loadtime = 0 }
-end
-
-local function starttiming(instance)
- local timer = timers[instance or "notimer"]
- if not timer then
- timer = { }
- timers[instance or "notimer"] = timer
- end
- local it = timer.timing
- if not it then
- it = 0
- end
- if it == 0 then
- timer.starttime = clock()
- if not timer.loadtime then
- timer.loadtime = 0
- end
- end
- timer.timing = it + 1
-end
-
-local function stoptiming(instance, report)
- local timer = timers[instance or "notimer"]
- local it = timer.timing
- if it > 1 then
- timer.timing = it - 1
- else
- local starttime = timer.starttime
- if starttime then
- local stoptime = clock()
- local loadtime = stoptime - starttime
- timer.stoptime = stoptime
- timer.loadtime = timer.loadtime + loadtime
- if report then
- statistics.report("load time %0.3f",loadtime)
- end
- timer.timing = 0
- return loadtime
- end
- end
- return 0
-end
-
-local function elapsedtime(instance)
- local timer = timers[instance or "notimer"]
- return format("%0.3f",timer and timer.loadtime or 0)
-end
-
-local function elapsedindeed(instance)
- local timer = timers[instance or "notimer"]
- return (timer and timer.loadtime or 0) > statistics.threshold
-end
-
-local function elapsedseconds(instance,rest) -- returns nil if 0 seconds
- if elapsedindeed(instance) then
- return format("%s seconds %s", elapsedtime(instance),rest or "")
- end
-end
-
-statistics.hastiming = hastiming
-statistics.resettiming = resettiming
-statistics.starttiming = starttiming
-statistics.stoptiming = stoptiming
-statistics.elapsedtime = elapsedtime
-statistics.elapsedindeed = elapsedindeed
-statistics.elapsedseconds = elapsedseconds
-
--- general function
-
-function statistics.register(tag,fnc)
- if statistics.enable and type(fnc) == "function" then
- local rt = registered[tag] or (#statusinfo + 1)
- statusinfo[rt] = { tag, fnc }
- registered[tag] = rt
- if #tag > n then n = #tag end
- end
-end
-
-function statistics.show(reporter)
- if statistics.enable then
- if not reporter then reporter = function(tag,data,n) write_nl(tag .. " " .. data) end end
- -- this code will move
- local register = statistics.register
- register("luatex banner", function()
- return lower(status.banner)
- end)
- register("control sequences", function()
- return format("%s of %s + %s", status.cs_count, status.hash_size,status.hash_extra)
- end)
- register("callbacks", function()
- local total, indirect = status.callbacks or 0, status.indirect_callbacks or 0
- return format("%s direct, %s indirect, %s total", total-indirect, indirect, total)
- end)
- collectgarbage("collect")
- register("current memory usage", statistics.memused)
- register("runtime",statistics.runtime)
- for i=1,#statusinfo do
- local s = statusinfo[i]
- local r = s[2]()
- if r then
- reporter(s[1],r,n)
- end
- end
- write_nl("") -- final newline
- statistics.enable = false
- end
-end
-
-local template, report_statistics, nn = nil, nil, 0 -- we only calcute it once
-
-function statistics.showjobstat(tag,data,n)
- if not logs then
- -- sorry
- elseif type(data) == "table" then
- for i=1,#data do
- statistics.showjobstat(tag,data[i],n)
- end
- else
- if not template or n > nn then
- template, n = format("%%-%ss - %%s",n), nn
- report_statistics = logs.reporter("mkiv lua stats")
- end
- report_statistics(format(template,tag,data))
- end
-end
-
-function statistics.memused() -- no math.round yet -)
- local round = math.round or math.floor
- return format("%s MB (ctx: %s MB)",round(collectgarbage("count")/1000), round(status.luastate_bytes/1000000))
-end
-
-starttiming(statistics)
-
-function statistics.formatruntime(runtime) -- indirect so it can be overloaded and
- return format("%s seconds", runtime) -- indeed that happens in cure-uti.lua
-end
-
-function statistics.runtime()
- stoptiming(statistics)
- return statistics.formatruntime(elapsedtime(statistics))
-end
-
-function statistics.timed(action,report)
- report = report or logs.reporter("system")
- starttiming("run")
- action()
- stoptiming("run")
- report("total runtime: %s",elapsedtime("run"))
-end
-
--- where, not really the best spot for this:
-
-commands = commands or { }
-
-function commands.resettimer(name)
- resettiming(name or "whatever")
- starttiming(name or "whatever")
-end
-
-function commands.elapsedtime(name)
- stoptiming(name or "whatever")
- context(elapsedtime(name or "whatever"))
-end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['trac-set'] = { -- might become util-set.lua
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local type, next, tostring = type, next, tostring
-local concat = table.concat
-local format, find, lower, gsub, escapedpattern = string.format, string.find, string.lower, string.gsub, string.escapedpattern
-local is_boolean = string.is_boolean
-local settings_to_hash = utilities.parsers.settings_to_hash
-local allocate = utilities.storage.allocate
-
-utilities = utilities or { }
-local utilities = utilities
-utilities.setters = utilities.setters or { }
-local setters = utilities.setters
-
-local data = { } -- maybe just local
-
--- We can initialize from the cnf file. This is sort of tricky as
--- later defined setters also need to be initialized then. If set
--- this way, we need to ensure that they are not reset later on.
-
-local trace_initialize = false -- only for testing during development
-
-function setters.initialize(filename,name,values) -- filename only for diagnostics
- local setter = data[name]
- if setter then
- local data = setter.data
- if data then
- for key, value in next, values do
- -- key = gsub(key,"_",".")
- value = is_boolean(value,value)
- local functions = data[key]
- if functions then
- if #functions > 0 and not functions.value then
- if trace_initialize then
- setter.report("executing %s (%s -> %s)",key,filename,tostring(value))
- end
- for i=1,#functions do
- functions[i](value)
- end
- functions.value = value
- else
- if trace_initialize then
- setter.report("skipping %s (%s -> %s)",key,filename,tostring(value))
- end
- end
- else
- -- we do a simple preregistration i.e. not in the
- -- list as it might be an obsolete entry
- functions = { default = value }
- data[key] = functions
- if trace_initialize then
- setter.report("storing %s (%s -> %s)",key,filename,tostring(value))
- end
- end
- end
- return true
- end
- end
-end
-
--- user interface code
-
-local function set(t,what,newvalue)
- local data, done = t.data, t.done
- if type(what) == "string" then
- what = settings_to_hash(what) -- inefficient but ok
- end
- if type(what) ~= "table" then
- return
- end
- if not done then -- catch ... why not set?
- done = { }
- t.done = done
- end
- for w, value in next, what do
- if value == "" then
- value = newvalue
- elseif not value then
- value = false -- catch nil
- else
- value = is_boolean(value,value)
- end
- w = "^" .. escapedpattern(w,true) .. "$" -- new: anchored
- for name, functions in next, data do
- if done[name] then
- -- prevent recursion due to wildcards
- elseif find(name,w) then
- done[name] = true
- for i=1,#functions do
- functions[i](value)
- end
- functions.value = value
- end
- end
- end
-end
-
-local function reset(t)
- for name, functions in next, t.data do
- for i=1,#functions do
- functions[i](false)
- end
- functions.value = false
- end
-end
-
-local function enable(t,what)
- set(t,what,true)
-end
-
-local function disable(t,what)
- local data = t.data
- if not what or what == "" then
- t.done = { }
- reset(t)
- else
- set(t,what,false)
- end
-end
-
-function setters.register(t,what,...)
- local data = t.data
- what = lower(what)
- local functions = data[what]
- if not functions then
- functions = { }
- data[what] = functions
- if trace_initialize then
- t.report("defining %s",what)
- end
- end
- local default = functions.default -- can be set from cnf file
- for _, fnc in next, { ... } do
- local typ = type(fnc)
- if typ == "string" then
- if trace_initialize then
- t.report("coupling %s to %s",what,fnc)
- end
- local s = fnc -- else wrong reference
- fnc = function(value) set(t,s,value) end
- elseif typ ~= "function" then
- fnc = nil
- end
- if fnc then
- functions[#functions+1] = fnc
- -- default: set at command line or in cnf file
- -- value : set in tex run (needed when loading runtime)
- local value = functions.value or default
- if value ~= nil then
- fnc(value)
- functions.value = value
- end
- end
- end
- return false -- so we can use it in an assignment
-end
-
-function setters.enable(t,what)
- local e = t.enable
- t.enable, t.done = enable, { }
- enable(t,what)
- t.enable, t.done = e, { }
-end
-
-function setters.disable(t,what)
- local e = t.disable
- t.disable, t.done = disable, { }
- disable(t,what)
- t.disable, t.done = e, { }
-end
-
-function setters.reset(t)
- t.done = { }
- reset(t)
-end
-
-function setters.list(t) -- pattern
- local list = table.sortedkeys(t.data)
- local user, system = { }, { }
- for l=1,#list do
- local what = list[l]
- if find(what,"^%*") then
- system[#system+1] = what
- else
- user[#user+1] = what
- end
- end
- return user, system
-end
-
-function setters.show(t)
- local category = t.name
- local list = setters.list(t)
- t.report()
- for k=1,#list do
- local name = list[k]
- local functions = t.data[name]
- if functions then
- local value, default, modules = functions.value, functions.default, #functions
- value = value == nil and "unset" or tostring(value)
- default = default == nil and "unset" or tostring(default)
- t.report("%-30s modules: %2i default: %6s value: %6s",name,modules,default,value)
- end
- end
- t.report()
-end
-
--- we could have used a bit of oo and the trackers:enable syntax but
--- there is already a lot of code around using the singular tracker
-
--- we could make this into a module but we also want the rest avaliable
-
-local enable, disable, register, list, show = setters.enable, setters.disable, setters.register, setters.list, setters.show
-
-local function report(setter,...)
- local report = logs and logs.report
- if report then
- report(setter.name,...)
- else -- fallback, as this module is loaded before the logger
- write_nl(format("%-15s : %s\n",setter.name,format(...)))
- end
-end
-
-function setters.new(name)
- local setter -- we need to access it in setter itself
- setter = {
- data = allocate(), -- indexed, but also default and value fields
- name = name,
- report = function(...) report (setter,...) end,
- enable = function(...) enable (setter,...) end,
- disable = function(...) disable (setter,...) end,
- register = function(...) register(setter,...) end,
- list = function(...) list (setter,...) end,
- show = function(...) show (setter,...) end,
- }
- data[name] = setter
- return setter
-end
-
-trackers = setters.new("trackers")
-directives = setters.new("directives")
-experiments = setters.new("experiments")
-
-local t_enable, t_disable, t_report = trackers .enable, trackers .disable, trackers .report
-local d_enable, d_disable, d_report = directives .enable, directives .disable, directives .report
-local e_enable, e_disable, e_report = experiments.enable, experiments.disable, experiments.report
-
--- nice trick: we overload two of the directives related functions with variants that
--- do tracing (itself using a tracker) .. proof of concept
-
-local trace_directives = false local trace_directives = false trackers.register("system.directives", function(v) trace_directives = v end)
-local trace_experiments = false local trace_experiments = false trackers.register("system.experiments", function(v) trace_experiments = v end)
-
-function directives.enable(...)
- if trace_directives then
- d_report("enabling: %s",concat({...}," "))
- end
- d_enable(...)
-end
-
-function directives.disable(...)
- if trace_directives then
- d_report("disabling: %s",concat({...}," "))
- end
- d_disable(...)
-end
-
-function experiments.enable(...)
- if trace_experiments then
- e_report("enabling: %s",concat({...}," "))
- end
- e_enable(...)
-end
-
-function experiments.disable(...)
- if trace_experiments then
- e_report("disabling: %s",concat({...}," "))
- end
- e_disable(...)
-end
-
--- a useful example
-
-directives.register("system.nostatistics", function(v)
- statistics.enable = not v
-end)
-
-directives.register("system.nolibraries", function(v)
- libraries = nil -- we discard this tracing for security
-end)
-
--- experiment
-
-local flags = environment and environment.engineflags
-
-if flags then
- if trackers and flags.trackers then
- setters.initialize("flags","trackers", settings_to_hash(flags.trackers))
- -- t_enable(flags.trackers)
- end
- if directives and flags.directives then
- setters.initialize("flags","directives", settings_to_hash(flags.directives))
- -- d_enable(flags.directives)
- end
-end
-
--- here
-
-if texconfig then
-
- -- this happens too late in ini mode but that is no problem
-
- local function set(k,v)
- v = tonumber(v)
- if v then
- texconfig[k] = v
- end
- end
-
- directives.register("luatex.expanddepth", function(v) set("expand_depth",v) end)
- directives.register("luatex.hashextra", function(v) set("hash_extra",v) end)
- directives.register("luatex.nestsize", function(v) set("nest_size",v) end)
- directives.register("luatex.maxinopen", function(v) set("max_in_open",v) end)
- directives.register("luatex.maxprintline", function(v) set("max_print_line",v) end)
- directives.register("luatex.maxstrings", function(v) set("max_strings",v) end)
- directives.register("luatex.paramsize", function(v) set("param_size",v) end)
- directives.register("luatex.savesize", function(v) set("save_size",v) end)
- directives.register("luatex.stacksize", function(v) set("stack_size",v) end)
-
-end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['trac-log'] = {
- version = 1.001,
- comment = "companion to trac-log.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- todo: less categories, more subcategories (e.g. nodes)
-
-
-local write_nl, write = texio and texio.write_nl or print, texio and texio.write or io.write
-local format, gmatch, find = string.format, string.gmatch, string.find
-local concat, insert, remove = table.concat, table.insert, table.remove
-local escapedpattern = string.escapedpattern
-local texcount = tex and tex.count
-local next, type = next, type
-
-local setmetatableindex = table.setmetatableindex
-
---[[ldx--
-This is a prelude to a more extensive logging module. We no longer
-provide based logging a sparsing is relatively easy anyway.
---ldx]]--
-
-logs = logs or { }
-local logs = logs
-
-local moreinfo = [[
-More information about ConTeXt and the tools that come with it can be found at:
-
-maillist : ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
-webpage : http://www.pragma-ade.nl / http://tex.aanhet.net
-wiki : http://contextgarden.net
-]]
-
--- basic loggers
-
-local function ignore() end
-
-setmetatableindex(logs, function(t,k) t[k] = ignore ; return ignore end)
-
-local report, subreport, status, settarget, setformats, settranslations
-
-local direct, subdirect, writer, pushtarget, poptarget
-
-if tex and (tex.jobname or tex.formatname) then
-
- local valueiskey = { __index = function(t,k) t[k] = k return k end } -- will be helper
-
- local target = "term and log"
-
- logs.flush = io.flush
-
- local formats = { } setmetatable(formats, valueiskey)
- local translations = { } setmetatable(translations,valueiskey)
-
- writer = function(...)
- write_nl(target,...)
- end
-
- newline = function()
- write_nl(target,"\n")
- end
-
- report = function(a,b,c,...)
- if c then
- write_nl(target,format("%-15s > %s\n",translations[a],format(formats[b],c,...)))
- elseif b then
- write_nl(target,format("%-15s > %s\n",translations[a],formats[b]))
- elseif a then
- write_nl(target,format("%-15s >\n", translations[a]))
- else
- write_nl(target,"\n")
- end
- end
-
- direct = function(a,b,c,...)
- if c then
- return format("%-15s > %s",translations[a],format(formats[b],c,...))
- elseif b then
- return format("%-15s > %s",translations[a],formats[b])
- elseif a then
- return format("%-15s >", translations[a])
- else
- return ""
- end
- end
-
- subreport = function(a,s,b,c,...)
- if c then
- write_nl(target,format("%-15s > %s > %s\n",translations[a],translations[s],format(formats[b],c,...)))
- elseif b then
- write_nl(target,format("%-15s > %s > %s\n",translations[a],translations[s],formats[b]))
- elseif a then
- write_nl(target,format("%-15s > %s >\n", translations[a],translations[s]))
- else
- write_nl(target,"\n")
- end
- end
-
- subdirect = function(a,s,b,c,...)
- if c then
- return format("%-15s > %s > %s",translations[a],translations[s],format(formats[b],c,...))
- elseif b then
- return format("%-15s > %s > %s",translations[a],translations[s],formats[b])
- elseif a then
- return format("%-15s > %s >", translations[a],translations[s])
- else
- return ""
- end
- end
-
- status = function(a,b,c,...)
- if c then
- write_nl(target,format("%-15s : %s\n",translations[a],format(formats[b],c,...)))
- elseif b then
- write_nl(target,format("%-15s : %s\n",translations[a],formats[b]))
- elseif a then
- write_nl(target,format("%-15s :\n", translations[a]))
- else
- write_nl(target,"\n")
- end
- end
-
- local targets = {
- logfile = "log",
- log = "log",
- file = "log",
- console = "term",
- terminal = "term",
- both = "term and log",
- }
-
- settarget = function(whereto)
- target = targets[whereto or "both"] or targets.both
- if target == "term" or target == "term and log" then
- logs.flush = io.flush
- else
- logs.flush = ignore
- end
- end
-
- local stack = { }
-
- pushtarget = function(newtarget)
- insert(stack,target)
- settarget(newtarget)
- end
-
- poptarget = function()
- if #stack > 0 then
- settarget(remove(stack))
- end
- end
-
- setformats = function(f)
- formats = f
- end
-
- settranslations = function(t)
- translations = t
- end
-
-else
-
- logs.flush = ignore
-
- writer = write_nl
-
- newline = function()
- write_nl("\n")
- end
-
- report = function(a,b,c,...)
- if c then
- write_nl(format("%-15s | %s",a,format(b,c,...)))
- elseif b then
- write_nl(format("%-15s | %s",a,b))
- elseif a then
- write_nl(format("%-15s |", a))
- else
- write_nl("")
- end
- end
-
- subreport = function(a,sub,b,c,...)
- if c then
- write_nl(format("%-15s | %s | %s",a,sub,format(b,c,...)))
- elseif b then
- write_nl(format("%-15s | %s | %s",a,sub,b))
- elseif a then
- write_nl(format("%-15s | %s |", a,sub))
- else
- write_nl("")
- end
- end
-
- status = function(a,b,c,...) -- not to be used in lua anyway
- if c then
- write_nl(format("%-15s : %s\n",a,format(b,c,...)))
- elseif b then
- write_nl(format("%-15s : %s\n",a,b)) -- b can have %'s
- elseif a then
- write_nl(format("%-15s :\n", a))
- else
- write_nl("\n")
- end
- end
-
- direct = ignore
- subdirect = ignore
-
- settarget = ignore
- pushtarget = ignore
- poptarget = ignore
- setformats = ignore
- settranslations = ignore
-
-end
-
-logs.report = report
-logs.subreport = subreport
-logs.status = status
-logs.settarget = settarget
-logs.pushtarget = pushtarget
-logs.poptarget = poptarget
-logs.setformats = setformats
-logs.settranslations = settranslations
-
-logs.direct = direct
-logs.subdirect = subdirect
-logs.writer = writer
-logs.newline = newline
-
--- installer
-
--- todo: renew (un) locks when a new one is added and wildcard
-
-local data, states = { }, nil
-
-function logs.reporter(category,subcategory)
- local logger = data[category]
- if not logger then
- local state = false
- if states == true then
- state = true
- elseif type(states) == "table" then
- for c, _ in next, states do
- if find(category,c) then
- state = true
- break
- end
- end
- end
- logger = {
- reporters = { },
- state = state,
- }
- data[category] = logger
- end
- local reporter = logger.reporters[subcategory or "default"]
- if not reporter then
- if subcategory then
- reporter = function(...)
- if not logger.state then
- subreport(category,subcategory,...)
- end
- end
- logger.reporters[subcategory] = reporter
- else
- local tag = category
- reporter = function(...)
- if not logger.state then
- report(category,...)
- end
- end
- logger.reporters.default = reporter
- end
- end
- return reporter
-end
-
-logs.new = logs.reporter -- for old times sake
-
--- context specicific: this ends up in the macro stream
-
-local ctxreport = logs.writer
-
-function logs.setmessenger(m)
- ctxreport = m
-end
-
-function logs.messenger(category,subcategory)
- -- we need to avoid catcode mess (todo: fast context)
- if subcategory then
- return function(...)
- ctxreport(subdirect(category,subcategory,...))
- end
- else
- return function(...)
- ctxreport(direct(category,...))
- end
- end
-end
-
--- so far
-
-local function setblocked(category,value)
- if category == true then
- -- lock all
- category, value = "*", true
- elseif category == false then
- -- unlock all
- category, value = "*", false
- elseif value == nil then
- -- lock selective
- value = true
- end
- if category == "*" then
- states = value
- for k, v in next, data do
- v.state = value
- end
- else
- states = utilities.parsers.settings_to_hash(category)
- for c, _ in next, states do
- if data[c] then
- v.state = value
- else
- c = escapedpattern(c,true)
- for k, v in next, data do
- if find(k,c) then
- v.state = value
- end
- end
- end
- end
- end
-end
-
-function logs.disable(category,value)
- setblocked(category,value == nil and true or value)
-end
-
-function logs.enable(category)
- setblocked(category,false)
-end
-
-function logs.categories()
- return table.sortedkeys(data)
-end
-
-function logs.show()
- local n, c, s, max = 0, 0, 0, 0
- for category, v in table.sortedpairs(data) do
- n = n + 1
- local state = v.state
- local reporters = v.reporters
- local nc = #category
- if nc > c then
- c = nc
- end
- for subcategory, _ in next, reporters do
- local ns = #subcategory
- if ns > c then
- s = ns
- end
- local m = nc + ns
- if m > max then
- max = m
- end
- end
- local subcategories = concat(table.sortedkeys(reporters),", ")
- if state == true then
- state = "disabled"
- elseif state == false then
- state = "enabled"
- else
- state = "unknown"
- end
- -- no new here
- report("logging","category: '%s', subcategories: '%s', state: '%s'",category,subcategories,state)
- end
- report("logging","categories: %s, max category: %s, max subcategory: %s, max combined: %s",n,c,s,max)
-end
-
-directives.register("logs.blocked", function(v)
- setblocked(v,true)
-end)
-
-directives.register("logs.target", function(v)
- settarget(v)
-end)
-
--- tex specific loggers (might move elsewhere)
-
-local report_pages = logs.reporter("pages") -- not needed but saves checking when we grep for it
-
-local real, user, sub
-
-function logs.start_page_number()
- real, user, sub = texcount.realpageno, texcount.userpageno, texcount.subpageno
--- real, user, sub = 0, 0, 0
-end
-
-local timing = false
-local starttime = nil
-local lasttime = nil
-
-trackers.register("pages.timing", function(v) -- only for myself (diagnostics)
- starttime = os.clock()
- timing = true
-end)
-
-function logs.stop_page_number() -- the first page can includes the initialization so we omit this in average
- if timing then
- local elapsed, average
- local stoptime = os.clock()
- if not lasttime or real < 2 then
- elapsed = stoptime
- average = stoptime
- starttime = stoptime
- else
- elapsed = stoptime - lasttime
- average = (stoptime - starttime) / (real - 1)
- end
- lasttime = stoptime
- if real > 0 then
- if user > 0 then
- if sub > 0 then
- report_pages("flushing realpage %s, userpage %s, subpage %s, time %0.04f / %0.04f",real,user,sub,elapsed,average)
- else
- report_pages("flushing realpage %s, userpage %s, time %0.04f / %0.04f",real,user,elapsed,average)
- end
- else
- report_pages("flushing realpage %s, time %0.04f / %0.04f",real,elapsed,average)
- end
- else
- report_pages("flushing page, time %0.04f / %0.04f",elapsed,average)
- end
- else
- if real > 0 then
- if user > 0 then
- if sub > 0 then
- report_pages("flushing realpage %s, userpage %s, subpage %s",real,user,sub)
- else
- report_pages("flushing realpage %s, userpage %s",real,user)
- end
- else
- report_pages("flushing realpage %s",real)
- end
- else
- report_pages("flushing page")
- end
- end
- logs.flush()
-end
-
-logs.report_job_stat = statistics and statistics.showjobstat
-
-local report_files = logs.reporter("files")
-
-local nesting = 0
-local verbose = false
-local hasscheme = url.hasscheme
-
--- we don't have show_open and show_close callbacks yet
-
-function logs.show_open(name)
- -- if hasscheme(name) ~= "virtual" then
- -- if verbose then
- -- nesting = nesting + 1
- -- report_files("level %s, opening %s",nesting,name)
- -- else
- -- write(format("(%s",name)) -- tex adds a space
- -- end
- -- end
-end
-
-function logs.show_close(name)
- -- if hasscheme(name) ~= "virtual" then
- -- if verbose then
- -- report_files("level %s, closing %s",nesting,name)
- -- nesting = nesting - 1
- -- else
- -- write(")") -- tex adds a space
- -- end
- -- end
-end
-
-function logs.show_load(name)
- -- if hasscheme(name) ~= "virtual" then
- -- if verbose then
- -- report_files("level %s, loading %s",nesting+1,name)
- -- else
- -- write(format("(%s)",name))
- -- end
- -- end
-end
-
--- there may be scripts out there using this:
-
-local simple = logs.reporter("comment")
-
-logs.simple = simple
-logs.simpleline = simple
-
--- obsolete
-
-function logs.setprogram () end -- obsolete
-function logs.extendbanner() end -- obsolete
-function logs.reportlines () end -- obsolete
-function logs.reportbanner() end -- obsolete
-function logs.reportline () end -- obsolete
-function logs.simplelines () end -- obsolete
-function logs.help () end -- obsolete
-
--- applications
-
-local function reportlines(t,str)
- if str then
- for line in gmatch(str,"(.-)[\n\r]") do
- t.report(line)
- end
- end
-end
-
-local function reportbanner(t)
- local banner = t.banner
- if banner then
- t.report(banner)
- t.report()
- end
-end
-
-local function reportversion(t)
- local banner = t.banner
- if banner then
- t.report(banner)
- end
-end
-
-local function reporthelp(t,...)
- local helpinfo = t.helpinfo
- if type(helpinfo) == "string" then
- reportlines(t,helpinfo)
- elseif type(helpinfo) == "table" then
- local tags = { ... }
- for i=1,#tags do
- reportlines(t,t.helpinfo[tags[i]])
- if i < #tags then
- t.report()
- end
- end
- end
-end
-
-local function reportinfo(t)
- t.report()
- reportlines(t,moreinfo)
-end
-
-function logs.application(t)
- t.name = t.name or "unknown"
- t.banner = t.banner
- t.report = logs.reporter(t.name)
- t.help = function(...) reportbanner(t) ; reporthelp(t,...) ; reportinfo(t) end
- t.identify = function() reportbanner(t) end
- t.version = function() reportversion(t) end
- return t
-end
-
--- somewhat special
-
--- logging to a file
-
-
-function logs.system(whereto,process,jobname,category,...)
- local message = format("%s %s => %s => %s => %s\r",os.date("%d/%m/%y %H:%m:%S"),process,jobname,category,format(...))
- for i=1,10 do
- local f = io.open(whereto,"a") -- we can consider keepint the file open
- if f then
- f:write(message)
- f:close()
- break
- else
- sleep(0.1)
- end
- end
-end
-
-local report_system = logs.reporter("system","logs")
-
-function logs.obsolete(old,new)
- local o = loadstring("return " .. new)()
- if type(o) == "function" then
- return function(...)
- report_system("function %s is obsolete, use %s",old,new)
- loadstring(old .. "=" .. new .. " return ".. old)()(...)
- end
- elseif type(o) == "table" then
- local t, m = { }, { }
- m.__index = function(t,k)
- report_system("table %s is obsolete, use %s",old,new)
- m.__index, m.__newindex = o, o
- return o[k]
- end
- m.__newindex = function(t,k,v)
- report_system("table %s is obsolete, use %s",old,new)
- m.__index, m.__newindex = o, o
- o[k] = v
- end
- if libraries then
- libraries.obsolete[old] = t -- true
- end
- setmetatable(t,m)
- return t
- end
-end
-
-if utilities then
- utilities.report = report_system
-end
-
-if tex and tex.error then
- function logs.texerrormessage(...) -- for the moment we put this function here
- tex.error(format(...), { })
- end
-else
- function logs.texerrormessage(...)
- print(format(...))
- end
-end
-
--- do we still need io.flush then?
-
-io.stdout:setvbuf('no')
-io.stderr:setvbuf('no')
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['trac-pro'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local getmetatable, setmetatable, rawset, type = getmetatable, setmetatable, rawset, type
-
--- The protection implemented here is probably not that tight but good enough to catch
--- problems due to naive usage.
---
--- There's a more extensive version (trac-xxx.lua) that supports nesting.
---
--- This will change when we have _ENV in lua 5.2+
-
-local trace_namespaces = false trackers.register("system.namespaces", function(v) trace_namespaces = v end)
-
-local report_system = logs.reporter("system","protection")
-
-namespaces = namespaces or { }
-local namespaces = namespaces
-
-local registered = { }
-
-local function report_index(k,name)
- if trace_namespaces then
- report_system("reference to '%s' in protected namespace '%s', %s",k,name,debug.traceback())
- else
- report_system("reference to '%s' in protected namespace '%s'",k,name)
- end
-end
-
-local function report_newindex(k,name)
- if trace_namespaces then
- report_system("assignment to '%s' in protected namespace '%s', %s",k,name,debug.traceback())
- else
- report_system("assignment to '%s' in protected namespace '%s'",k,name)
- end
-end
-
-local function register(name)
- local data = name == "global" and _G or _G[name]
- if not data then
- return -- error
- end
- registered[name] = data
- local m = getmetatable(data)
- if not m then
- m = { }
- setmetatable(data,m)
- end
- local index, newindex = { }, { }
- m.__saved__index = m.__index
- m.__no__index = function(t,k)
- if not index[k] then
- index[k] = true
- report_index(k,name)
- end
- return nil
- end
- m.__saved__newindex = m.__newindex
- m.__no__newindex = function(t,k,v)
- if not newindex[k] then
- newindex[k] = true
- report_newindex(k,name)
- end
- rawset(t,k,v)
- end
- m.__protection__depth = 0
-end
-
-local function private(name) -- maybe save name
- local data = registered[name]
- if not data then
- data = _G[name]
- if not data then
- data = { }
- _G[name] = data
- end
- register(name)
- end
- return data
-end
-
-local function protect(name)
- local data = registered[name]
- if not data then
- return
- end
- local m = getmetatable(data)
- local pd = m.__protection__depth
- if pd > 0 then
- m.__protection__depth = pd + 1
- else
- m.__save_d_index, m.__saved__newindex = m.__index, m.__newindex
- m.__index, m.__newindex = m.__no__index, m.__no__newindex
- m.__protection__depth = 1
- end
-end
-
-local function unprotect(name)
- local data = registered[name]
- if not data then
- return
- end
- local m = getmetatable(data)
- local pd = m.__protection__depth
- if pd > 1 then
- m.__protection__depth = pd - 1
- else
- m.__index, m.__newindex = m.__saved__index, m.__saved__newindex
- m.__protection__depth = 0
- end
-end
-
-local function protectall()
- for name, _ in next, registered do
- if name ~= "global" then
- protect(name)
- end
- end
-end
-
-local function unprotectall()
- for name, _ in next, registered do
- if name ~= "global" then
- unprotect(name)
- end
- end
-end
-
-namespaces.register = register -- register when defined
-namespaces.private = private -- allocate and register if needed
-namespaces.protect = protect
-namespaces.unprotect = unprotect
-namespaces.protectall = protectall
-namespaces.unprotectall = unprotectall
-
-namespaces.private("namespaces") registered = { } register("global") -- unreachable
-
-directives.register("system.protect", function(v)
- if v then
- protectall()
- else
- unprotectall()
- end
-end)
-
-directives.register("system.checkglobals", function(v)
- if v then
- report_system("enabling global namespace guard")
- protect("global")
- else
- report_system("disabling global namespace guard")
- unprotect("global")
- end
-end)
-
--- dummy section (will go to luat-dum.lua)
-
-
-
-
-
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['luat-env'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- A former version provided functionality for non embeded core
--- scripts i.e. runtime library loading. Given the amount of
--- Lua code we use now, this no longer makes sense. Much of this
--- evolved before bytecode arrays were available and so a lot of
--- code has disappeared already.
-
-local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
-
-local report_lua = logs.reporter("resolvers","lua")
-
-local allocate, mark = utilities.storage.allocate, utilities.storage.mark
-
-local format, sub, match, gsub, find = string.format, string.sub, string.match, string.gsub, string.find
-local unquoted, quoted = string.unquoted, string.quoted
-local concat = table.concat
-
--- precautions
-
-os.setlocale(nil,nil) -- useless feature and even dangerous in luatex
-
-function os.setlocale()
- -- no way you can mess with it
-end
-
--- dirty tricks
-
-if arg and (arg[0] == 'luatex' or arg[0] == 'luatex.exe') and arg[1] == "--luaonly" then
- arg[-1] = arg[0]
- arg[ 0] = arg[2]
- for k=3,#arg do
- arg[k-2] = arg[k]
- end
- arg[#arg] = nil -- last
- arg[#arg] = nil -- pre-last
-end
-
--- environment
-
-environment = environment or { }
-local environment = environment
-
-environment.arguments = allocate()
-environment.files = allocate()
-environment.sortedflags = nil
-
-local mt = {
- __index = function(_,k)
- if k == "version" then
- local version = tex.toks and tex.toks.contextversiontoks
- if version and version ~= "" then
- rawset(environment,"version",version)
- return version
- else
- return "unknown"
- end
- elseif k == "jobname" or k == "formatname" then
- local name = tex and tex[k]
- if name or name== "" then
- rawset(environment,k,name)
- return name
- else
- return "unknown"
- end
- elseif k == "outputfilename" then
- local name = environment.jobname
- rawset(environment,k,name)
- return name
- end
- end
-}
-
-setmetatable(environment,mt)
-
-function environment.initializearguments(arg)
- local arguments, files = { }, { }
- environment.arguments, environment.files, environment.sortedflags = arguments, files, nil
- for index=1,#arg do
- local argument = arg[index]
- if index > 0 then
- local flag, value = match(argument,"^%-+(.-)=(.-)$")
- if flag then
- arguments[flag] = unquoted(value or "")
- else
- flag = match(argument,"^%-+(.+)")
- if flag then
- arguments[flag] = true
- else
- files[#files+1] = argument
- end
- end
- end
- end
- environment.ownname = environment.ownname or arg[0] or 'unknown.lua'
-end
-
-function environment.setargument(name,value)
- environment.arguments[name] = value
-end
-
--- todo: defaults, better checks e.g on type (boolean versus string)
---
--- tricky: too many hits when we support partials unless we add
--- a registration of arguments so from now on we have 'partial'
-
-function environment.argument(name,partial)
- local arguments, sortedflags = environment.arguments, environment.sortedflags
- if arguments[name] then
- return arguments[name]
- elseif partial then
- if not sortedflags then
- sortedflags = allocate(table.sortedkeys(arguments))
- for k=1,#sortedflags do
- sortedflags[k] = "^" .. sortedflags[k]
- end
- environment.sortedflags = sortedflags
- end
- -- example of potential clash: ^mode ^modefile
- for k=1,#sortedflags do
- local v = sortedflags[k]
- if find(name,v) then
- return arguments[sub(v,2,#v)]
- end
- end
- end
- return nil
-end
-
-function environment.splitarguments(separator) -- rather special, cut-off before separator
- local done, before, after = false, { }, { }
- local originalarguments = environment.originalarguments
- for k=1,#originalarguments do
- local v = originalarguments[k]
- if not done and v == separator then
- done = true
- elseif done then
- after[#after+1] = v
- else
- before[#before+1] = v
- end
- end
- return before, after
-end
-
-function environment.reconstructcommandline(arg,noquote)
- arg = arg or environment.originalarguments
- if noquote and #arg == 1 then
- -- we could just do: return unquoted(resolvers.resolve(arg[i]))
- local a = arg[1]
- a = resolvers.resolve(a)
- a = unquoted(a)
- return a
- elseif #arg > 0 then
- local result = { }
- for i=1,#arg do
- -- we could just do: result[#result+1] = format("%q",unquoted(resolvers.resolve(arg[i])))
- local a = arg[i]
- a = resolvers.resolve(a)
- a = unquoted(a)
- a = gsub(a,'"','\\"') -- tricky
- if find(a," ") then
- result[#result+1] = quoted(a)
- else
- result[#result+1] = a
- end
- end
- return concat(result," ")
- else
- return ""
- end
-end
-
-
-if arg then
-
- -- new, reconstruct quoted snippets (maybe better just remove the " then and add them later)
- local newarg, instring = { }, false
-
- for index=1,#arg do
- local argument = arg[index]
- if find(argument,"^\"") then
- newarg[#newarg+1] = gsub(argument,"^\"","")
- if not find(argument,"\"$") then
- instring = true
- end
- elseif find(argument,"\"$") then
- newarg[#newarg] = newarg[#newarg] .. " " .. gsub(argument,"\"$","")
- instring = false
- elseif instring then
- newarg[#newarg] = newarg[#newarg] .. " " .. argument
- else
- newarg[#newarg+1] = argument
- end
- end
- for i=1,-5,-1 do
- newarg[i] = arg[i]
- end
-
- environment.initializearguments(newarg)
-
- environment.originalarguments = mark(newarg)
- environment.rawarguments = mark(arg)
-
- arg = { } -- prevent duplicate handling
-
-end
-
--- weird place ... depends on a not yet loaded module
-
-function environment.texfile(filename)
- return resolvers.findfile(filename,'tex')
-end
-
-function environment.luafile(filename)
- local resolved = resolvers.findfile(filename,'tex') or ""
- if resolved ~= "" then
- return resolved
- end
- resolved = resolvers.findfile(filename,'texmfscripts') or ""
- if resolved ~= "" then
- return resolved
- end
- return resolvers.findfile(filename,'luatexlibs') or ""
-end
-
-environment.loadedluacode = loadfile -- can be overloaded
-
-function environment.luafilechunk(filename,silent) -- used for loading lua bytecode in the format
- filename = file.replacesuffix(filename, "lua")
- local fullname = environment.luafile(filename)
- if fullname and fullname ~= "" then
- local data = environment.loadedluacode(fullname)
- if trace_locating then
- report_lua("loading file %s%s", fullname, not data and " failed" or "")
- elseif not silent then
- texio.write("<",data and "+ " or "- ",fullname,">")
- end
- return data
- else
- if trace_locating then
- report_lua("unknown file %s", filename)
- end
- return nil
- end
-end
-
--- the next ones can use the previous ones / combine
-
-function environment.loadluafile(filename, version)
- local lucname, luaname, chunk
- local basename = file.removesuffix(filename)
- if basename == filename then
- lucname, luaname = basename .. ".luc", basename .. ".lua"
- else
- lucname, luaname = nil, basename -- forced suffix
- end
- -- when not overloaded by explicit suffix we look for a luc file first
- local fullname = (lucname and environment.luafile(lucname)) or ""
- if fullname ~= "" then
- if trace_locating then
- report_lua("loading %s", fullname)
- end
- chunk = loadfile(fullname) -- this way we don't need a file exists check
- end
- if chunk then
- assert(chunk)()
- if version then
- -- we check of the version number of this chunk matches
- local v = version -- can be nil
- if modules and modules[filename] then
- v = modules[filename].version -- new method
- elseif versions and versions[filename] then
- v = versions[filename] -- old method
- end
- if v == version then
- return true
- else
- if trace_locating then
- report_lua("version mismatch for %s: lua=%s, luc=%s", filename, v, version)
- end
- environment.loadluafile(filename)
- end
- else
- return true
- end
- end
- fullname = (luaname and environment.luafile(luaname)) or ""
- if fullname ~= "" then
- if trace_locating then
- report_lua("loading %s", fullname)
- end
- chunk = loadfile(fullname) -- this way we don't need a file exists check
- if not chunk then
- if trace_locating then
- report_lua("unknown file %s", filename)
- end
- else
- assert(chunk)()
- return true
- end
- end
- return false
-end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['lxml-tab'] = {
- version = 1.001,
- comment = "this module is the basis for the lxml-* ones",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- this module needs a cleanup: check latest lpeg, passing args, (sub)grammar, etc etc
--- stripping spaces from e.g. cont-en.xml saves .2 sec runtime so it's not worth the
--- trouble
-
--- todo: when serializing optionally remap named entities to hex (if known in char-ent.lua)
--- maybe when letter -> utf, else name .. then we need an option to the serializer .. a bit
--- of work so we delay this till we cleanup
-
-local trace_entities = false trackers.register("xml.entities", function(v) trace_entities = v end)
-
-local report_xml = logs and logs.reporter("xml","core") or function(...) print(format(...)) end
-
---[[ldx--
-The parser used here is inspired by the variant discussed in the lua book, but
-handles comment and processing instructions, has a different structure, provides
-parent access; a first version used different trickery but was less optimized to we
-went this route. First we had a find based parser, now we have an based one.
-The find based parser can be found in l-xml-edu.lua along with other older code.
-
-Beware, the interface may change. For instance at, ns, tg, dt may get more
-verbose names. Once the code is stable we will also remove some tracing and
-optimize the code.
-
-I might even decide to reimplement the parser using the latest trickery
-as the current variant was written when showed up and it's easier now to
-build tables in one go.
---ldx]]--
-
-xml = xml or { }
-local xml = xml
-
-
-local utf = unicode.utf8
-local concat, remove, insert = table.concat, table.remove, table.insert
-local type, next, setmetatable, getmetatable, tonumber = type, next, setmetatable, getmetatable, tonumber
-local format, lower, find, match, gsub = string.format, string.lower, string.find, string.match, string.gsub
-local utfchar, utffind, utfgsub = utf.char, utf.find, utf.gsub
-local lpegmatch = lpeg.match
-local P, S, R, C, V, C, Cs = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.V, lpeg.C, lpeg.Cs
-
---[[ldx--
-First a hack to enable namespace resolving. A namespace is characterized by
-a . The following function associates a namespace prefix with a
-pattern. We use , which in this case is more than twice as fast as a
-find based solution where we loop over an array of patterns. Less code and
-much cleaner.
---ldx]]--
-
-xml.xmlns = xml.xmlns or { }
-
-local check = P(false)
-local parse = check
-
---[[ldx--
-The next function associates a namespace prefix with an . This
-normally happens independent of parsing.
-
-
-xml.registerns("mml","mathml")
-
---ldx]]--
-
-function xml.registerns(namespace, pattern) -- pattern can be an lpeg
- check = check + C(P(lower(pattern))) / namespace
- parse = P { P(check) + 1 * V(1) }
-end
-
---[[ldx--
-The next function also registers a namespace, but this time we map a
-given namespace prefix onto a registered one, using the given
- . This used for attributes like xmlns:m .
-
-
-xml.checkns("m","http://www.w3.org/mathml")
-
---ldx]]--
-
-function xml.checkns(namespace,url)
- local ns = lpegmatch(parse,lower(url))
- if ns and namespace ~= ns then
- xml.xmlns[namespace] = ns
- end
-end
-
---[[ldx--
-Next we provide a way to turn an into a registered
-namespace. This used for the xmlns attribute.
-
-
-resolvedns = xml.resolvens("http://www.w3.org/mathml")
-
-
-This returns mml .
---ldx]]--
-
-function xml.resolvens(url)
- return lpegmatch(parse,lower(url)) or ""
-end
-
---[[ldx--
-A namespace in an element can be remapped onto the registered
-one efficiently by using the xml.xmlns table.
---ldx]]--
-
---[[ldx--
-This version uses . We follow the same approach as before, stack and top and
-such. This version is about twice as fast which is mostly due to the fact that
-we don't have to prepare the stream for cdata, doctype etc etc. This variant is
-is dedicated to Luigi Scarso, who challenged me with 40 megabyte files that
-took 12.5 seconds to load (1.5 for file io and the rest for tree building). With
-the implementation we got that down to less 7.3 seconds. Loading the 14
- interface definition files (2.6 meg) went down from 1.05 seconds to 0.55.
-
-Next comes the parser. The rather messy doctype definition comes in many
-disguises so it is no surprice that later on have to dedicate quite some
- code to it.
-
-
-
-
-
-
-
-
-
-
-The code may look a bit complex but this is mostly due to the fact that we
-resolve namespaces and attach metatables. There is only one public function:
-
-
-local x = xml.convert(somestring)
-
-
-An optional second boolean argument tells this function not to create a root
-element.
-
-Valid entities are:
-
-
-
-
-
-
---ldx]]--
-
--- not just one big nested table capture (lpeg overflow)
-
-local nsremap, resolvens = xml.xmlns, xml.resolvens
-
-local stack = { }
-local top = { }
-local dt = { }
-local at = { }
-local xmlns = { }
-local errorstr = nil
-local entities = { }
-local strip = false
-local cleanup = false
-local utfize = false
-local resolve_predefined = false
-local unify_predefined = false
-
-local dcache = { }
-local hcache = { }
-local acache = { }
-
-local mt = { }
-
-local function initialize_mt(root)
- mt = { __index = root } -- will be redefined later
-end
-
-function xml.setproperty(root,k,v)
- getmetatable(root).__index[k] = v
-end
-
-function xml.checkerror(top,toclose)
- return "" -- can be set
-end
-
-local function add_attribute(namespace,tag,value)
- if cleanup and #value > 0 then
- value = cleanup(value) -- new
- end
- if tag == "xmlns" then
- xmlns[#xmlns+1] = resolvens(value)
- at[tag] = value
- elseif namespace == "" then
- at[tag] = value
- elseif namespace == "xmlns" then
- xml.checkns(tag,value)
- at["xmlns:" .. tag] = value
- else
- -- for the moment this way:
- at[namespace .. ":" .. tag] = value
- end
-end
-
-local function add_empty(spacing, namespace, tag)
- if #spacing > 0 then
- dt[#dt+1] = spacing
- end
- local resolved = (namespace == "" and xmlns[#xmlns]) or nsremap[namespace] or namespace
- top = stack[#stack]
- dt = top.dt
- local t = { ns=namespace or "", rn=resolved, tg=tag, at=at, dt={}, __p__ = top }
- dt[#dt+1] = t
- setmetatable(t, mt)
- if at.xmlns then
- remove(xmlns)
- end
- at = { }
-end
-
-local function add_begin(spacing, namespace, tag)
- if #spacing > 0 then
- dt[#dt+1] = spacing
- end
- local resolved = (namespace == "" and xmlns[#xmlns]) or nsremap[namespace] or namespace
- top = { ns=namespace or "", rn=resolved, tg=tag, at=at, dt={}, __p__ = stack[#stack] }
- setmetatable(top, mt)
- dt = top.dt
- stack[#stack+1] = top
- at = { }
-end
-
-local function add_end(spacing, namespace, tag)
- if #spacing > 0 then
- dt[#dt+1] = spacing
- end
- local toclose = remove(stack)
- top = stack[#stack]
- if #stack < 1 then
- errorstr = format("nothing to close with %s %s", tag, xml.checkerror(top,toclose) or "")
- elseif toclose.tg ~= tag then -- no namespace check
- errorstr = format("unable to close %s with %s %s", toclose.tg, tag, xml.checkerror(top,toclose) or "")
- end
- dt = top.dt
- dt[#dt+1] = toclose
- -- dt[0] = top -- nasty circular reference when serializing table
- if toclose.at.xmlns then
- remove(xmlns)
- end
-end
-
-local function add_text(text)
- if cleanup and #text > 0 then
- dt[#dt+1] = cleanup(text)
- else
- dt[#dt+1] = text
- end
-end
-
-local function add_special(what, spacing, text)
- if #spacing > 0 then
- dt[#dt+1] = spacing
- end
- if strip and (what == "@cm@" or what == "@dt@") then
- -- forget it
- else
- dt[#dt+1] = { special=true, ns="", tg=what, dt={ text } }
- end
-end
-
-local function set_message(txt)
- errorstr = "garbage at the end of the file: " .. gsub(txt,"([ \n\r\t]*)","")
-end
-
-local reported_attribute_errors = { }
-
-local function attribute_value_error(str)
- if not reported_attribute_errors[str] then
- report_xml("invalid attribute value: %q",str)
- reported_attribute_errors[str] = true
- at._error_ = str
- end
- return str
-end
-
-local function attribute_specification_error(str)
- if not reported_attribute_errors[str] then
- report_xml("invalid attribute specification: %q",str)
- reported_attribute_errors[str] = true
- at._error_ = str
- end
- return str
-end
-
-xml.placeholders = {
- unknown_dec_entity = function(str) return (str == "" and "&error;") or format("&%s;",str) end,
- unknown_hex_entity = function(str) return format("%s;",str) end,
- unknown_any_entity = function(str) return format("%s;",str) end,
-}
-
-local placeholders = xml.placeholders
-
-local function fromhex(s)
- local n = tonumber(s,16)
- if n then
- return utfchar(n)
- else
- return format("h:%s",s), true
- end
-end
-
-local function fromdec(s)
- local n = tonumber(s)
- if n then
- return utfchar(n)
- else
- return format("d:%s",s), true
- end
-end
-
--- one level expansion (simple case), no checking done
-
-local rest = (1-P(";"))^0
-local many = P(1)^0
-
-local parsedentity =
- P("&") * (P("#x")*(rest/fromhex) + P("#")*(rest/fromdec)) * P(";") * P(-1) +
- (P("#x")*(many/fromhex) + P("#")*(many/fromdec))
-
--- parsing in the xml file
-
-local predefined_unified = {
- [38] = "&",
- [42] = """,
- [47] = "'",
- [74] = "<",
- [76] = ">",
-}
-
-local predefined_simplified = {
- [38] = "&", amp = "&",
- [42] = '"', quot = '"',
- [47] = "'", apos = "'",
- [74] = "<", lt = "<",
- [76] = ">", gt = ">",
-}
-
-local nofprivates = 0xF0000 -- shared but seldom used
-
-local privates_u = { -- unescaped
- [ [[&]] ] = "&",
- [ [["]] ] = """,
- [ [[']] ] = "'",
- [ [[<]] ] = "<",
- [ [[>]] ] = ">",
-}
-
-local privates_p = {
-}
-
-local privates_n = {
- -- keeps track of defined ones
-}
-
-local function escaped(s)
- if s == "" then
- return ""
- else -- if utffind(s,privates_u) then
- return (utfgsub(s,".",privates_u))
- -- else
- -- return s
- end
-end
-
-local function unescaped(s)
- local p = privates_n[s]
- if not p then
- nofprivates = nofprivates + 1
- p = utfchar(nofprivates)
- privates_n[s] = p
- s = "&" .. s .. ";" -- todo: use char-ent to map to hex
- privates_u[p] = s
- privates_p[p] = s
- end
- return p
-end
-
-local function unprivatized(s,resolve)
- if s == "" then
- return ""
- else
- return (utfgsub(s,".",privates_p))
- end
-end
-
-xml.privatetoken = unescaped
-xml.unprivatized = unprivatized
-xml.privatecodes = privates_n
-
-local function handle_hex_entity(str)
- local h = hcache[str]
- if not h then
- local n = tonumber(str,16)
- h = unify_predefined and predefined_unified[n]
- if h then
- if trace_entities then
- report_xml("utfize, converting hex entity %s; into %s",str,h)
- end
- elseif utfize then
- h = (n and utfchar(n)) or xml.unknown_hex_entity(str) or ""
- if not n then
- report_xml("utfize, ignoring hex entity %s;",str)
- elseif trace_entities then
- report_xml("utfize, converting hex entity %s; into %s",str,h)
- end
- else
- if trace_entities then
- report_xml("found entity %s;",str)
- end
- h = "" .. str .. ";"
- end
- hcache[str] = h
- end
- return h
-end
-
-local function handle_dec_entity(str)
- local d = dcache[str]
- if not d then
- local n = tonumber(str)
- d = unify_predefined and predefined_unified[n]
- if d then
- if trace_entities then
- report_xml("utfize, converting dec entity %s; into %s",str,d)
- end
- elseif utfize then
- d = (n and utfchar(n)) or placeholders.unknown_dec_entity(str) or ""
- if not n then
- report_xml("utfize, ignoring dec entity %s;",str)
- elseif trace_entities then
- report_xml("utfize, converting dec entity %s; into %s",str,d)
- end
- else
- if trace_entities then
- report_xml("found entity %s;",str)
- end
- d = "" .. str .. ";"
- end
- dcache[str] = d
- end
- return d
-end
-
-xml.parsedentitylpeg = parsedentity
-
-local function handle_any_entity(str)
- if resolve then
- local a = acache[str] -- per instance ! todo
- if not a then
- a = resolve_predefined and predefined_simplified[str]
- if a then
- if trace_entities then
- report_xml("resolved entity &%s; -> %s (predefined)",str,a)
- end
- else
- if type(resolve) == "function" then
- a = resolve(str) or entities[str]
- else
- a = entities[str]
- end
- if a then
- if type(a) == "function" then
- if trace_entities then
- report_xml("expanding entity &%s; (function)",str)
- end
- a = a(str) or ""
- end
- a = lpegmatch(parsedentity,a) or a -- for nested
- if trace_entities then
- report_xml("resolved entity &%s; -> %s (internal)",str,a)
- end
- else
- local unknown_any_entity = placeholders.unknown_any_entity
- if unknown_any_entity then
- a = unknown_any_entity(str) or ""
- end
- if a then
- if trace_entities then
- report_xml("resolved entity &%s; -> %s (external)",str,a)
- end
- else
- if trace_entities then
- report_xml("keeping entity &%s;",str)
- end
- if str == "" then
- a = "&error;"
- else
- a = "&" .. str .. ";"
- end
- end
- end
- end
- acache[str] = a
- elseif trace_entities then
- if not acache[str] then
- report_xml("converting entity &%s; into %s",str,a)
- acache[str] = a
- end
- end
- return a
- else
- local a = acache[str]
- if not a then
- a = resolve_predefined and predefined_simplified[str]
- if a then
- -- one of the predefined
- acache[str] = a
- if trace_entities then
- report_xml("entity &%s; becomes %s",str,tostring(a))
- end
- elseif str == "" then
- if trace_entities then
- report_xml("invalid entity &%s;",str)
- end
- a = "&error;"
- acache[str] = a
- else
- if trace_entities then
- report_xml("entity &%s; is made private",str)
- end
- -- a = "&" .. str .. ";"
- a = unescaped(str)
- acache[str] = a
- end
- end
- return a
- end
-end
-
-local function handle_end_entity(chr)
- report_xml("error in entity, %q found instead of ';'",chr)
-end
-
-local space = S(' \r\n\t')
-local open = P('<')
-local close = P('>')
-local squote = S("'")
-local dquote = S('"')
-local equal = P('=')
-local slash = P('/')
-local colon = P(':')
-local semicolon = P(';')
-local ampersand = P('&')
-local valid = R('az', 'AZ', '09') + S('_-.')
-local name_yes = C(valid^1) * colon * C(valid^1)
-local name_nop = C(P(true)) * C(valid^1)
-local name = name_yes + name_nop
-local utfbom = lpeg.patterns.utfbom -- no capture
-local spacing = C(space^0)
-
------ entitycontent = (1-open-semicolon)^0
-local anyentitycontent = (1-open-semicolon-space-close)^0
-local hexentitycontent = R("AF","af","09")^0
-local decentitycontent = R("09")^0
-local parsedentity = P("#")/"" * (
- P("x")/"" * (hexentitycontent/handle_hex_entity) +
- (decentitycontent/handle_dec_entity)
- ) + (anyentitycontent/handle_any_entity)
-local entity = ampersand/"" * parsedentity * ( (semicolon/"") + #(P(1)/handle_end_entity))
-
-local text_unparsed = C((1-open)^1)
-local text_parsed = Cs(((1-open-ampersand)^1 + entity)^1)
-
-local somespace = space^1
-local optionalspace = space^0
-
------ value = (squote * C((1 - squote)^0) * squote) + (dquote * C((1 - dquote)^0) * dquote) -- ampersand and < also invalid in value
-local value = (squote * Cs((entity + (1 - squote))^0) * squote) + (dquote * Cs((entity + (1 - dquote))^0) * dquote) -- ampersand and < also invalid in value
-
-local endofattributes = slash * close + close -- recovery of flacky html
-local whatever = space * name * optionalspace * equal
------ wrongvalue = C(P(1-whatever-close)^1 + P(1-close)^1) / attribute_value_error
------ wrongvalue = C(P(1-whatever-endofattributes)^1 + P(1-endofattributes)^1) / attribute_value_error
------ wrongvalue = C(P(1-space-endofattributes)^1) / attribute_value_error
-local wrongvalue = Cs(P(entity + (1-space-endofattributes))^1) / attribute_value_error
-
-local attributevalue = value + wrongvalue
-
-local attribute = (somespace * name * optionalspace * equal * optionalspace * attributevalue) / add_attribute
------ attributes = (attribute)^0
-
-local attributes = (attribute + somespace^-1 * (((1-endofattributes)^1)/attribute_specification_error))^0
-
-local parsedtext = text_parsed / add_text
-local unparsedtext = text_unparsed / add_text
-local balanced = P { "[" * ((1 - S"[]") + V(1))^0 * "]" } -- taken from lpeg manual, () example
-
-local emptyelement = (spacing * open * name * attributes * optionalspace * slash * close) / add_empty
-local beginelement = (spacing * open * name * attributes * optionalspace * close) / add_begin
-local endelement = (spacing * open * slash * name * optionalspace * close) / add_end
-
-local begincomment = open * P("!--")
-local endcomment = P("--") * close
-local begininstruction = open * P("?")
-local endinstruction = P("?") * close
-local begincdata = open * P("![CDATA[")
-local endcdata = P("]]") * close
-
-local someinstruction = C((1 - endinstruction)^0)
-local somecomment = C((1 - endcomment )^0)
-local somecdata = C((1 - endcdata )^0)
-
-local function normalentity(k,v ) entities[k] = v end
-local function systementity(k,v,n) entities[k] = v end
-local function publicentity(k,v,n) entities[k] = v end
-
--- todo: separate dtd parser
-
-local begindoctype = open * P("!DOCTYPE")
-local enddoctype = close
-local beginset = P("[")
-local endset = P("]")
-local doctypename = C((1-somespace-close)^0)
-local elementdoctype = optionalspace * P(" &
- cleanup = settings.text_cleanup
- entities = settings.entities or { }
- --
- if utfize == nil then
- settings.utfize_entities = true
- utfize = true
- end
- if resolve_predefined == nil then
- settings.resolve_predefined_entities = true
- resolve_predefined = true
- end
- --
- --
- stack, top, at, xmlns, errorstr = { }, { }, { }, { }, nil
- acache, hcache, dcache = { }, { }, { } -- not stored
- reported_attribute_errors = { }
- if settings.parent_root then
- mt = getmetatable(settings.parent_root)
- else
- initialize_mt(top)
- end
- stack[#stack+1] = top
- top.dt = { }
- dt = top.dt
- if not data or data == "" then
- errorstr = "empty xml file"
- elseif utfize or resolve then
- if lpegmatch(grammar_parsed_text,data) then
- errorstr = ""
- else
- errorstr = "invalid xml file - parsed text"
- end
- elseif type(data) == "string" then
- if lpegmatch(grammar_unparsed_text,data) then
- errorstr = ""
- else
- errorstr = "invalid xml file - unparsed text"
- end
- else
- errorstr = "invalid xml file - no text at all"
- end
- local result
- if errorstr and errorstr ~= "" then
- result = { dt = { { ns = "", tg = "error", dt = { errorstr }, at={ }, er = true } } }
- setmetatable(stack, mt)
- local errorhandler = settings.error_handler
- if errorhandler == false then
- -- no error message
- else
- errorhandler = errorhandler or xml.errorhandler
- if errorhandler then
- xml.errorhandler(format("load error: %s",errorstr))
- end
- end
- else
- result = stack[1]
- end
- if not settings.no_root then
- result = { special = true, ns = "", tg = '@rt@', dt = result.dt, at={ }, entities = entities, settings = settings }
- setmetatable(result, mt)
- local rdt = result.dt
- for k=1,#rdt do
- local v = rdt[k]
- if type(v) == "table" and not v.special then -- always table -)
- result.ri = k -- rootindex
- v.__p__ = result -- new, experiment, else we cannot go back to settings, we need to test this !
- break
- end
- end
- end
- if errorstr and errorstr ~= "" then
- result.error = true
- end
- result.statistics = {
- entities = {
- decimals = dcache,
- hexadecimals = hcache,
- names = acache,
- }
- }
- strip, utfize, resolve, resolve_predefined = nil, nil, nil, nil
- unify_predefined, cleanup, entities = nil, nil, nil
- stack, top, at, xmlns, errorstr = nil, nil, nil, nil, nil
- acache, hcache, dcache = nil, nil, nil
- reported_attribute_errors, mt, errorhandler = nil, nil, nil
- return result
-end
-
--- Because we can have a crash (stack issues) with faulty xml, we wrap this one
--- in a protector:
-
-function xmlconvert(data,settings)
- local ok, result = pcall(function() return _xmlconvert_(data,settings) end)
- if ok then
- return result
- else
- return _xmlconvert_("")
- end
-end
-
-xml.convert = xmlconvert
-
-function xml.inheritedconvert(data,xmldata) -- xmldata is parent
- local settings = xmldata.settings
- if settings then
- settings.parent_root = xmldata -- to be tested
- end
- -- settings.no_root = true
- local xc = xmlconvert(data,settings) -- hm, we might need to locate settings
- -- xc.settings = nil
- -- xc.entities = nil
- -- xc.special = nil
- -- xc.ri = nil
- -- print(xc.tg)
- return xc
-end
-
---[[ldx--
-Packaging data in an xml like table is done with the following
-function. Maybe it will go away (when not used).
---ldx]]--
-
-function xml.is_valid(root)
- return root and root.dt and root.dt[1] and type(root.dt[1]) == "table" and not root.dt[1].er
-end
-
-function xml.package(tag,attributes,data)
- local ns, tg = match(tag,"^(.-):?([^:]+)$")
- local t = { ns = ns, tg = tg, dt = data or "", at = attributes or {} }
- setmetatable(t, mt)
- return t
-end
-
-function xml.is_valid(root)
- return root and not root.error
-end
-
-xml.errorhandler = report_xml
-
---[[ldx--
-We cannot load an from a filehandle so we need to load
-the whole file first. The function accepts a string representing
-a filename or a file handle.
---ldx]]--
-
-function xml.load(filename,settings)
- local data = ""
- if type(filename) == "string" then
- -- local data = io.loaddata(filename) - -todo: check type in io.loaddata
- local f = io.open(filename,'r')
- if f then
- data = f:read("*all")
- f:close()
- end
- elseif filename then -- filehandle
- data = filename:read("*all")
- end
- return xmlconvert(data,settings)
-end
-
---[[ldx--
-When we inject new elements, we need to convert strings to
-valid trees, which is what the next function does.
---ldx]]--
-
-local no_root = { no_root = true }
-
-function xml.toxml(data)
- if type(data) == "string" then
- local root = { xmlconvert(data,no_root) }
- return (#root > 1 and root) or root[1]
- else
- return data
- end
-end
-
---[[ldx--
-For copying a tree we use a dedicated function instead of the
-generic table copier. Since we know what we're dealing with we
-can speed up things a bit. The second argument is not to be used!
---ldx]]--
-
-local function copy(old,tables)
- if old then
- tables = tables or { }
- local new = { }
- if not tables[old] then
- tables[old] = new
- end
- for k,v in next, old do
- new[k] = (type(v) == "table" and (tables[v] or copy(v, tables))) or v
- end
- local mt = getmetatable(old)
- if mt then
- setmetatable(new,mt)
- end
- return new
- else
- return { }
- end
-end
-
-xml.copy = copy
-
---[[ldx--
-In serializing the tree or parts of the tree is a major
-actitivity which is why the following function is pretty optimized resulting
-in a few more lines of code than needed. The variant that uses the formatting
-function for all components is about 15% slower than the concatinating
-alternative.
---ldx]]--
-
--- todo: add when not present
-
-function xml.checkbom(root) -- can be made faster
- if root.ri then
- local dt = root.dt
- for k=1,#dt do
- local v = dt[k]
- if type(v) == "table" and v.special and v.tg == "@pi@" and find(v.dt[1],"xml.*version=") then
- return
- end
- end
- insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
- insert(dt, 2, "\n" )
- end
-end
-
---[[ldx--
-At the cost of some 25% runtime overhead you can first convert the tree to a string
-and then handle the lot.
---ldx]]--
-
--- new experimental reorganized serialize
-
-local function verbose_element(e,handlers) -- options
- local handle = handlers.handle
- local serialize = handlers.serialize
- local ens, etg, eat, edt, ern = e.ns, e.tg, e.at, e.dt, e.rn
- local ats = eat and next(eat) and { }
- if ats then
- for k,v in next, eat do
- ats[#ats+1] = format('%s=%q',k,escaped(v))
- end
- end
- if ern and trace_entities and ern ~= ens then
- ens = ern
- end
- if ens ~= "" then
- if edt and #edt > 0 then
- if ats then
- handle("<",ens,":",etg," ",concat(ats," "),">")
- else
- handle("<",ens,":",etg,">")
- end
- for i=1,#edt do
- local e = edt[i]
- if type(e) == "string" then
- handle(escaped(e))
- else
- serialize(e,handlers)
- end
- end
- handle("",ens,":",etg,">")
- else
- if ats then
- handle("<",ens,":",etg," ",concat(ats," "),"/>")
- else
- handle("<",ens,":",etg,"/>")
- end
- end
- else
- if edt and #edt > 0 then
- if ats then
- handle("<",etg," ",concat(ats," "),">")
- else
- handle("<",etg,">")
- end
- for i=1,#edt do
- local e = edt[i]
- if type(e) == "string" then
- handle(escaped(e)) -- option: hexify escaped entities
- else
- serialize(e,handlers)
- end
- end
- handle("",etg,">")
- else
- if ats then
- handle("<",etg," ",concat(ats," "),"/>")
- else
- handle("<",etg,"/>")
- end
- end
- end
-end
-
-local function verbose_pi(e,handlers)
- handlers.handle("",e.dt[1],"?>")
-end
-
-local function verbose_comment(e,handlers)
- handlers.handle("")
-end
-
-local function verbose_cdata(e,handlers)
- handlers.handle("")
-end
-
-local function verbose_doctype(e,handlers)
- handlers.handle("")
-end
-
-local function verbose_root(e,handlers)
- handlers.serialize(e.dt,handlers)
-end
-
-local function verbose_text(e,handlers)
- handlers.handle(escaped(e))
-end
-
-local function verbose_document(e,handlers)
- local serialize = handlers.serialize
- local functions = handlers.functions
- for i=1,#e do
- local ei = e[i]
- if type(ei) == "string" then
- functions["@tx@"](ei,handlers)
- else
- serialize(ei,handlers)
- end
- end
-end
-
-local function serialize(e,handlers,...)
- local initialize = handlers.initialize
- local finalize = handlers.finalize
- local functions = handlers.functions
- if initialize then
- local state = initialize(...)
- if not state == true then
- return state
- end
- end
- local etg = e.tg
- if etg then
- (functions[etg] or functions["@el@"])(e,handlers)
- -- elseif type(e) == "string" then
- -- functions["@tx@"](e,handlers)
- else
- functions["@dc@"](e,handlers) -- dc ?
- end
- if finalize then
- return finalize()
- end
-end
-
-local function xserialize(e,handlers)
- local functions = handlers.functions
- local etg = e.tg
- if etg then
- (functions[etg] or functions["@el@"])(e,handlers)
- -- elseif type(e) == "string" then
- -- functions["@tx@"](e,handlers)
- else
- functions["@dc@"](e,handlers)
- end
-end
-
-local handlers = { }
-
-local function newhandlers(settings)
- local t = table.copy(handlers.verbose or { }) -- merge
- if settings then
- for k,v in next, settings do
- if type(v) == "table" then
- local tk = t[k] if not tk then tk = { } t[k] = tk end
- for kk,vv in next, v do
- tk[kk] = vv
- end
- else
- t[k] = v
- end
- end
- if settings.name then
- handlers[settings.name] = t
- end
- end
- utilities.storage.mark(t)
- return t
-end
-
-local nofunction = function() end
-
-function xml.sethandlersfunction(handler,name,fnc)
- handler.functions[name] = fnc or nofunction
-end
-
-function xml.gethandlersfunction(handler,name)
- return handler.functions[name]
-end
-
-function xml.gethandlers(name)
- return handlers[name]
-end
-
-newhandlers {
- name = "verbose",
- initialize = false, -- faster than nil and mt lookup
- finalize = false, -- faster than nil and mt lookup
- serialize = xserialize,
- handle = print,
- functions = {
- ["@dc@"] = verbose_document,
- ["@dt@"] = verbose_doctype,
- ["@rt@"] = verbose_root,
- ["@el@"] = verbose_element,
- ["@pi@"] = verbose_pi,
- ["@cm@"] = verbose_comment,
- ["@cd@"] = verbose_cdata,
- ["@tx@"] = verbose_text,
- }
-}
-
---[[ldx--
-How you deal with saving data depends on your preferences. For a 40 MB database
-file the timing on a 2.3 Core Duo are as follows (time in seconds):
-
-
-1.3 : load data from file to string
-6.1 : convert string into tree
-5.3 : saving in file using xmlsave
-6.8 : converting to string using xml.tostring
-3.6 : saving converted string in file
-
-
-Beware, these were timing with the old routine but measurements will not be that
-much different I guess.
---ldx]]--
-
--- maybe this will move to lxml-xml
-
-local result
-
-local xmlfilehandler = newhandlers {
- name = "file",
- initialize = function(name)
- result = io.open(name,"wb")
- return result
- end,
- finalize = function()
- result:close()
- return true
- end,
- handle = function(...)
- result:write(...)
- end,
-}
-
--- no checking on writeability here but not faster either
---
--- local xmlfilehandler = newhandlers {
--- initialize = function(name)
--- io.output(name,"wb")
--- return true
--- end,
--- finalize = function()
--- io.close()
--- return true
--- end,
--- handle = io.write,
--- }
-
-function xml.save(root,name)
- serialize(root,xmlfilehandler,name)
-end
-
-local result
-
-local xmlstringhandler = newhandlers {
- name = "string",
- initialize = function()
- result = { }
- return result
- end,
- finalize = function()
- return concat(result)
- end,
- handle = function(...)
- result[#result+1] = concat { ... }
- end,
-}
-
-local function xmltostring(root) -- 25% overhead due to collecting
- if not root then
- return ""
- elseif type(root) == 'string' then
- return root
- else -- if next(root) then -- next is faster than type (and >0 test)
- return serialize(root,xmlstringhandler) or ""
- end
-end
-
-local function __tostring(root) -- inline
- return (root and xmltostring(root)) or ""
-end
-
-initialize_mt = function(root) -- redefinition
- mt = { __tostring = __tostring, __index = root }
-end
-
-xml.defaulthandlers = handlers
-xml.newhandlers = newhandlers
-xml.serialize = serialize
-xml.tostring = xmltostring
-
---[[ldx--
-The next function operated on the content only and needs a handle function
-that accepts a string.
---ldx]]--
-
-local function xmlstring(e,handle)
- if not handle or (e.special and e.tg ~= "@rt@") then
- -- nothing
- elseif e.tg then
- local edt = e.dt
- if edt then
- for i=1,#edt do
- xmlstring(edt[i],handle)
- end
- end
- else
- handle(e)
- end
-end
-
-xml.string = xmlstring
-
---[[ldx--
-A few helpers:
---ldx]]--
-
-
-function xml.settings(e)
- while e do
- local s = e.settings
- if s then
- return s
- else
- e = e.__p__
- end
- end
- return nil
-end
-
-function xml.root(e)
- local r = e
- while e do
- e = e.__p__
- if e then
- r = e
- end
- end
- return r
-end
-
-function xml.parent(root)
- return root.__p__
-end
-
-function xml.body(root)
- return (root.ri and root.dt[root.ri]) or root -- not ok yet
-end
-
-function xml.name(root)
- if not root then
- return ""
- elseif root.ns == "" then
- return root.tg
- else
- return root.ns .. ":" .. root.tg
- end
-end
-
---[[ldx--
-The next helper erases an element but keeps the table as it is,
-and since empty strings are not serialized (effectively) it does
-not harm. Copying the table would take more time. Usage:
---ldx]]--
-
-function xml.erase(dt,k)
- if dt then
- if k then
- dt[k] = ""
- else for k=1,#dt do
- dt[1] = { "" }
- end end
- end
-end
-
---[[ldx--
-The next helper assigns a tree (or string). Usage:
-
-
-dt[k] = xml.assign(root) or xml.assign(dt,k,root)
-
---ldx]]--
-
-function xml.assign(dt,k,root)
- if dt and k then
- dt[k] = (type(root) == "table" and xml.body(root)) or root
- return dt[k]
- else
- return xml.body(root)
- end
-end
-
--- the following helpers may move
-
---[[ldx--
-The next helper assigns a tree (or string). Usage:
-
-xml.tocdata(e)
-xml.tocdata(e,"error")
-
---ldx]]--
-
-function xml.tocdata(e,wrapper) -- a few more in the aux module
- local whatever = type(e) == "table" and xmltostring(e.dt) or e or ""
- if wrapper then
- whatever = format("<%s>%s%s>",wrapper,whatever,wrapper)
- end
- local t = { special = true, ns = "", tg = "@cd@", at = {}, rn = "", dt = { whatever }, __p__ = e }
- setmetatable(t,getmetatable(e))
- e.dt = { t }
-end
-
-function xml.makestandalone(root)
- if root.ri then
- local dt = root.dt
- for k=1,#dt do
- local v = dt[k]
- if type(v) == "table" and v.special and v.tg == "@pi@" then
- local txt = v.dt[1]
- if find(txt,"xml.*version=") then
- v.dt[1] = txt .. " standalone='yes'"
- break
- end
- end
- end
- end
- return root
-end
-
-function xml.kind(e)
- local dt = e and e.dt
- if dt then
- local n = #dt
- if n == 1 then
- local d = dt[1]
- if d.special then
- local tg = d.tg
- if tg == "@cd@" then
- return "cdata"
- elseif tg == "@cm" then
- return "comment"
- elseif tg == "@pi@" then
- return "instruction"
- elseif tg == "@dt@" then
- return "declaration"
- end
- elseif type(d) == "string" then
- return "text"
- end
- return "element"
- elseif n > 0 then
- return "mixed"
- end
- end
- return "empty"
-end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['lxml-pth'] = {
- version = 1.001,
- comment = "this module is the basis for the lxml-* ones",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- e.ni is only valid after a filter run
--- todo: B/C/[get first match]
-
-local concat, remove, insert = table.concat, table.remove, table.insert
-local type, next, tonumber, tostring, setmetatable, loadstring = type, next, tonumber, tostring, setmetatable, loadstring
-local format, upper, lower, gmatch, gsub, find, rep = string.format, string.upper, string.lower, string.gmatch, string.gsub, string.find, string.rep
-local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
-
-local setmetatableindex = table.setmetatableindex
-
--- beware, this is not xpath ... e.g. position is different (currently) and
--- we have reverse-sibling as reversed preceding sibling
-
---[[ldx--
-This module can be used stand alone but also inside in
-which case it hooks into the tracker code. Therefore we provide a few
-functions that set the tracers. Here we overload a previously defined
-function.
-If I can get in the mood I will make a variant that is XSLT compliant
-but I wonder if it makes sense.
---ldx]]--
-
---[[ldx--
-Expecially the lpath code is experimental, we will support some of xpath, but
-only things that make sense for us; as compensation it is possible to hook in your
-own functions. Apart from preprocessing content for we also need
-this module for process management, like handling and
-files.
-
-
-a/b/c /*/c
-a/b/c/first() a/b/c/last() a/b/c/index(n) a/b/c/index(-n)
-a/b/c/text() a/b/c/text(1) a/b/c/text(-1) a/b/c/text(n)
-
---ldx]]--
-
-local trace_lpath = false if trackers then trackers.register("xml.path", function(v) trace_lpath = v end) end
-local trace_lparse = false if trackers then trackers.register("xml.parse", function(v) trace_lparse = v end) end
-local trace_lprofile = false if trackers then trackers.register("xml.profile", function(v) trace_lpath = v trace_lparse = v trace_lprofile = v end) end
-
-local report_lpath = logs.reporter("xml","lpath")
-
---[[ldx--
-We've now arrived at an interesting part: accessing the tree using a subset
-of and since we're not compatible we call it . We
-will explain more about its usage in other documents.
---ldx]]--
-
-local xml = xml
-
-local lpathcalls = 0 function xml.lpathcalls () return lpathcalls end
-local lpathcached = 0 function xml.lpathcached() return lpathcached end
-
-xml.functions = xml.functions or { } -- internal
-local functions = xml.functions
-
-xml.expressions = xml.expressions or { } -- in expressions
-local expressions = xml.expressions
-
-xml.finalizers = xml.finalizers or { } -- fast do-with ... (with return value other than collection)
-local finalizers = xml.finalizers
-
-xml.specialhandler = xml.specialhandler or { }
-local specialhandler = xml.specialhandler
-
-lpegpatterns.xml = lpegpatterns.xml or { }
-local xmlpatterns = lpegpatterns.xml
-
-finalizers.xml = finalizers.xml or { }
-finalizers.tex = finalizers.tex or { }
-
-local function fallback (t, name)
- local fn = finalizers[name]
- if fn then
- t[name] = fn
- else
- report_lpath("unknown sub finalizer '%s'",tostring(name))
- fn = function() end
- end
- return fn
-end
-
-setmetatableindex(finalizers.xml, fallback)
-setmetatableindex(finalizers.tex, fallback)
-
-xml.defaultprotocol = "xml"
-
--- as xsl does not follow xpath completely here we will also
--- be more liberal especially with regards to the use of | and
--- the rootpath:
---
--- test : all 'test' under current
--- /test : 'test' relative to current
--- a|b|c : set of names
--- (a|b|c) : idem
--- ! : not
---
--- after all, we're not doing transformations but filtering. in
--- addition we provide filter functions (last bit)
---
--- todo: optimizer
---
--- .. : parent
--- * : all kids
--- / : anchor here
--- // : /**/
--- ** : all in between
---
--- so far we had (more practical as we don't transform)
---
--- {/test} : kids 'test' under current node
--- {test} : any kid with tag 'test'
--- {//test} : same as above
-
--- evaluator (needs to be redone, for the moment copied)
-
--- todo: apply_axis(list,notable) and collection vs single
-
-local apply_axis = { }
-
-apply_axis['root'] = function(list)
- local collected = { }
- for l=1,#list do
- local ll = list[l]
- local rt = ll
- while ll do
- ll = ll.__p__
- if ll then
- rt = ll
- end
- end
- collected[l] = rt
- end
- return collected
-end
-
-apply_axis['self'] = function(list)
- return list
-end
-
-apply_axis['child'] = function(list)
- local collected, c = { }, 0
- for l=1,#list do
- local ll = list[l]
- local dt = ll.dt
- if dt then -- weird that this is needed
- local en = 0
- for k=1,#dt do
- local dk = dt[k]
- if dk.tg then
- c = c + 1
- collected[c] = dk
- dk.ni = k -- refresh
- en = en + 1
- dk.ei = en
- end
- end
- ll.en = en
- end
- end
- return collected
-end
-
-local function collect(list,collected,c)
- local dt = list.dt
- if dt then
- local en = 0
- for k=1,#dt do
- local dk = dt[k]
- if dk.tg then
- c = c + 1
- collected[c] = dk
- dk.ni = k -- refresh
- en = en + 1
- dk.ei = en
- c = collect(dk,collected,c)
- end
- end
- list.en = en
- end
- return c
-end
-
-apply_axis['descendant'] = function(list)
- local collected, c = { }, 0
- for l=1,#list do
- c = collect(list[l],collected,c)
- end
- return collected
-end
-
-local function collect(list,collected,c)
- local dt = list.dt
- if dt then
- local en = 0
- for k=1,#dt do
- local dk = dt[k]
- if dk.tg then
- c = c + 1
- collected[c] = dk
- dk.ni = k -- refresh
- en = en + 1
- dk.ei = en
- c = collect(dk,collected,c)
- end
- end
- list.en = en
- end
- return c
-end
-apply_axis['descendant-or-self'] = function(list)
- local collected, c = { }, 0
- for l=1,#list do
- local ll = list[l]
- if ll.special ~= true then -- catch double root
- c = c + 1
- collected[c] = ll
- end
- c = collect(ll,collected,c)
- end
- return collected
-end
-
-apply_axis['ancestor'] = function(list)
- local collected, c = { }, 0
- for l=1,#list do
- local ll = list[l]
- while ll do
- ll = ll.__p__
- if ll then
- c = c + 1
- collected[c] = ll
- end
- end
- end
- return collected
-end
-
-apply_axis['ancestor-or-self'] = function(list)
- local collected, c = { }, 0
- for l=1,#list do
- local ll = list[l]
- c = c + 1
- collected[c] = ll
- while ll do
- ll = ll.__p__
- if ll then
- c = c + 1
- collected[c] = ll
- end
- end
- end
- return collected
-end
-
-apply_axis['parent'] = function(list)
- local collected, c = { }, 0
- for l=1,#list do
- local pl = list[l].__p__
- if pl then
- c = c + 1
- collected[c] = pl
- end
- end
- return collected
-end
-
-apply_axis['attribute'] = function(list)
- return { }
-end
-
-apply_axis['namespace'] = function(list)
- return { }
-end
-
-apply_axis['following'] = function(list) -- incomplete
- return { }
-end
-
-apply_axis['preceding'] = function(list) -- incomplete
- return { }
-end
-
-apply_axis['following-sibling'] = function(list)
- local collected, c = { }, 0
- for l=1,#list do
- local ll = list[l]
- local p = ll.__p__
- local d = p.dt
- for i=ll.ni+1,#d do
- local di = d[i]
- if type(di) == "table" then
- c = c + 1
- collected[c] = di
- end
- end
- end
- return collected
-end
-
-apply_axis['preceding-sibling'] = function(list)
- local collected, c = { }, 0
- for l=1,#list do
- local ll = list[l]
- local p = ll.__p__
- local d = p.dt
- for i=1,ll.ni-1 do
- local di = d[i]
- if type(di) == "table" then
- c = c + 1
- collected[c] = di
- end
- end
- end
- return collected
-end
-
-apply_axis['reverse-sibling'] = function(list) -- reverse preceding
- local collected, c = { }, 0
- for l=1,#list do
- local ll = list[l]
- local p = ll.__p__
- local d = p.dt
- for i=ll.ni-1,1,-1 do
- local di = d[i]
- if type(di) == "table" then
- c = c + 1
- collected[c] = di
- end
- end
- end
- return collected
-end
-
-apply_axis['auto-descendant-or-self'] = apply_axis['descendant-or-self']
-apply_axis['auto-descendant'] = apply_axis['descendant']
-apply_axis['auto-child'] = apply_axis['child']
-apply_axis['auto-self'] = apply_axis['self']
-apply_axis['initial-child'] = apply_axis['child']
-
-local function apply_nodes(list,directive,nodes)
- -- todo: nodes[1] etc ... negated node name in set ... when needed
- -- ... currently ignored
- local maxn = #nodes
- if maxn == 3 then --optimized loop
- local nns, ntg = nodes[2], nodes[3]
- if not nns and not ntg then -- wildcard
- if directive then
- return list
- else
- return { }
- end
- else
- local collected, c, m, p = { }, 0, 0, nil
- if not nns then -- only check tag
- for l=1,#list do
- local ll = list[l]
- local ltg = ll.tg
- if ltg then
- if directive then
- if ntg == ltg then
- local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
- c = c + 1
- collected[c], ll.mi = ll, m
- end
- elseif ntg ~= ltg then
- local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
- c = c + 1
- collected[c], ll.mi = ll, m
- end
- end
- end
- elseif not ntg then -- only check namespace
- for l=1,#list do
- local ll = list[l]
- local lns = ll.rn or ll.ns
- if lns then
- if directive then
- if lns == nns then
- local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
- c = c + 1
- collected[c], ll.mi = ll, m
- end
- elseif lns ~= nns then
- local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
- c = c + 1
- collected[c], ll.mi = ll, m
- end
- end
- end
- else -- check both
- for l=1,#list do
- local ll = list[l]
- local ltg = ll.tg
- if ltg then
- local lns = ll.rn or ll.ns
- local ok = ltg == ntg and lns == nns
- if directive then
- if ok then
- local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
- c = c + 1
- collected[c], ll.mi = ll, m
- end
- elseif not ok then
- local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
- c = c + 1
- collected[c], ll.mi = ll, m
- end
- end
- end
- end
- return collected
- end
- else
- local collected, c, m, p = { }, 0, 0, nil
- for l=1,#list do
- local ll = list[l]
- local ltg = ll.tg
- if ltg then
- local lns = ll.rn or ll.ns
- local ok = false
- for n=1,maxn,3 do
- local nns, ntg = nodes[n+1], nodes[n+2]
- ok = (not ntg or ltg == ntg) and (not nns or lns == nns)
- if ok then
- break
- end
- end
- if directive then
- if ok then
- local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
- c = c + 1
- collected[c], ll.mi = ll, m
- end
- elseif not ok then
- local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
- c = c + 1
- collected[c], ll.mi = ll, m
- end
- end
- end
- return collected
- end
-end
-
-local quit_expression = false
-
-local function apply_expression(list,expression,order)
- local collected, c = { }, 0
- quit_expression = false
- for l=1,#list do
- local ll = list[l]
- if expression(list,ll,l,order) then -- nasty, order alleen valid als n=1
- c = c + 1
- collected[c] = ll
- end
- if quit_expression then
- break
- end
- end
- return collected
-end
-
-local P, V, C, Cs, Cc, Ct, R, S, Cg, Cb = lpeg.P, lpeg.V, lpeg.C, lpeg.Cs, lpeg.Cc, lpeg.Ct, lpeg.R, lpeg.S, lpeg.Cg, lpeg.Cb
-
-local spaces = S(" \n\r\t\f")^0
-local lp_space = S(" \n\r\t\f")
-local lp_any = P(1)
-local lp_noequal = P("!=") / "~=" + P("<=") + P(">=") + P("==")
-local lp_doequal = P("=") / "=="
-local lp_or = P("|") / " or "
-local lp_and = P("&") / " and "
-
-local lp_builtin = P (
- P("text") / "(ll.dt[1] or '')" + -- fragile
- P("content") / "ll.dt" +
- -- P("name") / "(ll.ns~='' and ll.ns..':'..ll.tg)" +
- P("name") / "((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)" +
- P("tag") / "ll.tg" +
- P("position") / "l" + -- is element in finalizer
- P("firstindex") / "1" +
- P("lastindex") / "(#ll.__p__.dt or 1)" +
- P("firstelement") / "1" +
- P("lastelement") / "(ll.__p__.en or 1)" +
- P("first") / "1" +
- P("last") / "#list" +
- P("rootposition") / "order" +
- P("order") / "order" +
- P("element") / "(ll.ei or 1)" +
- P("index") / "(ll.ni or 1)" +
- P("match") / "(ll.mi or 1)" +
- -- P("namespace") / "ll.ns" +
- P("ns") / "ll.ns"
- ) * ((spaces * P("(") * spaces * P(")"))/"")
-
--- for the moment we keep namespaces with attributes
-
-local lp_attribute = (P("@") + P("attribute::")) / "" * Cc("(ll.at and ll.at['") * ((R("az","AZ") + S("-_:"))^1) * Cc("'])")
-local lp_fastpos_p = ((P("+")^0 * R("09")^1 * P(-1)) / function(s) return "l==" .. s end)
-local lp_fastpos_n = ((P("-") * R("09")^1 * P(-1)) / function(s) return "(" .. s .. "<0 and (#list+".. s .. "==l))" end)
-local lp_fastpos = lp_fastpos_n + lp_fastpos_p
-local lp_reserved = C("and") + C("or") + C("not") + C("div") + C("mod") + C("true") + C("false")
-
-local lp_lua_function = C(R("az","AZ","__")^1 * (P(".") * R("az","AZ","__")^1)^1) * ("(") / function(t) -- todo: better . handling
- return t .. "("
-end
-
-local lp_function = C(R("az","AZ","__")^1) * P("(") / function(t) -- todo: better . handling
- if expressions[t] then
- return "expr." .. t .. "("
- else
- return "expr.error("
- end
-end
-
-local lparent = P("(")
-local rparent = P(")")
-local noparent = 1 - (lparent+rparent)
-local nested = P{lparent * (noparent + V(1))^0 * rparent}
-local value = P(lparent * C((noparent + nested)^0) * rparent) -- P{"("*C(((1-S("()"))+V(1))^0)*")"}
-
-local lp_child = Cc("expr.child(ll,'") * R("az","AZ","--","__")^1 * Cc("')")
-local lp_number = S("+-") * R("09")^1
-local lp_string = Cc("'") * R("az","AZ","--","__")^1 * Cc("'")
-local lp_content = (P("'") * (1-P("'"))^0 * P("'") + P('"') * (1-P('"'))^0 * P('"'))
-
-local cleaner
-
-local lp_special = (C(P("name")+P("text")+P("tag")+P("count")+P("child"))) * value / function(t,s)
- if expressions[t] then
- s = s and s ~= "" and lpegmatch(cleaner,s)
- if s and s ~= "" then
- return "expr." .. t .. "(ll," .. s ..")"
- else
- return "expr." .. t .. "(ll)"
- end
- else
- return "expr.error(" .. t .. ")"
- end
-end
-
-local content =
- lp_builtin +
- lp_attribute +
- lp_special +
- lp_noequal + lp_doequal +
- lp_or + lp_and +
- lp_reserved +
- lp_lua_function + lp_function +
- lp_content + -- too fragile
- lp_child +
- lp_any
-
-local converter = Cs (
- lp_fastpos + (P { lparent * (V(1))^0 * rparent + content } )^0
-)
-
-cleaner = Cs ( (
- lp_reserved +
- lp_number +
- lp_string +
-1 )^1 )
-
-
-
-local template_e = [[
- local expr = xml.expressions
- return function(list,ll,l,order)
- return %s
- end
-]]
-
-local template_f_y = [[
- local finalizer = xml.finalizers['%s']['%s']
- return function(collection)
- return finalizer(collection,%s)
- end
-]]
-
-local template_f_n = [[
- return xml.finalizers['%s']['%s']
-]]
-
---
-
-local register_self = { kind = "axis", axis = "self" } -- , apply = apply_axis["self"] }
-local register_parent = { kind = "axis", axis = "parent" } -- , apply = apply_axis["parent"] }
-local register_descendant = { kind = "axis", axis = "descendant" } -- , apply = apply_axis["descendant"] }
-local register_child = { kind = "axis", axis = "child" } -- , apply = apply_axis["child"] }
-local register_descendant_or_self = { kind = "axis", axis = "descendant-or-self" } -- , apply = apply_axis["descendant-or-self"] }
-local register_root = { kind = "axis", axis = "root" } -- , apply = apply_axis["root"] }
-local register_ancestor = { kind = "axis", axis = "ancestor" } -- , apply = apply_axis["ancestor"] }
-local register_ancestor_or_self = { kind = "axis", axis = "ancestor-or-self" } -- , apply = apply_axis["ancestor-or-self"] }
-local register_attribute = { kind = "axis", axis = "attribute" } -- , apply = apply_axis["attribute"] }
-local register_namespace = { kind = "axis", axis = "namespace" } -- , apply = apply_axis["namespace"] }
-local register_following = { kind = "axis", axis = "following" } -- , apply = apply_axis["following"] }
-local register_following_sibling = { kind = "axis", axis = "following-sibling" } -- , apply = apply_axis["following-sibling"] }
-local register_preceding = { kind = "axis", axis = "preceding" } -- , apply = apply_axis["preceding"] }
-local register_preceding_sibling = { kind = "axis", axis = "preceding-sibling" } -- , apply = apply_axis["preceding-sibling"] }
-local register_reverse_sibling = { kind = "axis", axis = "reverse-sibling" } -- , apply = apply_axis["reverse-sibling"] }
-
-local register_auto_descendant_or_self = { kind = "axis", axis = "auto-descendant-or-self" } -- , apply = apply_axis["auto-descendant-or-self"] }
-local register_auto_descendant = { kind = "axis", axis = "auto-descendant" } -- , apply = apply_axis["auto-descendant"] }
-local register_auto_self = { kind = "axis", axis = "auto-self" } -- , apply = apply_axis["auto-self"] }
-local register_auto_child = { kind = "axis", axis = "auto-child" } -- , apply = apply_axis["auto-child"] }
-
-local register_initial_child = { kind = "axis", axis = "initial-child" } -- , apply = apply_axis["initial-child"] }
-
-local register_all_nodes = { kind = "nodes", nodetest = true, nodes = { true, false, false } }
-
-local skip = { }
-
-local function errorrunner_e(str,cnv)
- if not skip[str] then
- report_lpath("error in expression: %s => %s",str,cnv)
- skip[str] = cnv or str
- end
- return false
-end
-local function errorrunner_f(str,arg)
- report_lpath("error in finalizer: %s(%s)",str,arg or "")
- return false
-end
-
-local function register_nodes(nodetest,nodes)
- return { kind = "nodes", nodetest = nodetest, nodes = nodes }
-end
-
-local function register_expression(expression)
- local converted = lpegmatch(converter,expression)
- local runner = loadstring(format(template_e,converted))
- runner = (runner and runner()) or function() errorrunner_e(expression,converted) end
- return { kind = "expression", expression = expression, converted = converted, evaluator = runner }
-end
-
-local function register_finalizer(protocol,name,arguments)
- local runner
- if arguments and arguments ~= "" then
- runner = loadstring(format(template_f_y,protocol or xml.defaultprotocol,name,arguments))
- else
- runner = loadstring(format(template_f_n,protocol or xml.defaultprotocol,name))
- end
- runner = (runner and runner()) or function() errorrunner_f(name,arguments) end
- return { kind = "finalizer", name = name, arguments = arguments, finalizer = runner }
-end
-
-local expression = P { "ex",
- ex = "[" * C((V("sq") + V("dq") + (1 - S("[]")) + V("ex"))^0) * "]",
- sq = "'" * (1 - S("'"))^0 * "'",
- dq = '"' * (1 - S('"'))^0 * '"',
-}
-
-local arguments = P { "ar",
- ar = "(" * Cs((V("sq") + V("dq") + V("nq") + P(1-P(")")))^0) * ")",
- nq = ((1 - S("),'\""))^1) / function(s) return format("%q",s) end,
- sq = P("'") * (1 - P("'"))^0 * P("'"),
- dq = P('"') * (1 - P('"'))^0 * P('"'),
-}
-
--- todo: better arg parser
-
-local function register_error(str)
- return { kind = "error", error = format("unparsed: %s",str) }
-end
-
--- there is a difference in * and /*/ and so we need to catch a few special cases
-
-local special_1 = P("*") * Cc(register_auto_descendant) * Cc(register_all_nodes) -- last one not needed
-local special_2 = P("/") * Cc(register_auto_self)
-local special_3 = P("") * Cc(register_auto_self)
-
-local no_nextcolon = P(-1) + #(1-P(":")) -- newer lpeg needs the P(-1)
-local no_nextlparent = P(-1) + #(1-P("(")) -- newer lpeg needs the P(-1)
-
-local pathparser = Ct { "patterns", -- can be made a bit faster by moving some patterns outside
-
- patterns = spaces * V("protocol") * spaces * (
- ( V("special") * spaces * P(-1) ) +
- ( V("initial") * spaces * V("step") * spaces * (P("/") * spaces * V("step") * spaces)^0 )
- ),
-
- protocol = Cg(V("letters"),"protocol") * P("://") + Cg(Cc(nil),"protocol"),
-
- -- the / is needed for // as descendant or self is somewhat special
- -- step = (V("shortcuts") + V("axis") * spaces * V("nodes")^0 + V("error")) * spaces * V("expressions")^0 * spaces * V("finalizer")^0,
- step = ((V("shortcuts") + P("/") + V("axis")) * spaces * V("nodes")^0 + V("error")) * spaces * V("expressions")^0 * spaces * V("finalizer")^0,
-
- axis = V("descendant") + V("child") + V("parent") + V("self") + V("root") + V("ancestor") +
- V("descendant_or_self") + V("following_sibling") + V("following") +
- V("reverse_sibling") + V("preceding_sibling") + V("preceding") + V("ancestor_or_self") +
- #(1-P(-1)) * Cc(register_auto_child),
-
- special = special_1 + special_2 + special_3,
-
- initial = (P("/") * spaces * Cc(register_initial_child))^-1,
-
- error = (P(1)^1) / register_error,
-
- shortcuts_a = V("s_descendant_or_self") + V("s_descendant") + V("s_child") + V("s_parent") + V("s_self") + V("s_root") + V("s_ancestor"),
-
- shortcuts = V("shortcuts_a") * (spaces * "/" * spaces * V("shortcuts_a"))^0,
-
- s_descendant_or_self = (P("***/") + P("/")) * Cc(register_descendant_or_self), --- *** is a bonus
- s_descendant = P("**") * Cc(register_descendant),
- s_child = P("*") * no_nextcolon * Cc(register_child ),
- s_parent = P("..") * Cc(register_parent ),
- s_self = P("." ) * Cc(register_self ),
- s_root = P("^^") * Cc(register_root ),
- s_ancestor = P("^") * Cc(register_ancestor ),
-
- descendant = P("descendant::") * Cc(register_descendant ),
- child = P("child::") * Cc(register_child ),
- parent = P("parent::") * Cc(register_parent ),
- self = P("self::") * Cc(register_self ),
- root = P('root::') * Cc(register_root ),
- ancestor = P('ancestor::') * Cc(register_ancestor ),
- descendant_or_self = P('descendant-or-self::') * Cc(register_descendant_or_self ),
- ancestor_or_self = P('ancestor-or-self::') * Cc(register_ancestor_or_self ),
- -- attribute = P('attribute::') * Cc(register_attribute ),
- -- namespace = P('namespace::') * Cc(register_namespace ),
- following = P('following::') * Cc(register_following ),
- following_sibling = P('following-sibling::') * Cc(register_following_sibling ),
- preceding = P('preceding::') * Cc(register_preceding ),
- preceding_sibling = P('preceding-sibling::') * Cc(register_preceding_sibling ),
- reverse_sibling = P('reverse-sibling::') * Cc(register_reverse_sibling ),
-
- nodes = (V("nodefunction") * spaces * P("(") * V("nodeset") * P(")") + V("nodetest") * V("nodeset")) / register_nodes,
-
- expressions = expression / register_expression,
-
- letters = R("az")^1,
- name = (1-S("/[]()|:*!"))^1, -- make inline
- negate = P("!") * Cc(false),
-
- nodefunction = V("negate") + P("not") * Cc(false) + Cc(true),
- nodetest = V("negate") + Cc(true),
- nodename = (V("negate") + Cc(true)) * spaces * ((V("wildnodename") * P(":") * V("wildnodename")) + (Cc(false) * V("wildnodename"))),
- wildnodename = (C(V("name")) + P("*") * Cc(false)) * no_nextlparent,
- nodeset = spaces * Ct(V("nodename") * (spaces * P("|") * spaces * V("nodename"))^0) * spaces,
-
- finalizer = (Cb("protocol") * P("/")^-1 * C(V("name")) * arguments * P(-1)) / register_finalizer,
-
-}
-
-xmlpatterns.pathparser = pathparser
-
-local cache = { }
-
-local function nodesettostring(set,nodetest)
- local t = { }
- for i=1,#set,3 do
- local directive, ns, tg = set[i], set[i+1], set[i+2]
- if not ns or ns == "" then ns = "*" end
- if not tg or tg == "" then tg = "*" end
- tg = (tg == "@rt@" and "[root]") or format("%s:%s",ns,tg)
- t[i] = (directive and tg) or format("not(%s)",tg)
- end
- if nodetest == false then
- return format("not(%s)",concat(t,"|"))
- else
- return concat(t,"|")
- end
-end
-
-local function tagstostring(list)
- if #list == 0 then
- return "no elements"
- else
- local t = { }
- for i=1, #list do
- local li = list[i]
- local ns, tg = li.ns, li.tg
- if not ns or ns == "" then ns = "*" end
- if not tg or tg == "" then tg = "*" end
- t[i] = (tg == "@rt@" and "[root]") or format("%s:%s",ns,tg)
- end
- return concat(t," ")
- end
-end
-
-xml.nodesettostring = nodesettostring
-
-local lpath -- we have a harmless kind of circular reference
-
-local lshowoptions = { functions = false }
-
-local function lshow(parsed)
- if type(parsed) == "string" then
- parsed = lpath(parsed)
- end
- report_lpath("%s://%s => %s",parsed.protocol or xml.defaultprotocol,parsed.pattern,
- table.serialize(parsed,false,lshowoptions))
-end
-
-xml.lshow = lshow
-
-local function add_comment(p,str)
- local pc = p.comment
- if not pc then
- p.comment = { str }
- else
- pc[#pc+1] = str
- end
-end
-
-lpath = function (pattern) -- the gain of caching is rather minimal
- lpathcalls = lpathcalls + 1
- if type(pattern) == "table" then
- return pattern
- else
- local parsed = cache[pattern]
- if parsed then
- lpathcached = lpathcached + 1
- else
- parsed = lpegmatch(pathparser,pattern)
- if parsed then
- parsed.pattern = pattern
- local np = #parsed
- if np == 0 then
- parsed = { pattern = pattern, register_self, state = "parsing error" }
- report_lpath("parsing error in '%s'",pattern)
- lshow(parsed)
- else
- -- we could have done this with a more complex parser but this
- -- is cleaner
- local pi = parsed[1]
- if pi.axis == "auto-child" then
- if false then
- add_comment(parsed, "auto-child replaced by auto-descendant-or-self")
- parsed[1] = register_auto_descendant_or_self
- else
- add_comment(parsed, "auto-child replaced by auto-descendant")
- parsed[1] = register_auto_descendant
- end
- elseif pi.axis == "initial-child" and np > 1 and parsed[2].axis then
- add_comment(parsed, "initial-child removed") -- we could also make it a auto-self
- remove(parsed,1)
- end
- local np = #parsed -- can have changed
- if np > 1 then
- local pnp = parsed[np]
- if pnp.kind == "nodes" and pnp.nodetest == true then
- local nodes = pnp.nodes
- if nodes[1] == true and nodes[2] == false and nodes[3] == false then
- add_comment(parsed, "redundant final wildcard filter removed")
- remove(parsed,np)
- end
- end
- end
- end
- else
- parsed = { pattern = pattern }
- end
- cache[pattern] = parsed
- if trace_lparse and not trace_lprofile then
- lshow(parsed)
- end
- end
- return parsed
- end
-end
-
-xml.lpath = lpath
-
--- we can move all calls inline and then merge the trace back
--- technically we can combine axis and the next nodes which is
--- what we did before but this a bit cleaner (but slower too)
--- but interesting is that it's not that much faster when we
--- go inline
---
--- beware: we need to return a collection even when we filter
--- else the (simple) cache gets messed up
-
--- caching found lookups saves not that much (max .1 sec on a 8 sec run)
--- and it also messes up finalizers
-
--- watch out: when there is a finalizer, it's always called as there
--- can be cases that a finalizer returns (or does) something in case
--- there is no match; an example of this is count()
-
-local profiled = { } xml.profiled = profiled
-
-local function profiled_apply(list,parsed,nofparsed,order)
- local p = profiled[parsed.pattern]
- if p then
- p.tested = p.tested + 1
- else
- p = { tested = 1, matched = 0, finalized = 0 }
- profiled[parsed.pattern] = p
- end
- local collected = list
- for i=1,nofparsed do
- local pi = parsed[i]
- local kind = pi.kind
- if kind == "axis" then
- collected = apply_axis[pi.axis](collected)
- elseif kind == "nodes" then
- collected = apply_nodes(collected,pi.nodetest,pi.nodes)
- elseif kind == "expression" then
- collected = apply_expression(collected,pi.evaluator,order)
- elseif kind == "finalizer" then
- collected = pi.finalizer(collected) -- no check on # here
- p.matched = p.matched + 1
- p.finalized = p.finalized + 1
- return collected
- end
- if not collected or #collected == 0 then
- local pn = i < nofparsed and parsed[nofparsed]
- if pn and pn.kind == "finalizer" then
- collected = pn.finalizer(collected)
- p.finalized = p.finalized + 1
- return collected
- end
- return nil
- end
- end
- if collected then
- p.matched = p.matched + 1
- end
- return collected
-end
-
-local function traced_apply(list,parsed,nofparsed,order)
- if trace_lparse then
- lshow(parsed)
- end
- report_lpath("collecting: %s",parsed.pattern)
- report_lpath("root tags : %s",tagstostring(list))
- report_lpath("order : %s",order or "unset")
- local collected = list
- for i=1,nofparsed do
- local pi = parsed[i]
- local kind = pi.kind
- if kind == "axis" then
- collected = apply_axis[pi.axis](collected)
- report_lpath("% 10i : ax : %s",(collected and #collected) or 0,pi.axis)
- elseif kind == "nodes" then
- collected = apply_nodes(collected,pi.nodetest,pi.nodes)
- report_lpath("% 10i : ns : %s",(collected and #collected) or 0,nodesettostring(pi.nodes,pi.nodetest))
- elseif kind == "expression" then
- collected = apply_expression(collected,pi.evaluator,order)
- report_lpath("% 10i : ex : %s -> %s",(collected and #collected) or 0,pi.expression,pi.converted)
- elseif kind == "finalizer" then
- collected = pi.finalizer(collected)
- report_lpath("% 10i : fi : %s : %s(%s)",(type(collected) == "table" and #collected) or 0,parsed.protocol or xml.defaultprotocol,pi.name,pi.arguments or "")
- return collected
- end
- if not collected or #collected == 0 then
- local pn = i < nofparsed and parsed[nofparsed]
- if pn and pn.kind == "finalizer" then
- collected = pn.finalizer(collected)
- report_lpath("% 10i : fi : %s : %s(%s)",(type(collected) == "table" and #collected) or 0,parsed.protocol or xml.defaultprotocol,pn.name,pn.arguments or "")
- return collected
- end
- return nil
- end
- end
- return collected
-end
-
-local function normal_apply(list,parsed,nofparsed,order)
- local collected = list
- for i=1,nofparsed do
- local pi = parsed[i]
- local kind = pi.kind
- if kind == "axis" then
- local axis = pi.axis
- if axis ~= "self" then
- collected = apply_axis[axis](collected)
- end
- elseif kind == "nodes" then
- collected = apply_nodes(collected,pi.nodetest,pi.nodes)
- elseif kind == "expression" then
- collected = apply_expression(collected,pi.evaluator,order)
- elseif kind == "finalizer" then
- return pi.finalizer(collected)
- end
- if not collected or #collected == 0 then
- local pf = i < nofparsed and parsed[nofparsed].finalizer
- if pf then
- return pf(collected) -- can be anything
- end
- return nil
- end
- end
- return collected
-end
-
-
-local function applylpath(list,pattern)
- if not list then
- return
- end
- local parsed = cache[pattern]
- if parsed then
- lpathcalls = lpathcalls + 1
- lpathcached = lpathcached + 1
- elseif type(pattern) == "table" then
- lpathcalls = lpathcalls + 1
- parsed = pattern
- else
- parsed = lpath(pattern) or pattern
- end
- if not parsed then
- return
- end
- local nofparsed = #parsed
- if nofparsed == 0 then
- return -- something is wrong
- end
- if not trace_lpath then
- return normal_apply ({ list },parsed,nofparsed,list.mi)
- elseif trace_lprofile then
- return profiled_apply({ list },parsed,nofparsed,list.mi)
- else
- return traced_apply ({ list },parsed,nofparsed,list.mi)
- end
-end
-
-xml.applylpath = applylpath -- takes a table as first argment, which is what xml.filter will do
-
---[[ldx--
-This is the main filter function. It returns whatever is asked for.
---ldx]]--
-
-function xml.filter(root,pattern) -- no longer funny attribute handling here
- return applylpath(root,pattern)
-end
-
--- internal (parsed)
-
-expressions.child = function(e,pattern)
- return applylpath(e,pattern) -- todo: cache
-end
-expressions.count = function(e,pattern) -- what if pattern == empty or nil
- local collected = applylpath(e,pattern) -- todo: cache
- return pattern and (collected and #collected) or 0
-end
-
--- external
-
-expressions.oneof = function(s,...) -- slow
- local t = {...} for i=1,#t do if s == t[i] then return true end end return false
-end
-expressions.error = function(str)
- xml.errorhandler(format("unknown function in lpath expression: %s",tostring(str or "?")))
- return false
-end
-expressions.undefined = function(s)
- return s == nil
-end
-
-expressions.quit = function(s)
- if s or s == nil then
- quit_expression = true
- end
- return true
-end
-
-expressions.print = function(...)
- print(...)
- return true
-end
-
-expressions.contains = find
-expressions.find = find
-expressions.upper = upper
-expressions.lower = lower
-expressions.number = tonumber
-expressions.boolean = toboolean
-
-function expressions.contains(str,pattern)
- local t = type(str)
- if t == "string" then
- if find(str,pattern) then
- return true
- end
- elseif t == "table" then
- for i=1,#str do
- local d = str[i]
- if type(d) == "string" and find(d,pattern) then
- return true
- end
- end
- end
- return false
-end
-
--- user interface
-
-local function traverse(root,pattern,handle)
- report_lpath("use 'xml.selection' instead for '%s'",pattern)
- local collected = applylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local r = e.__p__
- handle(r,r.dt,e.ni)
- end
- end
-end
-
-local function selection(root,pattern,handle)
- local collected = applylpath(root,pattern)
- if collected then
- if handle then
- for c=1,#collected do
- handle(collected[c])
- end
- else
- return collected
- end
- end
-end
-
-xml.traverse = traverse -- old method, r, d, k
-xml.selection = selection -- new method, simple handle
-
-
--- generic function finalizer (independant namespace)
-
-local function dofunction(collected,fnc)
- if collected then
- local f = functions[fnc]
- if f then
- for c=1,#collected do
- f(collected[c])
- end
- else
- report_lpath("unknown function '%s'",fnc)
- end
- end
-end
-
-finalizers.xml["function"] = dofunction
-finalizers.tex["function"] = dofunction
-
--- functions
-
-expressions.text = function(e,n)
- local rdt = e.__p__.dt
- return (rdt and rdt[n]) or ""
-end
-
-expressions.name = function(e,n) -- ns + tg
- local found = false
- n = tonumber(n) or 0
- if n == 0 then
- found = type(e) == "table" and e
- elseif n < 0 then
- local d, k = e.__p__.dt, e.ni
- for i=k-1,1,-1 do
- local di = d[i]
- if type(di) == "table" then
- if n == -1 then
- found = di
- break
- else
- n = n + 1
- end
- end
- end
- else
- local d, k = e.__p__.dt, e.ni
- for i=k+1,#d,1 do
- local di = d[i]
- if type(di) == "table" then
- if n == 1 then
- found = di
- break
- else
- n = n - 1
- end
- end
- end
- end
- if found then
- local ns, tg = found.rn or found.ns or "", found.tg
- if ns ~= "" then
- return ns .. ":" .. tg
- else
- return tg
- end
- else
- return ""
- end
-end
-
-expressions.tag = function(e,n) -- only tg
- if not e then
- return ""
- else
- local found = false
- n = tonumber(n) or 0
- if n == 0 then
- found = (type(e) == "table") and e -- seems to fail
- elseif n < 0 then
- local d, k = e.__p__.dt, e.ni
- for i=k-1,1,-1 do
- local di = d[i]
- if type(di) == "table" then
- if n == -1 then
- found = di
- break
- else
- n = n + 1
- end
- end
- end
- else
- local d, k = e.__p__.dt, e.ni
- for i=k+1,#d,1 do
- local di = d[i]
- if type(di) == "table" then
- if n == 1 then
- found = di
- break
- else
- n = n - 1
- end
- end
- end
- end
- return (found and found.tg) or ""
- end
-end
-
---[[ldx--
-Often using an iterators looks nicer in the code than passing handler
-functions. The book describes how to use coroutines for that
-purpose ( ). This permits
-code like:
-
-
-for r, d, k in xml.elements(xml.load('text.xml'),"title") do
- print(d[k]) -- old method
-end
-for e in xml.collected(xml.load('text.xml'),"title") do
- print(e) -- new one
-end
-
---ldx]]--
-
-local wrap, yield = coroutine.wrap, coroutine.yield
-
-function xml.elements(root,pattern,reverse) -- r, d, k
- local collected = applylpath(root,pattern)
- if collected then
- if reverse then
- return wrap(function() for c=#collected,1,-1 do
- local e = collected[c] local r = e.__p__ yield(r,r.dt,e.ni)
- end end)
- else
- return wrap(function() for c=1,#collected do
- local e = collected[c] local r = e.__p__ yield(r,r.dt,e.ni)
- end end)
- end
- end
- return wrap(function() end)
-end
-
-function xml.collected(root,pattern,reverse) -- e
- local collected = applylpath(root,pattern)
- if collected then
- if reverse then
- return wrap(function() for c=#collected,1,-1 do yield(collected[c]) end end)
- else
- return wrap(function() for c=1,#collected do yield(collected[c]) end end)
- end
- end
- return wrap(function() end)
-end
-
--- handy
-
-function xml.inspect(collection,pattern)
- pattern = pattern or "."
- for e in xml.collected(collection,pattern or ".") do
- report_lpath("pattern %q\n\n%s\n",pattern,xml.tostring(e))
- end
-end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['lxml-mis'] = {
- version = 1.001,
- comment = "this module is the basis for the lxml-* ones",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local xml, lpeg, string = xml, lpeg, string
-
-local concat = table.concat
-local type, next, tonumber, tostring, setmetatable, loadstring = type, next, tonumber, tostring, setmetatable, loadstring
-local format, gsub, match = string.format, string.gsub, string.match
-local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
-local P, S, R, C, V, Cc, Cs = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.V, lpeg.Cc, lpeg.Cs
-
-lpegpatterns.xml = lpegpatterns.xml or { }
-local xmlpatterns = lpegpatterns.xml
-
---[[ldx--
-The following helper functions best belong to the lxml-ini
-module. Some are here because we need then in the mk
-document and other manuals, others came up when playing with
-this module. Since this module is also used in we've
-put them here instead of loading mode modules there then needed.
---ldx]]--
-
-local function xmlgsub(t,old,new) -- will be replaced
- local dt = t.dt
- if dt then
- for k=1,#dt do
- local v = dt[k]
- if type(v) == "string" then
- dt[k] = gsub(v,old,new)
- else
- xmlgsub(v,old,new)
- end
- end
- end
-end
-
-
-function xml.stripleadingspaces(dk,d,k) -- cosmetic, for manual
- if d and k then
- local dkm = d[k-1]
- if dkm and type(dkm) == "string" then
- local s = match(dkm,"\n(%s+)")
- xmlgsub(dk,"\n"..rep(" ",#s),"\n")
- end
- end
-end
-
-
-
--- 100 * 2500 * "oeps< oeps> oeps&" : gsub:lpeg|lpeg|lpeg
---
--- 1021:0335:0287:0247
-
--- 10 * 1000 * "oeps< oeps> oeps& asfjhalskfjh alskfjh alskfjh alskfjh ;al J;LSFDJ"
---
--- 1559:0257:0288:0190 (last one suggested by roberto)
-
--- escaped = Cs((S("<&>") / xml.escapes + 1)^0)
--- escaped = Cs((S("<")/"<" + S(">")/">" + S("&")/"&" + 1)^0)
-local normal = (1 - S("<&>"))^0
-local special = P("<")/"<" + P(">")/">" + P("&")/"&"
-local escaped = Cs(normal * (special * normal)^0)
-
--- 100 * 1000 * "oeps< oeps> oeps&" : gsub:lpeg == 0153:0280:0151:0080 (last one by roberto)
-
-local normal = (1 - S"&")^0
-local special = P("<")/"<" + P(">")/">" + P("&")/"&"
-local unescaped = Cs(normal * (special * normal)^0)
-
--- 100 * 5000 * "oeps oeps oeps " : gsub:lpeg == 623:501 msec (short tags, less difference)
-
-local cleansed = Cs(((P("<") * (1-P(">"))^0 * P(">"))/"" + 1)^0)
-
-xmlpatterns.escaped = escaped
-xmlpatterns.unescaped = unescaped
-xmlpatterns.cleansed = cleansed
-
-function xml.escaped (str) return lpegmatch(escaped,str) end
-function xml.unescaped(str) return lpegmatch(unescaped,str) end
-function xml.cleansed (str) return lpegmatch(cleansed,str) end
-
--- this might move
-
-function xml.fillin(root,pattern,str,check)
- local e = xml.first(root,pattern)
- if e then
- local n = #e.dt
- if not check or n == 0 or (n == 1 and e.dt[1] == "") then
- e.dt = { str }
- end
- end
-end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['lxml-aux'] = {
- version = 1.001,
- comment = "this module is the basis for the lxml-* ones",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- not all functions here make sense anymore vbut we keep them for
--- compatibility reasons
-
-local trace_manipulations = false trackers.register("lxml.manipulations", function(v) trace_manipulations = v end)
-
-local report_xml = logs.reporter("xml")
-
-local xml = xml
-
-local xmlconvert, xmlcopy, xmlname = xml.convert, xml.copy, xml.name
-local xmlinheritedconvert = xml.inheritedconvert
-local xmlapplylpath = xml.applylpath
-local xmlfilter = xml.filter
-
-local type, setmetatable, getmetatable = type, setmetatable, getmetatable
-local insert, remove, fastcopy, concat = table.insert, table.remove, table.fastcopy, table.concat
-local gmatch, gsub, format, find, strip = string.gmatch, string.gsub, string.format, string.find, string.strip
-local utfbyte = utf.byte
-
-local function report(what,pattern,c,e)
- report_xml("%s element '%s' (root: '%s', position: %s, index: %s, pattern: %s)",what,xmlname(e),xmlname(e.__p__),c,e.ni,pattern)
-end
-
-local function withelements(e,handle,depth)
- if e and handle then
- local edt = e.dt
- if edt then
- depth = depth or 0
- for i=1,#edt do
- local e = edt[i]
- if type(e) == "table" then
- handle(e,depth)
- withelements(e,handle,depth+1)
- end
- end
- end
- end
-end
-
-xml.withelements = withelements
-
-function xml.withelement(e,n,handle) -- slow
- if e and n ~= 0 and handle then
- local edt = e.dt
- if edt then
- if n > 0 then
- for i=1,#edt do
- local ei = edt[i]
- if type(ei) == "table" then
- if n == 1 then
- handle(ei)
- return
- else
- n = n - 1
- end
- end
- end
- elseif n < 0 then
- for i=#edt,1,-1 do
- local ei = edt[i]
- if type(ei) == "table" then
- if n == -1 then
- handle(ei)
- return
- else
- n = n + 1
- end
- end
- end
- end
- end
- end
-end
-
-function xml.each(root,pattern,handle,reverse)
- local collected = xmlapplylpath(root,pattern)
- if collected then
- if reverse then
- for c=#collected,1,-1 do
- handle(collected[c])
- end
- else
- for c=1,#collected do
- handle(collected[c])
- end
- end
- return collected
- end
-end
-
-function xml.processattributes(root,pattern,handle)
- local collected = xmlapplylpath(root,pattern)
- if collected and handle then
- for c=1,#collected do
- handle(collected[c].at)
- end
- end
- return collected
-end
-
---[[ldx--
-The following functions collect elements and texts.
---ldx]]--
-
--- are these still needed -> lxml-cmp.lua
-
-function xml.collect(root, pattern)
- return xmlapplylpath(root,pattern)
-end
-
-function xml.collecttexts(root, pattern, flatten) -- todo: variant with handle
- local collected = xmlapplylpath(root,pattern)
- if collected and flatten then
- local xmltostring = xml.tostring
- for c=1,#collected do
- collected[c] = xmltostring(collected[c].dt)
- end
- end
- return collected or { }
-end
-
-function xml.collect_tags(root, pattern, nonamespace)
- local collected = xmlapplylpath(root,pattern)
- if collected then
- local t, n = { }, 0
- for c=1,#collected do
- local e = collected[c]
- local ns, tg = e.ns, e.tg
- n = n + 1
- if nonamespace then
- t[n] = tg
- elseif ns == "" then
- t[n] = tg
- else
- t[n] = ns .. ":" .. tg
- end
- end
- return t
- end
-end
-
---[[ldx--
-We've now arrived at the functions that manipulate the tree.
---ldx]]--
-
-local no_root = { no_root = true }
-
-local function redo_ni(d)
- for k=1,#d do
- local dk = d[k]
- if type(dk) == "table" then
- dk.ni = k
- end
- end
-end
-
-local function xmltoelement(whatever,root)
- if not whatever then
- return nil
- end
- local element
- if type(whatever) == "string" then
- element = xmlinheritedconvert(whatever,root) -- beware, not really a root
- else
- element = whatever -- we assume a table
- end
- if element.error then
- return whatever -- string
- end
- if element then
- end
- return element
-end
-
-xml.toelement = xmltoelement
-
-local function copiedelement(element,newparent)
- if type(element) == "string" then
- return element
- else
- element = xmlcopy(element).dt
- if newparent and type(element) == "table" then
- element.__p__ = newparent
- end
- return element
- end
-end
-
-function xml.delete(root,pattern)
- if not pattern or pattern == "" then
- local p = root.__p__
- if p then
- if trace_manipulations then
- report('deleting',"--",c,root)
- end
- local d = p.dt
- remove(d,root.ni)
- redo_ni(d) -- can be made faster and inlined
- end
- else
- local collected = xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local p = e.__p__
- if p then
- if trace_manipulations then
- report('deleting',pattern,c,e)
- end
- local d = p.dt
- remove(d,e.ni)
- redo_ni(d) -- can be made faster and inlined
- end
- end
- end
- end
-end
-
-function xml.replace(root,pattern,whatever)
- local element = root and xmltoelement(whatever,root)
- local collected = element and xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local p = e.__p__
- if p then
- if trace_manipulations then
- report('replacing',pattern,c,e)
- end
- local d = p.dt
- d[e.ni] = copiedelement(element,p)
- redo_ni(d) -- probably not needed
- end
- end
- end
-end
-
-local function wrap(e,wrapper)
- local t = {
- rn = e.rn,
- tg = e.tg,
- ns = e.ns,
- at = e.at,
- dt = e.dt,
- __p__ = e,
- }
- setmetatable(t,getmetatable(e))
- e.rn = wrapper.rn or e.rn or ""
- e.tg = wrapper.tg or e.tg or ""
- e.ns = wrapper.ns or e.ns or ""
- e.at = fastcopy(wrapper.at)
- e.dt = { t }
-end
-
-function xml.wrap(root,pattern,whatever)
- if whatever then
- local wrapper = xmltoelement(whatever,root)
- local collected = xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- if trace_manipulations then
- report('wrapping',pattern,c,e)
- end
- wrap(e,wrapper)
- end
- end
- else
- wrap(root,xmltoelement(pattern))
- end
-end
-
-local function inject_element(root,pattern,whatever,prepend)
- local element = root and xmltoelement(whatever,root)
- local collected = element and xmlapplylpath(root,pattern)
- local function inject_e(e)
- local r = e.__p__
- local d, k, rri = r.dt, e.ni, r.ri
- local edt = (rri and d[rri].dt) or (d and d[k] and d[k].dt)
- if edt then
- local be, af
- local cp = copiedelement(element,e)
- if prepend then
- be, af = cp, edt
- else
- be, af = edt, cp
- end
- local bn = #be
- for i=1,#af do
- bn = bn + 1
- be[bn] = af[i]
- end
- if rri then
- r.dt[rri].dt = be
- else
- d[k].dt = be
- end
- redo_ni(d)
- end
- end
- if not collected then
- -- nothing
- elseif collected.tg then
- -- first or so
- inject_e(collected)
- else
- for c=1,#collected do
- inject_e(collected[c])
- end
- end
-end
-
-local function insert_element(root,pattern,whatever,before) -- todo: element als functie
- local element = root and xmltoelement(whatever,root)
- local collected = element and xmlapplylpath(root,pattern)
- local function insert_e(e)
- local r = e.__p__
- local d, k = r.dt, e.ni
- if not before then
- k = k + 1
- end
- insert(d,k,copiedelement(element,r))
- redo_ni(d)
- end
- if not collected then
- -- nothing
- elseif collected.tg then
- -- first or so
- insert_e(collected)
- else
- for c=1,#collected do
- insert_e(collected[c])
- end
- end
-end
-
-xml.insert_element = insert_element
-xml.insertafter = insert_element
-xml.insertbefore = function(r,p,e) insert_element(r,p,e,true) end
-xml.injectafter = inject_element
-xml.injectbefore = function(r,p,e) inject_element(r,p,e,true) end
-
-local function include(xmldata,pattern,attribute,recursive,loaddata)
- -- parse="text" (default: xml), encoding="" (todo)
- -- attribute = attribute or 'href'
- pattern = pattern or 'include'
- loaddata = loaddata or io.loaddata
- local collected = xmlapplylpath(xmldata,pattern)
- if collected then
- for c=1,#collected do
- local ek = collected[c]
- local name = nil
- local ekdt = ek.dt
- local ekat = ek.at
- local epdt = ek.__p__.dt
- if not attribute or attribute == "" then
- name = (type(ekdt) == "table" and ekdt[1]) or ekdt -- check, probably always tab or str
- end
- if not name then
- for a in gmatch(attribute or "href","([^|]+)") do
- name = ekat[a]
- if name then break end
- end
- end
- local data = (name and name ~= "" and loaddata(name)) or ""
- if data == "" then
- epdt[ek.ni] = "" -- xml.empty(d,k)
- elseif ekat["parse"] == "text" then
- -- for the moment hard coded
- epdt[ek.ni] = xml.escaped(data) -- d[k] = xml.escaped(data)
- else
- local xi = xmlinheritedconvert(data,xmldata)
- if not xi then
- epdt[ek.ni] = "" -- xml.empty(d,k)
- else
- if recursive then
- include(xi,pattern,attribute,recursive,loaddata)
- end
- epdt[ek.ni] = xml.body(xi) -- xml.assign(d,k,xi)
- end
- end
- end
- end
-end
-
-xml.include = include
-
-local function stripelement(e,nolines,anywhere)
- local edt = e.dt
- if edt then
- if anywhere then
- local t, n = { }, 0
- for e=1,#edt do
- local str = edt[e]
- if type(str) ~= "string" then
- n = n + 1
- t[n] = str
- elseif str ~= "" then
- -- todo: lpeg for each case
- if nolines then
- str = gsub(str,"%s+"," ")
- end
- str = gsub(str,"^%s*(.-)%s*$","%1")
- if str ~= "" then
- n = n + 1
- t[n] = str
- end
- end
- end
- e.dt = t
- else
- -- we can assume a regular sparse xml table with no successive strings
- -- otherwise we should use a while loop
- if #edt > 0 then
- -- strip front
- local str = edt[1]
- if type(str) ~= "string" then
- -- nothing
- elseif str == "" then
- remove(edt,1)
- else
- if nolines then
- str = gsub(str,"%s+"," ")
- end
- str = gsub(str,"^%s+","")
- if str == "" then
- remove(edt,1)
- else
- edt[1] = str
- end
- end
- end
- local nedt = #edt
- if nedt > 0 then
- -- strip end
- local str = edt[nedt]
- if type(str) ~= "string" then
- -- nothing
- elseif str == "" then
- remove(edt)
- else
- if nolines then
- str = gsub(str,"%s+"," ")
- end
- str = gsub(str,"%s+$","")
- if str == "" then
- remove(edt)
- else
- edt[nedt] = str
- end
- end
- end
- end
- end
- return e -- convenient
-end
-
-xml.stripelement = stripelement
-
-function xml.strip(root,pattern,nolines,anywhere) -- strips all leading and trailing spacing
- local collected = xmlapplylpath(root,pattern) -- beware, indices no longer are valid now
- if collected then
- for i=1,#collected do
- stripelement(collected[i],nolines,anywhere)
- end
- end
-end
-
-local function renamespace(root, oldspace, newspace) -- fast variant
- local ndt = #root.dt
- for i=1,ndt or 0 do
- local e = root[i]
- if type(e) == "table" then
- if e.ns == oldspace then
- e.ns = newspace
- if e.rn then
- e.rn = newspace
- end
- end
- local edt = e.dt
- if edt then
- renamespace(edt, oldspace, newspace)
- end
- end
- end
-end
-
-xml.renamespace = renamespace
-
-function xml.remaptag(root, pattern, newtg)
- local collected = xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- collected[c].tg = newtg
- end
- end
-end
-
-function xml.remapnamespace(root, pattern, newns)
- local collected = xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- collected[c].ns = newns
- end
- end
-end
-
-function xml.checknamespace(root, pattern, newns)
- local collected = xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- if (not e.rn or e.rn == "") and e.ns == "" then
- e.rn = newns
- end
- end
- end
-end
-
-function xml.remapname(root, pattern, newtg, newns, newrn)
- local collected = xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- e.tg, e.ns, e.rn = newtg, newns, newrn
- end
- end
-end
-
---[[ldx--
-Helper (for q2p).
---ldx]]--
-
-function xml.cdatatotext(e)
- local dt = e.dt
- if #dt == 1 then
- local first = dt[1]
- if first.tg == "@cd@" then
- e.dt = first.dt
- end
- else
- -- maybe option
- end
-end
-
--- local x = xml.convert("12 3 ")
--- xml.texttocdata(xml.first(x,"a"))
--- print(x) -- 2 3]]>
-
-function xml.texttocdata(e) -- could be a finalizer
- local dt = e.dt
- local s = xml.tostring(dt) -- no shortcut?
- e.tg = "@cd@"
- e.special = true
- e.ns = ""
- e.rn = ""
- e.dt = { s }
- e.at = nil
-end
-
--- local x = xml.convert("12 3 ")
--- xml.tocdata(xml.first(x,"a"))
--- print(x) -- 12 3]]>
-
-function xml.elementtocdata(e) -- could be a finalizer
- local dt = e.dt
- local s = xml.tostring(e) -- no shortcut?
- e.tg = "@cd@"
- e.special = true
- e.ns = ""
- e.rn = ""
- e.dt = { s }
- e.at = nil
-end
-
-xml.builtinentities = table.tohash { "amp", "quot", "apos", "lt", "gt" } -- used often so share
-
-local entities = characters and characters.entities or nil
-local builtinentities = xml.builtinentities
-
-function xml.addentitiesdoctype(root,option) -- we could also have a 'resolve' i.e. inline hex
- if not entities then
- require("char-ent")
- entities = characters.entities
- end
- if entities and root and root.tg == "@rt@" and root.statistics then
- local list = { }
- local hexify = option == "hexadecimal"
- for k, v in table.sortedhash(root.statistics.entities.names) do
- if not builtinentities[k] then
- local e = entities[k]
- if not e then
- e = format("[%s]",k)
- elseif hexify then
- e = format("%05X;",utfbyte(k))
- end
- list[#list+1] = format(" ",k,e)
- end
- end
- local dt = root.dt
- local n = dt[1].tg == "@pi@" and 2 or 1
- if #list > 0 then
- insert(dt, n, { "\n" })
- insert(dt, n, {
- tg = "@dt@", -- beware, doctype is unparsed
- dt = { format("Something [\n%s\n] ",concat(list)) },
- ns = "",
- special = true,
- })
- insert(dt, n, { "\n\n" })
- else
- -- insert(dt, n, { table.serialize(root.statistics) })
- end
- end
-end
-
--- local str = [==[
---
---
--- test test { test
---
---
--- ]==]
---
--- local x = xml.convert(str)
--- xml.addentitiesdoctype(x,"hexadecimal")
--- print(x)
-
---[[ldx--
-Here are a few synonyms.
---ldx]]--
-
-xml.all = xml.each
-xml.insert = xml.insertafter
-xml.inject = xml.injectafter
-xml.after = xml.insertafter
-xml.before = xml.insertbefore
-xml.process = xml.each
-
--- obsolete
-
-xml.obsolete = xml.obsolete or { }
-local obsolete = xml.obsolete
-
-xml.strip_whitespace = xml.strip obsolete.strip_whitespace = xml.strip
-xml.collect_elements = xml.collect obsolete.collect_elements = xml.collect
-xml.delete_element = xml.delete obsolete.delete_element = xml.delete
-xml.replace_element = xml.replace obsolete.replace_element = xml.replacet
-xml.each_element = xml.each obsolete.each_element = xml.each
-xml.process_elements = xml.process obsolete.process_elements = xml.process
-xml.insert_element_after = xml.insertafter obsolete.insert_element_after = xml.insertafter
-xml.insert_element_before = xml.insertbefore obsolete.insert_element_before = xml.insertbefore
-xml.inject_element_after = xml.injectafter obsolete.inject_element_after = xml.injectafter
-xml.inject_element_before = xml.injectbefore obsolete.inject_element_before = xml.injectbefore
-xml.process_attributes = xml.processattributes obsolete.process_attributes = xml.processattributes
-xml.collect_texts = xml.collecttexts obsolete.collect_texts = xml.collecttexts
-xml.inject_element = xml.inject obsolete.inject_element = xml.inject
-xml.remap_tag = xml.remaptag obsolete.remap_tag = xml.remaptag
-xml.remap_name = xml.remapname obsolete.remap_name = xml.remapname
-xml.remap_namespace = xml.remapnamespace obsolete.remap_namespace = xml.remapnamespace
-
--- new (probably ok)
-
-function xml.cdata(e)
- if e then
- local dt = e.dt
- if dt and #dt == 1 then
- local first = dt[1]
- return first.tg == "@cd@" and first.dt[1] or ""
- end
- end
- return ""
-end
-
-function xml.finalizers.xml.cdata(collected)
- if collected then
- local e = collected[1]
- if e then
- local dt = e.dt
- if dt and #dt == 1 then
- local first = dt[1]
- return first.tg == "@cd@" and first.dt[1] or ""
- end
- end
- end
- return ""
-end
-
-function xml.insertcomment(e,str,n) -- also insertcdata
- table.insert(e.dt,n or 1,{
- tg = "@cm@",
- ns = "",
- special = true,
- at = { },
- dt = { str },
- })
-end
-
-function xml.setcdata(e,str) -- also setcomment
- e.dt = { {
- tg = "@cd@",
- ns = "",
- special = true,
- at = { },
- dt = { str },
- } }
-end
-
--- maybe helpers like this will move to an autoloader
-
-function xml.separate(x,pattern)
- local collected = xmlapplylpath(x,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local d = e.dt
- if d == x then
- report_xml("warning: xml.separate changes root")
- x = d
- end
- local t, n = { "\n" }, 1
- local i, nd = 1, #d
- while i <= nd do
- while i <= nd do
- local di = d[i]
- if type(di) == "string" then
- if di == "\n" or find(di,"^%s+$") then -- first test is speedup
- i = i + 1
- else
- d[i] = strip(di)
- break
- end
- else
- break
- end
- end
- if i > nd then
- break
- end
- t[n+1] = "\n"
- t[n+2] = d[i]
- t[n+3] = "\n"
- n = n + 3
- i = i + 1
- end
- t[n+1] = "\n"
- setmetatable(t,getmetatable(d))
- e.dt = t
- end
- end
- return x
-end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['lxml-xml'] = {
- version = 1.001,
- comment = "this module is the basis for the lxml-* ones",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local concat = table.concat
-local find, lower, upper = string.find, string.lower, string.upper
-
-local xml = xml
-
-local finalizers = xml.finalizers.xml
-local xmlfilter = xml.filter -- we could inline this one for speed
-local xmltostring = xml.tostring
-local xmlserialize = xml.serialize
-local xmlcollected = xml.collected
-local xmlnewhandlers = xml.newhandlers
-
-local function first(collected) -- wrong ?
- return collected and collected[1]
-end
-
-local function last(collected)
- return collected and collected[#collected]
-end
-
-local function all(collected)
- return collected
-end
-
--- local function reverse(collected)
--- if collected then
--- local nc = #collected
--- if nc > 0 then
--- local reversed, r = { }, 0
--- for c=nc,1,-1 do
--- r = r + 1
--- reversed[r] = collected[c]
--- end
--- return reversed
--- else
--- return collected
--- end
--- end
--- end
-
-local reverse = table.reversed
-
-local function attribute(collected,name)
- if collected and #collected > 0 then
- local at = collected[1].at
- return at and at[name]
- end
-end
-
-local function att(id,name)
- local at = id.at
- return at and at[name]
-end
-
-local function count(collected)
- return collected and #collected or 0
-end
-
-local function position(collected,n)
- if not collected then
- return 0
- end
- local nc = #collected
- if nc == 0 then
- return 0
- end
- n = tonumber(n) or 0
- if n < 0 then
- return collected[nc + n + 1]
- elseif n > 0 then
- return collected[n]
- else
- return collected[1].mi or 0
- end
-end
-
-local function match(collected)
- return collected and #collected > 0 and collected[1].mi or 0 -- match
-end
-
-local function index(collected)
- return collected and #collected > 0 and collected[1].ni or 0 -- 0 is new
-end
-
-local function attributes(collected,arguments)
- if collected and #collected > 0 then
- local at = collected[1].at
- if arguments then
- return at[arguments]
- elseif next(at) then
- return at -- all of them
- end
- end
-end
-
-local function chainattribute(collected,arguments) -- todo: optional levels
- if collected and #collected > 0 then
- local e = collected[1]
- while e do
- local at = e.at
- if at then
- local a = at[arguments]
- if a then
- return a
- end
- else
- break -- error
- end
- e = e.__p__
- end
- end
- return ""
-end
-
-local function raw(collected) -- hybrid (not much different from text so it might go)
- if collected and #collected > 0 then
- local e = collected[1] or collected
- return e and xmltostring(e) or "" -- only first as we cannot concat function
- else
- return ""
- end
-end
-
---
-
-local xmltexthandler = xmlnewhandlers {
- name = "string",
- initialize = function()
- result = { }
- return result
- end,
- finalize = function()
- return concat(result)
- end,
- handle = function(...)
- result[#result+1] = concat { ... }
- end,
- escape = false,
-}
-
-local function xmltotext(root)
- local dt = root.dt
- if not dt then
- return ""
- end
- local nt = #dt -- string or table
- if nt == 0 then
- return ""
- elseif nt == 1 and type(dt[1]) == "string" then
- return dt[1] -- no escaping of " ' < > &
- else
- return xmlserialize(root,xmltexthandler) or ""
- end
-end
-
---
-
-local function text(collected) -- hybrid
- if collected then -- no # test here !
- local e = collected[1] or collected -- why fallback to element, how about cdata
- return e and xmltotext(e) or ""
- else
- return ""
- end
-end
-
-local function texts(collected)
- if not collected then
- return { } -- why no nil
- end
- local nc = #collected
- if nc == 0 then
- return { } -- why no nil
- end
- local t, n = { }, 0
- for c=1,nc do
- local e = collected[c]
- if e and e.dt then
- n = n + 1
- t[n] = e.dt
- end
- end
- return t
-end
-
-local function tag(collected,n)
- if not collected then
- return
- end
- local nc = #collected
- if nc == 0 then
- return
- end
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[nc-n+1]
- end
- return c and c.tg
-end
-
-local function name(collected,n)
- if not collected then
- return
- end
- local nc = #collected
- if nc == 0 then
- return
- end
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[nc-n+1]
- end
- if not c then
- -- sorry
- elseif c.ns == "" then
- return c.tg
- else
- return c.ns .. ":" .. c.tg
- end
-end
-
-local function tags(collected,nonamespace)
- if not collected then
- return
- end
- local nc = #collected
- if nc == 0 then
- return
- end
- local t, n = { }, 0
- for c=1,nc do
- local e = collected[c]
- local ns, tg = e.ns, e.tg
- n = n + 1
- if nonamespace or ns == "" then
- t[n] = tg
- else
- t[n] = ns .. ":" .. tg
- end
- end
- return t
-end
-
-local function empty(collected,spacesonly)
- if not collected then
- return true
- end
- local nc = #collected
- if nc == 0 then
- return true
- end
- for c=1,nc do
- local e = collected[c]
- if e then
- local edt = e.dt
- if edt then
- local n = #edt
- if n == 1 then
- local edk = edt[1]
- local typ = type(edk)
- if typ == "table" then
- return false
- elseif edk ~= "" then
- return false
- elseif spacesonly and not find(edk,"%S") then
- return false
- end
- elseif n > 1 then
- return false
- end
- end
- end
- end
- return true
-end
-
-finalizers.first = first
-finalizers.last = last
-finalizers.all = all
-finalizers.reverse = reverse
-finalizers.elements = all
-finalizers.default = all
-finalizers.attribute = attribute
-finalizers.att = att
-finalizers.count = count
-finalizers.position = position
-finalizers.match = match
-finalizers.index = index
-finalizers.attributes = attributes
-finalizers.chainattribute = chainattribute
-finalizers.text = text
-finalizers.texts = texts
-finalizers.tag = tag
-finalizers.name = name
-finalizers.tags = tags
-finalizers.empty = empty
-
--- shortcuts -- we could support xmlfilter(id,pattern,first)
-
-function xml.first(id,pattern)
- return first(xmlfilter(id,pattern))
-end
-
-function xml.last(id,pattern)
- return last(xmlfilter(id,pattern))
-end
-
-function xml.count(id,pattern)
- return count(xmlfilter(id,pattern))
-end
-
-function xml.attribute(id,pattern,a,default)
- return attribute(xmlfilter(id,pattern),a,default)
-end
-
-function xml.raw(id,pattern)
- if pattern then
- return raw(xmlfilter(id,pattern))
- else
- return raw(id)
- end
-end
-
-function xml.text(id,pattern) -- brrr either content or element (when cdata)
- if pattern then
- -- return text(xmlfilter(id,pattern))
- local collected = xmlfilter(id,pattern)
- return collected and #collected > 0 and xmltotext(collected[1]) or ""
- elseif id then
- -- return text(id)
- return xmltotext(id) or ""
- else
- return ""
- end
-end
-
-xml.content = text
-
---
-
-function xml.position(id,pattern,n) -- element
- return position(xmlfilter(id,pattern),n)
-end
-
-function xml.match(id,pattern) -- number
- return match(xmlfilter(id,pattern))
-end
-
-function xml.empty(id,pattern,spacesonly)
- return empty(xmlfilter(id,pattern),spacesonly)
-end
-
-xml.all = xml.filter
-xml.index = xml.position
-xml.found = xml.filter
-
--- a nice one:
-
-local function totable(x)
- local t = { }
- for e in xmlcollected(x[1] or x,"/*") do
- t[e.tg] = xmltostring(e.dt) or ""
- end
- return next(t) and t or nil
-end
-
-xml.table = totable
-finalizers.table = totable
-
-local function textonly(e,t)
- if e then
- local edt = e.dt
- if edt then
- for i=1,#edt do
- local e = edt[i]
- if type(e) == "table" then
- textonly(e,t)
- else
- t[#t+1] = e
- end
- end
- end
- end
- return t
-end
-
-function xml.textonly(e) -- no pattern
- return concat(textonly(e,{}))
-end
-
---
-
--- local x = xml.convert("12 3 ")
--- xml.filter(x,"**/lowerall()") print(x)
--- xml.filter(x,"**/upperall()") print(x)
-
-function finalizers.lowerall(collected)
- for c=1,#collected do
- local e = collected[c]
- if not e.special then
- e.tg = lower(e.tg)
- local eat = e.at
- if eat then
- local t = { }
- for k,v in next, eat do
- t[lower(k)] = v
- end
- e.at = t
- end
- end
- end
-end
-
-function finalizers.upperall(collected)
- for c=1,#collected do
- local e = collected[c]
- if not e.special then
- e.tg = upper(e.tg)
- local eat = e.at
- if eat then
- local t = { }
- for k,v in next, eat do
- t[upper(k)] = v
- end
- e.at = t
- end
- end
- end
-end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['data-ini'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files",
-}
-
-local gsub, find, gmatch, char = string.gsub, string.find, string.gmatch, string.char
-local concat = table.concat
-local next, type = next, type
-
-local filedirname, filebasename, fileextname, filejoin = file.dirname, file.basename, file.extname, file.join
-
-local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
-local trace_detail = false trackers.register("resolvers.details", function(v) trace_detail = v end)
-local trace_expansions = false trackers.register("resolvers.expansions", function(v) trace_expansions = v end)
-
-local report_initialization = logs.reporter("resolvers","initialization")
-
-local ostype, osname, ossetenv, osgetenv = os.type, os.name, os.setenv, os.getenv
-
--- The code here used to be part of a data-res but for convenience
--- we now split it over multiple files. As this file is now the
--- starting point we introduce resolvers here.
-
-resolvers = resolvers or { }
-local resolvers = resolvers
-
--- We don't want the kpse library to kick in. Also, we want to be able to
--- execute programs. Control over execution is implemented later.
-
-texconfig.kpse_init = false
-texconfig.shell_escape = 't'
-
-if kpse and kpse.default_texmfcnf then
- local default_texmfcnf = kpse.default_texmfcnf()
- -- looks more like context:
- default_texmfcnf = gsub(default_texmfcnf,"$SELFAUTOLOC","selfautoloc:")
- default_texmfcnf = gsub(default_texmfcnf,"$SELFAUTODIR","selfautodir:")
- default_texmfcnf = gsub(default_texmfcnf,"$SELFAUTOPARENT","selfautoparent:")
- default_texmfcnf = gsub(default_texmfcnf,"$HOME","home:")
- --
- environment.default_texmfcnf = default_texmfcnf
-end
-
-kpse = { original = kpse }
-
-setmetatable(kpse, {
- __index = function(kp,name)
- report_initialization("fatal error: kpse library is accessed (key: %s)",name)
- os.exit()
- end
-} )
-
--- First we check a couple of environment variables. Some might be
--- set already but we need then later on. We start with the system
--- font path.
-
-do
-
- local osfontdir = osgetenv("OSFONTDIR")
-
- if osfontdir and osfontdir ~= "" then
- -- ok
- elseif osname == "windows" then
- ossetenv("OSFONTDIR","c:/windows/fonts//")
- elseif osname == "macosx" then
- ossetenv("OSFONTDIR","$HOME/Library/Fonts//;/Library/Fonts//;/System/Library/Fonts//")
- end
-
-end
-
--- Next comes the user's home path. We need this as later on we have
--- to replace ~ with its value.
-
-do
-
- local homedir = osgetenv(ostype == "windows" and 'USERPROFILE' or 'HOME') or ''
-
- if not homedir or homedir == "" then
- homedir = char(127) -- we need a value, later we wil trigger on it
- end
-
- homedir = file.collapsepath(homedir)
-
- ossetenv("HOME", homedir) -- can be used in unix cnf files
- ossetenv("USERPROFILE",homedir) -- can be used in windows cnf files
-
- environment.homedir = homedir
-
-end
-
--- The following code sets the name of the own binary and its
--- path. This is fallback code as we have os.selfdir now.
-
-do
-
- local args = environment.originalarguments or arg -- this needs a cleanup
-
- local ownbin = environment.ownbin or args[-2] or arg[-2] or args[-1] or arg[-1] or arg[0] or "luatex"
- local ownpath = environment.ownpath or os.selfdir
-
- ownbin = file.collapsepath(ownbin)
- ownpath = file.collapsepath(ownpath)
-
- if not ownpath or ownpath == "" or ownpath == "unset" then
- ownpath = args[-1] or arg[-1]
- ownpath = ownpath and filedirname(gsub(ownpath,"\\","/"))
- if not ownpath or ownpath == "" then
- ownpath = args[-0] or arg[-0]
- ownpath = ownpath and filedirname(gsub(ownpath,"\\","/"))
- end
- local binary = ownbin
- if not ownpath or ownpath == "" then
- ownpath = ownpath and filedirname(binary)
- end
- if not ownpath or ownpath == "" then
- if os.binsuffix ~= "" then
- binary = file.replacesuffix(binary,os.binsuffix)
- end
- local path = osgetenv("PATH")
- if path then
- for p in gmatch(path,"[^"..io.pathseparator.."]+") do
- local b = filejoin(p,binary)
- if lfs.isfile(b) then
- -- we assume that after changing to the path the currentdir function
- -- resolves to the real location and use this side effect here; this
- -- trick is needed because on the mac installations use symlinks in the
- -- path instead of real locations
- local olddir = lfs.currentdir()
- if lfs.chdir(p) then
- local pp = lfs.currentdir()
- if trace_locating and p ~= pp then
- report_initialization("following symlink '%s' to '%s'",p,pp)
- end
- ownpath = pp
- lfs.chdir(olddir)
- else
- if trace_locating then
- report_initialization("unable to check path '%s'",p)
- end
- ownpath = p
- end
- break
- end
- end
- end
- end
- if not ownpath or ownpath == "" then
- ownpath = "."
- report_initialization("forcing fallback ownpath .")
- elseif trace_locating then
- report_initialization("using ownpath '%s'",ownpath)
- end
- end
-
- environment.ownbin = ownbin
- environment.ownpath = ownpath
-
-end
-
-resolvers.ownpath = environment.ownpath
-
-function resolvers.getownpath()
- return environment.ownpath
-end
-
--- The self variables permit us to use only a few (or even no)
--- environment variables.
-
-do
-
- local ownpath = environment.ownpath or dir.current()
-
- if ownpath then
- ossetenv('SELFAUTOLOC', file.collapsepath(ownpath))
- ossetenv('SELFAUTODIR', file.collapsepath(ownpath .. "/.."))
- ossetenv('SELFAUTOPARENT', file.collapsepath(ownpath .. "/../.."))
- else
- report_initialization("error: unable to locate ownpath")
- os.exit()
- end
-
-end
-
--- The running os:
-
--- todo: check is context sits here os.platform is more trustworthy
--- that the bin check as mtx-update runs from another path
-
-local texos = environment.texos or osgetenv("TEXOS")
-local texmfos = environment.texmfos or osgetenv('SELFAUTODIR')
-
-if not texos or texos == "" then
- texos = file.basename(texmfos)
-end
-
-ossetenv('TEXMFOS', texmfos) -- full bin path
-ossetenv('TEXOS', texos) -- partial bin parent
-ossetenv('SELFAUTOSYSTEM',os.platform) -- bonus
-
-environment.texos = texos
-environment.texmfos = texmfos
-
--- The current root:
-
-local texroot = environment.texroot or osgetenv("TEXROOT")
-
-if not texroot or texroot == "" then
- texroot = osgetenv('SELFAUTOPARENT')
- ossetenv('TEXROOT',texroot)
-end
-
-environment.texroot = file.collapsepath(texroot)
-
--- Tracing. Todo ...
-
-function resolvers.settrace(n) -- no longer number but: 'locating' or 'detail'
- if n then
- trackers.disable("resolvers.*")
- trackers.enable("resolvers."..n)
- end
-end
-
-resolvers.settrace(osgetenv("MTX_INPUT_TRACE"))
-
--- todo:
-
--- if profiler and osgetenv("MTX_PROFILE_RUN") == "YES" then
--- profiler.start("luatex-profile.log")
--- end
-
--- a forward definition
-
-if not resolvers.resolve then
- function resolvers.resolve (s) return s end
- function resolvers.unresolve(s) return s end
- function resolvers.repath (s) return s end
-end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['data-exp'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files",
-}
-
-local format, find, gmatch, lower, char, sub = string.format, string.find, string.gmatch, string.lower, string.char, string.sub
-local concat, sort = table.concat, table.sort
-local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
-local Ct, Cs, Cc, P, C, S = lpeg.Ct, lpeg.Cs, lpeg.Cc, lpeg.P, lpeg.C, lpeg.S
-local type, next = type, next
-
-local ostype = os.type
-local collapsepath = file.collapsepath
-
-local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
-local trace_expansions = false trackers.register("resolvers.expansions", function(v) trace_expansions = v end)
-
-local report_expansions = logs.reporter("resolvers","expansions")
-
-local resolvers = resolvers
-
--- As this bit of code is somewhat special it gets its own module. After
--- all, when working on the main resolver code, I don't want to scroll
--- past this every time. See data-obs.lua for the gsub variant.
-
-local function f_first(a,b)
- local t, n = { }, 0
- for s in gmatch(b,"[^,]+") do
- n = n + 1 ; t[n] = a .. s
- end
- return concat(t,",")
-end
-
-local function f_second(a,b)
- local t, n = { }, 0
- for s in gmatch(a,"[^,]+") do
- n = n + 1 ; t[n] = s .. b
- end
- return concat(t,",")
-end
-
--- kpsewhich --expand-braces '{a,b}{c,d}'
--- ac:bc:ad:bd
-
--- old {a,b}{c,d} => ac ad bc bd
---
--- local function f_both(a,b)
--- local t, n = { }, 0
--- for sa in gmatch(a,"[^,]+") do
--- for sb in gmatch(b,"[^,]+") do
--- n = n + 1 ; t[n] = sa .. sb
--- end
--- end
--- return concat(t,",")
--- end
---
--- new {a,b}{c,d} => ac bc ad bd
-
-local function f_both(a,b)
- local t, n = { }, 0
- for sb in gmatch(b,"[^,]+") do -- and not sa
- for sa in gmatch(a,"[^,]+") do -- sb
- n = n + 1 ; t[n] = sa .. sb
- end
- end
- return concat(t,",")
-end
-
-local left = P("{")
-local right = P("}")
-local var = P((1 - S("{}" ))^0)
-local set = P((1 - S("{},"))^0)
-local other = P(1)
-
-local l_first = Cs( ( Cc("{") * (C(set) * left * C(var) * right / f_first) * Cc("}") + other )^0 )
-local l_second = Cs( ( Cc("{") * (left * C(var) * right * C(set) / f_second) * Cc("}") + other )^0 )
-local l_both = Cs( ( Cc("{") * (left * C(var) * right * left * C(var) * right / f_both) * Cc("}") + other )^0 )
-local l_rest = Cs( ( left * var * (left/"") * var * (right/"") * var * right + other )^0 )
-
-local stripper_1 = lpeg.stripper ("{}@")
-local replacer_1 = lpeg.replacer { { ",}", ",@}" }, { "{,", "{@," }, }
-
-local function splitpathexpr(str, newlist, validate) -- I couldn't resist lpegging it (nice exercise).
- if trace_expansions then
- report_expansions("expanding variable '%s'",str)
- end
- local t, ok, done = newlist or { }, false, false
- local n = #t
- str = lpegmatch(replacer_1,str)
- repeat
- local old = str
- repeat
- local old = str
- str = lpegmatch(l_first, str)
- until old == str
- repeat
- local old = str
- str = lpegmatch(l_second,str)
- until old == str
- repeat
- local old = str
- str = lpegmatch(l_both, str)
- until old == str
- repeat
- local old = str
- str = lpegmatch(l_rest, str)
- until old == str
- until old == str -- or not find(str,"{")
- str = lpegmatch(stripper_1,str)
- if validate then
- for s in gmatch(str,"[^,]+") do
- s = validate(s)
- if s then
- n = n + 1 ; t[n] = s
- end
- end
- else
- for s in gmatch(str,"[^,]+") do
- n = n + 1 ; t[n] = s
- end
- end
- if trace_expansions then
- for k=1,#t do
- report_expansions("% 4i: %s",k,t[k])
- end
- end
- return t
-end
-
--- We could make the previous one public.
-
-local function validate(s)
- s = collapsepath(s) -- already keeps the //
- return s ~= "" and not find(s,"^!*unset/*$") and s
-end
-
-resolvers.validatedpath = validate -- keeps the trailing //
-
-function resolvers.expandedpathfromlist(pathlist)
- local newlist = { }
- for k=1,#pathlist do
- splitpathexpr(pathlist[k],newlist,validate)
- end
- return newlist
-end
-
--- {a,b,c,d}
--- a,b,c/{p,q,r},d
--- a,b,c/{p,q,r}/d/{x,y,z}//
--- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
--- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
--- a{b,c}{d,e}f
--- {a,b,c,d}
--- {a,b,c/{p,q,r},d}
--- {a,b,c/{p,q,r}/d/{x,y,z}//}
--- {a,b,c/{p,q/{x,y,z}},d/{p,q,r}}
--- {a,b,c/{p,q/{x,y,z},w}v,d/{p,q,r}}
--- {$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,.local,}/web2c}
-
-local cleanup = lpeg.replacer {
- { "!" , "" },
- { "\\" , "/" },
-}
-
-function resolvers.cleanpath(str) -- tricky, maybe only simple paths
- local doslashes = (P("\\")/"/" + 1)^0
- local donegation = (P("!") /"" )^0
- local homedir = lpegmatch(Cs(donegation * doslashes),environment.homedir or "")
- if homedir == "~" or homedir == "" or not lfs.isdir(homedir) then
- if trace_expansions then
- report_expansions("no home dir set, ignoring dependent paths")
- end
- function resolvers.cleanpath(str)
- if not str or find(str,"~") then
- return "" -- special case
- else
- return lpegmatch(cleanup,str)
- end
- end
- else
- local dohome = ((P("~")+P("$HOME"))/homedir)^0
- local cleanup = Cs(donegation * dohome * doslashes)
- function resolvers.cleanpath(str)
- return str and lpegmatch(cleanup,str) or ""
- end
- end
- return resolvers.cleanpath(str)
-end
-
--- print(resolvers.cleanpath(""))
--- print(resolvers.cleanpath("!"))
--- print(resolvers.cleanpath("~"))
--- print(resolvers.cleanpath("~/test"))
--- print(resolvers.cleanpath("!~/test"))
--- print(resolvers.cleanpath("~/test~test"))
-
--- This one strips quotes and funny tokens.
-
-local expandhome = P("~") / "$HOME" -- environment.homedir
-
-local dodouble = P('"')/"" * (expandhome + (1 - P('"')))^0 * P('"')/""
-local dosingle = P("'")/"" * (expandhome + (1 - P("'")))^0 * P("'")/""
-local dostring = (expandhome + 1 )^0
-
-local stripper = Cs(
- lpegpatterns.unspacer * (dosingle + dodouble + dostring) * lpegpatterns.unspacer
-)
-
-function resolvers.checkedvariable(str) -- assumes str is a string
- return type(str) == "string" and lpegmatch(stripper,str) or str
-end
-
--- The path splitter:
-
--- A config (optionally) has the paths split in tables. Internally
--- we join them and split them after the expansion has taken place. This
--- is more convenient.
-
-local cache = { }
-
------ splitter = lpeg.tsplitat(S(ostype == "windows" and ";" or ":;")) -- maybe add ,
-local splitter = lpeg.tsplitat(";") -- as we move towards urls, prefixes and use tables we no longer do :
-
-local backslashswapper = lpeg.replacer("\\","/")
-
-local function splitconfigurationpath(str) -- beware, this can be either a path or a { specification }
- if str then
- local found = cache[str]
- if not found then
- if str == "" then
- found = { }
- else
- local split = lpegmatch(splitter,lpegmatch(backslashswapper,str)) -- can be combined
- found = { }
- local noffound = 0
- for i=1,#split do
- local s = split[i]
- if not find(s,"^{*unset}*") then
- noffound = noffound + 1
- found[noffound] = s
- end
- end
- if trace_expansions then
- report_expansions("splitting path specification '%s'",str)
- for k=1,noffound do
- report_expansions("% 4i: %s",k,found[k])
- end
- end
- cache[str] = found
- end
- end
- return found
- end
-end
-
-resolvers.splitconfigurationpath = splitconfigurationpath
-
-function resolvers.splitpath(str)
- if type(str) == 'table' then
- return str
- else
- return splitconfigurationpath(str)
- end
-end
-
-function resolvers.joinpath(str)
- if type(str) == 'table' then
- return file.joinpath(str)
- else
- return str
- end
-end
-
--- The next function scans directories and returns a hash where the
--- entries are either strings or tables.
-
--- starting with . or .. etc or funny char
-
-
-
-
--- a lot of this caching can be stripped away when we have ssd's everywhere
---
--- we could cache all the (sub)paths here if needed
-
-local attributes, directory = lfs.attributes, lfs.dir
-
-local weird = P(".")^1 + lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
-local timer = { }
-local scanned = { }
-local nofscans = 0
-local scancache = { }
-
-local function scan(files,spec,path,n,m,r)
- local full = (path == "" and spec) or (spec .. path .. '/')
- local dirs = { }
- local nofdirs = 0
- for name in directory(full) do
- if not lpegmatch(weird,name) then
- local mode = attributes(full..name,'mode')
- if mode == 'file' then
- n = n + 1
- local f = files[name]
- if f then
- if type(f) == 'string' then
- files[name] = { f, path }
- else
- f[#f+1] = path
- end
- else -- probably unique anyway
- files[name] = path
- local lower = lower(name)
- if name ~= lower then
- files["remap:"..lower] = name
- r = r + 1
- end
- end
- elseif mode == 'directory' then
- m = m + 1
- nofdirs = nofdirs + 1
- if path ~= "" then
- dirs[nofdirs] = path..'/'..name
- else
- dirs[nofdirs] = name
- end
- end
- end
- end
- if nofdirs > 0 then
- sort(dirs)
- for i=1,nofdirs do
- files, n, m, r = scan(files,spec,dirs[i],n,m,r)
- end
- end
- scancache[sub(full,1,-2)] = files
- return files, n, m, r
-end
-
-local fullcache = { }
-
-function resolvers.scanfiles(path,branch,usecache)
- statistics.starttiming(timer)
- local realpath = resolvers.resolve(path) -- no shortcut
- if usecache then
- local files = fullcache[realpath]
- if files then
- if trace_locating then
- report_expansions("using caches scan of path '%s', branch '%s'",path,branch or path)
- end
- return files
- end
- end
- if trace_locating then
- report_expansions("scanning path '%s', branch '%s'",path,branch or path)
- end
- local files, n, m, r = scan({ },realpath .. '/',"",0,0,0)
- files.__path__ = path -- can be selfautoparent:texmf-whatever
- files.__files__ = n
- files.__directories__ = m
- files.__remappings__ = r
- if trace_locating then
- report_expansions("%s files found on %s directories with %s uppercase remappings",n,m,r)
- end
- if usecache then
- scanned[#scanned+1] = realpath
- fullcache[realpath] = files
- end
- nofscans = nofscans + 1
- statistics.stoptiming(timer)
- return files
-end
-
-local function simplescan(files,spec,path) -- first match only, no map and such
- local full = (path == "" and spec) or (spec .. path .. '/')
- local dirs = { }
- local nofdirs = 0
- for name in directory(full) do
- if not lpegmatch(weird,name) then
- local mode = attributes(full..name,'mode')
- if mode == 'file' then
- if not files[name] then
- -- only first match
- files[name] = path
- end
- elseif mode == 'directory' then
- nofdirs = nofdirs + 1
- if path ~= "" then
- dirs[nofdirs] = path..'/'..name
- else
- dirs[nofdirs] = name
- end
- end
- end
- end
- if nofdirs > 0 then
- sort(dirs)
- for i=1,nofdirs do
- files = simplescan(files,spec,dirs[i])
- end
- end
- return files
-end
-
-local simplecache = { }
-local nofsharedscans = 0
-
-function resolvers.simplescanfiles(path,branch,usecache)
- statistics.starttiming(timer)
- local realpath = resolvers.resolve(path) -- no shortcut
- if usecache then
- local files = simplecache[realpath]
- if not files then
- files = scancache[realpath]
- if files then
- nofsharedscans = nofsharedscans + 1
- end
- end
- if files then
- if trace_locating then
- report_expansions("using caches scan of path '%s', branch '%s'",path,branch or path)
- end
- return files
- end
- end
- if trace_locating then
- report_expansions("scanning path '%s', branch '%s'",path,branch or path)
- end
- local files = simplescan({ },realpath .. '/',"")
- if trace_locating then
- report_expansions("%s files found",table.count(files))
- end
- if usecache then
- scanned[#scanned+1] = realpath
- simplecache[realpath] = files
- end
- nofscans = nofscans + 1
- statistics.stoptiming(timer)
- return files
-end
-
-function resolvers.scandata()
- table.sort(scanned)
- return {
- n = nofscans,
- shared = nofsharedscans,
- time = statistics.elapsedtime(timer),
- paths = scanned,
- }
-end
-
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['data-env'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files",
-}
-
-local lower, gsub = string.lower, string.gsub
-
-local resolvers = resolvers
-
-local allocate = utilities.storage.allocate
-local setmetatableindex = table.setmetatableindex
-local fileextname = file.extname
-
-local formats = allocate()
-local suffixes = allocate()
-local dangerous = allocate()
-local suffixmap = allocate()
-
-resolvers.formats = formats
-resolvers.suffixes = suffixes
-resolvers.dangerous = dangerous
-resolvers.suffixmap = suffixmap
-
-local relations = allocate { -- todo: handlers also here
- core = {
- ofm = { -- will become obsolete
- names = { "ofm", "omega font metric", "omega font metrics" },
- variable = 'OFMFONTS',
- suffixes = { 'ofm', 'tfm' },
- },
- ovf = { -- will become obsolete
- names = { "ovf", "omega virtual font", "omega virtual fonts" },
- variable = 'OVFFONTS',
- suffixes = { 'ovf', 'vf' },
- },
- tfm = {
- names = { "tfm", "tex font metric", "tex font metrics" },
- variable = 'TFMFONTS',
- suffixes = { 'tfm' },
- },
- vf = {
- names = { "vf", "virtual font", "virtual fonts" },
- variable = 'VFFONTS',
- suffixes = { 'vf' },
- },
- otf = {
- names = { "otf", "opentype", "opentype font", "opentype fonts"},
- variable = 'OPENTYPEFONTS',
- suffixes = { 'otf' },
- },
- ttf = {
- names = { "ttf", "truetype", "truetype font", "truetype fonts", "truetype collection", "truetype collections", "truetype dictionary", "truetype dictionaries" },
- variable = 'TTFONTS',
- suffixes = { 'ttf', 'ttc', 'dfont' },
- },
- afm = {
- names = { "afm", "adobe font metric", "adobe font metrics" },
- variable = "AFMFONTS",
- suffixes = { "afm" },
- },
- pfb = {
- names = { "pfb", "type1", "type 1", "type1 font", "type 1 font", "type1 fonts", "type 1 fonts" },
- variable = 'T1FONTS',
- suffixes = { 'pfb', 'pfa' },
- },
- fea = {
- names = { "fea", "font feature", "font features", "font feature file", "font feature files" },
- variable = 'FONTFEATURES',
- suffixes = { 'fea' },
- },
- cid = {
- names = { "cid", "cid map", "cid maps", "cid file", "cid files" },
- variable = 'FONTCIDMAPS',
- suffixes = { 'cid', 'cidmap' },
- },
- fmt = {
- names = { "fmt", "format", "tex format" },
- variable = 'TEXFORMATS',
- suffixes = { 'fmt' },
- },
- mem = { -- will become obsolete
- names = { 'mem', "metapost format" },
- variable = 'MPMEMS',
- suffixes = { 'mem' },
- },
- mp = {
- names = { "mp" },
- variable = 'MPINPUTS',
- suffixes = { 'mp', 'mpvi', 'mpiv', 'mpii' },
- },
- tex = {
- names = { "tex" },
- variable = 'TEXINPUTS',
- suffixes = { 'tex', "mkvi", "mkiv", "mkii" },
- },
- icc = {
- names = { "icc", "icc profile", "icc profiles" },
- variable = 'ICCPROFILES',
- suffixes = { 'icc' },
- },
- texmfscripts = {
- names = { "texmfscript", "texmfscripts", "script", "scripts" },
- variable = 'TEXMFSCRIPTS',
- suffixes = { 'rb', 'pl', 'py' },
- },
- lua = {
- names = { "lua" },
- variable = 'LUAINPUTS',
- suffixes = { 'lua', 'luc', 'tma', 'tmc' },
- },
- lib = {
- names = { "lib" },
- variable = 'CLUAINPUTS',
- suffixes = os.libsuffix and { os.libsuffix } or { 'dll', 'so' },
- },
- bib = {
- names = { 'bib' },
- suffixes = { 'bib' },
- },
- bst = {
- names = { 'bst' },
- suffixes = { 'bst' },
- },
- fontconfig = {
- names = { 'fontconfig', 'fontconfig file', 'fontconfig files' },
- variable = 'FONTCONFIG_PATH',
- },
- },
- obsolete = {
- enc = {
- names = { "enc", "enc files", "enc file", "encoding files", "encoding file" },
- variable = 'ENCFONTS',
- suffixes = { 'enc' },
- },
- map = {
- names = { "map", "map files", "map file" },
- variable = 'TEXFONTMAPS',
- suffixes = { 'map' },
- },
- lig = {
- names = { "lig files", "lig file", "ligature file", "ligature files" },
- variable = 'LIGFONTS',
- suffixes = { 'lig' },
- },
- opl = {
- names = { "opl" },
- variable = 'OPLFONTS',
- suffixes = { 'opl' },
- },
- ovp = {
- names = { "ovp" },
- variable = 'OVPFONTS',
- suffixes = { 'ovp' },
- },
- },
- kpse = { -- subset
- base = {
- names = { 'base', "metafont format" },
- variable = 'MFBASES',
- suffixes = { 'base', 'bas' },
- },
- cmap = {
- names = { 'cmap', 'cmap files', 'cmap file' },
- variable = 'CMAPFONTS',
- suffixes = { 'cmap' },
- },
- cnf = {
- names = { 'cnf' },
- suffixes = { 'cnf' },
- },
- web = {
- names = { 'web' },
- suffixes = { 'web', 'ch' }
- },
- cweb = {
- names = { 'cweb' },
- suffixes = { 'w', 'web', 'ch' },
- },
- gf = {
- names = { 'gf' },
- suffixes = { 'gf' },
- },
- mf = {
- names = { 'mf' },
- variable = 'MFINPUTS',
- suffixes = { 'mf' },
- },
- mft = {
- names = { 'mft' },
- suffixes = { 'mft' },
- },
- pk = {
- names = { 'pk' },
- suffixes = { 'pk' },
- },
- },
-}
-
-resolvers.relations = relations
-
--- formats: maps a format onto a variable
-
-function resolvers.updaterelations()
- for category, categories in next, relations do
- for name, relation in next, categories do
- local rn = relation.names
- local rv = relation.variable
- local rs = relation.suffixes
- if rn and rv then
- for i=1,#rn do
- local rni = lower(gsub(rn[i]," ",""))
- formats[rni] = rv
- if rs then
- suffixes[rni] = rs
- for i=1,#rs do
- local rsi = rs[i]
- suffixmap[rsi] = rni
- end
- end
- end
- end
- if rs then
- end
- end
- end
-end
-
-resolvers.updaterelations() -- push this in the metatable -> newindex
-
-local function simplified(t,k)
- return k and rawget(t,lower(gsub(k," ",""))) or nil
-end
-
-setmetatableindex(formats, simplified)
-setmetatableindex(suffixes, simplified)
-setmetatableindex(suffixmap, simplified)
-
--- A few accessors, mostly for command line tool.
-
-function resolvers.suffixofformat(str)
- local s = suffixes[str]
- return s and s[1] or ""
-end
-
-function resolvers.suffixofformat(str)
- return suffixes[str] or { }
-end
-
-for name, format in next, formats do
- dangerous[name] = true -- still needed ?
-end
-
--- because vf searching is somewhat dangerous, we want to prevent
--- too liberal searching esp because we do a lookup on the current
--- path anyway; only tex (or any) is safe
-
-dangerous.tex = nil
-
-
--- more helpers
-
-function resolvers.formatofvariable(str)
- return formats[str] or ''
-end
-
-function resolvers.formatofsuffix(str) -- of file
- return suffixmap[fileextname(str)] or 'tex' -- so many map onto tex (like mkiv, cld etc)
-end
-
-function resolvers.variableofformat(str)
- return formats[str] or ''
-end
-
-function resolvers.variableofformatorsuffix(str)
- local v = formats[str]
- if v then
- return v
- end
- v = suffixmap[fileextname(str)]
- if v then
- return formats[v]
- end
- return ''
-end
-
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['data-tmp'] = {
- version = 1.100,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
---[[ldx--
-This module deals with caching data. It sets up the paths and
-implements loaders and savers for tables. Best is to set the
-following variable. When not set, the usual paths will be
-checked. Personally I prefer the (users) temporary path.
-
-
-TEXMFCACHE=$TMP;$TEMP;$TMPDIR;$TEMPDIR;$HOME;$TEXMFVAR;$VARTEXMF;.
-
-
-Currently we do no locking when we write files. This is no real
-problem because most caching involves fonts and the chance of them
-being written at the same time is small. We also need to extend
-luatools with a recache feature.
---ldx]]--
-
-local format, lower, gsub, concat = string.format, string.lower, string.gsub, table.concat
-local serialize, serializetofile = table.serialize, table.tofile
-local mkdirs, isdir = dir.mkdirs, lfs.isdir
-
-local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
-local trace_cache = false trackers.register("resolvers.cache", function(v) trace_cache = v end)
-
-local report_caches = logs.reporter("resolvers","caches")
-local report_resolvers = logs.reporter("resolvers","caching")
-
-local resolvers = resolvers
-
--- intermezzo
-
-local directive_cleanup = false directives.register("system.compile.cleanup", function(v) directive_cleanup = v end)
-local directive_strip = true directives.register("system.compile.strip", function(v) directive_strip = v end)
-
-local compile = utilities.lua.compile
-
-function utilities.lua.compile(luafile,lucfile,cleanup,strip)
- if cleanup == nil then cleanup = directive_cleanup end
- if strip == nil then strip = directive_strip end
- return compile(luafile,lucfile,cleanup,strip)
-end
-
--- end of intermezzo
-
-caches = caches or { }
-local caches = caches
-
-caches.base = caches.base or "luatex-cache"
-caches.more = caches.more or "context"
-caches.direct = false -- true is faster but may need huge amounts of memory
-caches.tree = false
-caches.force = true
-caches.ask = false
-caches.relocate = false
-caches.defaults = { "TMPDIR", "TEMPDIR", "TMP", "TEMP", "HOME", "HOMEPATH" }
-
-local writable, readables, usedreadables = nil, { }, { }
-
--- we could use a metatable for writable and readable but not yet
-
-local function identify()
- -- Combining the loops makes it messy. First we check the format cache path
- -- and when the last component is not present we try to create it.
- local texmfcaches = resolvers.cleanpathlist("TEXMFCACHE")
- if texmfcaches then
- for k=1,#texmfcaches do
- local cachepath = texmfcaches[k]
- if cachepath ~= "" then
- cachepath = resolvers.resolve(cachepath)
- cachepath = resolvers.cleanpath(cachepath)
- cachepath = file.collapsepath(cachepath)
- local valid = isdir(cachepath)
- if valid then
- if file.is_readable(cachepath) then
- readables[#readables+1] = cachepath
- if not writable and file.is_writable(cachepath) then
- writable = cachepath
- end
- end
- elseif not writable and caches.force then
- local cacheparent = file.dirname(cachepath)
- if file.is_writable(cacheparent) and true then -- we go on anyway (needed for mojca's kind of paths)
- if not caches.ask or io.ask(format("\nShould I create the cache path %s?",cachepath), "no", { "yes", "no" }) == "yes" then
- mkdirs(cachepath)
- if isdir(cachepath) and file.is_writable(cachepath) then
- report_caches("created: %s",cachepath)
- writable = cachepath
- readables[#readables+1] = cachepath
- end
- end
- end
- end
- end
- end
- end
- -- As a last resort we check some temporary paths but this time we don't
- -- create them.
- local texmfcaches = caches.defaults
- if texmfcaches then
- for k=1,#texmfcaches do
- local cachepath = texmfcaches[k]
- cachepath = resolvers.expansion(cachepath) -- was getenv
- if cachepath ~= "" then
- cachepath = resolvers.resolve(cachepath)
- cachepath = resolvers.cleanpath(cachepath)
- local valid = isdir(cachepath)
- if valid and file.is_readable(cachepath) then
- if not writable and file.is_writable(cachepath) then
- readables[#readables+1] = cachepath
- writable = cachepath
- break
- end
- end
- end
- end
- end
- -- Some extra checking. If we have no writable or readable path then we simply
- -- quit.
- if not writable then
- report_caches("fatal error: there is no valid writable cache path defined")
- os.exit()
- elseif #readables == 0 then
- report_caches("fatal error: there is no valid readable cache path defined")
- os.exit()
- end
- -- why here
- writable = dir.expandname(resolvers.cleanpath(writable)) -- just in case
- -- moved here
- local base, more, tree = caches.base, caches.more, caches.tree or caches.treehash() -- we have only one writable tree
- if tree then
- caches.tree = tree
- writable = mkdirs(writable,base,more,tree)
- for i=1,#readables do
- readables[i] = file.join(readables[i],base,more,tree)
- end
- else
- writable = mkdirs(writable,base,more)
- for i=1,#readables do
- readables[i] = file.join(readables[i],base,more)
- end
- end
- -- end
- if trace_cache then
- for i=1,#readables do
- report_caches("using readable path '%s' (order %s)",readables[i],i)
- end
- report_caches("using writable path '%s'",writable)
- end
- identify = function()
- return writable, readables
- end
- return writable, readables
-end
-
-function caches.usedpaths()
- local writable, readables = identify()
- if #readables > 1 then
- local result = { }
- for i=1,#readables do
- local readable = readables[i]
- if usedreadables[i] or readable == writable then
- result[#result+1] = format("readable: '%s' (order %s)",readable,i)
- end
- end
- result[#result+1] = format("writable: '%s'",writable)
- return result
- else
- return writable
- end
-end
-
-function caches.configfiles()
- return concat(resolvers.instance.specification,";")
-end
-
-function caches.hashed(tree)
- tree = gsub(tree,"\\$","/")
- tree = gsub(tree,"/+$","")
- tree = lower(tree)
- local hash = md5.hex(tree)
- if trace_cache or trace_locating then
- report_caches("hashing tree %s, hash %s",tree,hash)
- end
- return hash
-end
-
-function caches.treehash()
- local tree = caches.configfiles()
- if not tree or tree == "" then
- return false
- else
- return caches.hashed(tree)
- end
-end
-
-local r_cache, w_cache = { }, { } -- normally w in in r but who cares
-
-local function getreadablepaths(...) -- we can optimize this as we have at most 2 tags
- local tags = { ... }
- local hash = concat(tags,"/")
- local done = r_cache[hash]
- if not done then
- local writable, readables = identify() -- exit if not found
- if #tags > 0 then
- done = { }
- for i=1,#readables do
- done[i] = file.join(readables[i],...)
- end
- else
- done = readables
- end
- r_cache[hash] = done
- end
- return done
-end
-
-local function getwritablepath(...)
- local tags = { ... }
- local hash = concat(tags,"/")
- local done = w_cache[hash]
- if not done then
- local writable, readables = identify() -- exit if not found
- if #tags > 0 then
- done = mkdirs(writable,...)
- else
- done = writable
- end
- w_cache[hash] = done
- end
- return done
-end
-
-caches.getreadablepaths = getreadablepaths
-caches.getwritablepath = getwritablepath
-
-function caches.getfirstreadablefile(filename,...)
- local rd = getreadablepaths(...)
- for i=1,#rd do
- local path = rd[i]
- local fullname = file.join(path,filename)
- if file.is_readable(fullname) then
- usedreadables[i] = true
- return fullname, path
- end
- end
- return caches.setfirstwritablefile(filename,...)
-end
-
-function caches.setfirstwritablefile(filename,...)
- local wr = getwritablepath(...)
- local fullname = file.join(wr,filename)
- return fullname, wr
-end
-
-function caches.define(category,subcategory) -- for old times sake
- return function()
- return getwritablepath(category,subcategory)
- end
-end
-
-function caches.setluanames(path,name)
- return path .. "/" .. name .. ".tma", path .. "/" .. name .. ".tmc"
-end
-
-function caches.loaddata(readables,name)
- if type(readables) == "string" then
- readables = { readables }
- end
- for i=1,#readables do
- local path = readables[i]
- local tmaname, tmcname = caches.setluanames(path,name)
- local loader = loadfile(tmcname) or loadfile(tmaname)
- if loader then
- loader = loader()
- collectgarbage("step")
- return loader
- end
- end
- return false
-end
-
-function caches.is_writable(filepath,filename)
- local tmaname, tmcname = caches.setluanames(filepath,filename)
- return file.is_writable(tmaname)
-end
-
-local saveoptions = { compact = true }
-
-function caches.savedata(filepath,filename,data,raw)
- local tmaname, tmcname = caches.setluanames(filepath,filename)
- local reduce, simplify = true, true
- if raw then
- reduce, simplify = false, false
- end
- data.cache_uuid = os.uuid()
- if caches.direct then
- file.savedata(tmaname,serialize(data,true,saveoptions))
- else
- serializetofile(tmaname,data,true,saveoptions)
- end
- utilities.lua.compile(tmaname,tmcname)
-end
-
--- moved from data-res:
-
-local content_state = { }
-
-function caches.contentstate()
- return content_state or { }
-end
-
-function caches.loadcontent(cachename,dataname)
- local name = caches.hashed(cachename)
- local full, path = caches.getfirstreadablefile(name ..".lua","trees")
- local filename = file.join(path,name)
- local blob = loadfile(filename .. ".luc") or loadfile(filename .. ".lua")
- if blob then
- local data = blob()
- if data and data.content then
- if data.type == dataname then
- if data.version == resolvers.cacheversion then
- content_state[#content_state+1] = data.uuid
- if trace_locating then
- report_resolvers("loading '%s' for '%s' from '%s'",dataname,cachename,filename)
- end
- return data.content
- else
- report_resolvers("skipping '%s' for '%s' from '%s' (version mismatch)",dataname,cachename,filename)
- end
- else
- report_resolvers("skipping '%s' for '%s' from '%s' (datatype mismatch)",dataname,cachename,filename)
- end
- elseif trace_locating then
- report_resolvers("skipping '%s' for '%s' from '%s' (no content)",dataname,cachename,filename)
- end
- elseif trace_locating then
- report_resolvers("skipping '%s' for '%s' from '%s' (invalid file)",dataname,cachename,filename)
- end
-end
-
-function caches.collapsecontent(content)
- for k, v in next, content do
- if type(v) == "table" and #v == 1 then
- content[k] = v[1]
- end
- end
-end
-
-function caches.savecontent(cachename,dataname,content)
- local name = caches.hashed(cachename)
- local full, path = caches.setfirstwritablefile(name ..".lua","trees")
- local filename = file.join(path,name) -- is full
- local luaname, lucname = filename .. ".lua", filename .. ".luc"
- if trace_locating then
- report_resolvers("preparing '%s' for '%s'",dataname,cachename)
- end
- local data = {
- type = dataname,
- root = cachename,
- version = resolvers.cacheversion,
- date = os.date("%Y-%m-%d"),
- time = os.date("%H:%M:%S"),
- content = content,
- uuid = os.uuid(),
- }
- local ok = io.savedata(luaname,serialize(data,true))
- if ok then
- if trace_locating then
- report_resolvers("category '%s', cachename '%s' saved in '%s'",dataname,cachename,luaname)
- end
- if utilities.lua.compile(luaname,lucname) then
- if trace_locating then
- report_resolvers("'%s' compiled to '%s'",dataname,lucname)
- end
- return true
- else
- if trace_locating then
- report_resolvers("compiling failed for '%s', deleting file '%s'",dataname,lucname)
- end
- os.remove(lucname)
- end
- elseif trace_locating then
- report_resolvers("unable to save '%s' in '%s' (access error)",dataname,luaname)
- end
-end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['data-met'] = {
- version = 1.100,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local find, format = string.find, string.format
-local sequenced = table.sequenced
-local addurlscheme, urlhashed = url.addscheme, url.hashed
-
-local trace_locating = false
-
-trackers.register("resolvers.locating", function(v) trace_methods = v end)
-trackers.register("resolvers.methods", function(v) trace_methods = v end)
-
-
-local report_methods = logs.reporter("resolvers","methods")
-
-local allocate = utilities.storage.allocate
-
-local resolvers = resolvers
-
-local registered = { }
-
-local function splitmethod(filename) -- todo: filetype in specification
- if not filename then
- return { scheme = "unknown", original = filename }
- end
- if type(filename) == "table" then
- return filename -- already split
- end
- filename = file.collapsepath(filename)
- if not find(filename,"://") then
- return { scheme = "file", path = filename, original = filename, filename = filename }
- end
- local specification = url.hashed(filename)
- if not specification.scheme or specification.scheme == "" then
- return { scheme = "file", path = filename, original = filename, filename = filename }
- else
- return specification
- end
-end
-
-resolvers.splitmethod = splitmethod -- bad name but ok
-
--- the second argument is always analyzed (saves time later on) and the original
--- gets passed as original but also as argument
-
-local function methodhandler(what,first,...) -- filename can be nil or false
- local method = registered[what]
- if method then
- local how, namespace = method.how, method.namespace
- if how == "uri" or how == "url" then
- local specification = splitmethod(first)
- local scheme = specification.scheme
- local resolver = namespace and namespace[scheme]
- if resolver then
- if trace_methods then
- report_methods("resolver: method=%s, how=%s, scheme=%s, argument=%s",what,how,scheme,first)
- end
- return resolver(specification,...)
- else
- resolver = namespace.default or namespace.file
- if resolver then
- if trace_methods then
- report_methods("resolver: method=%s, how=%s, default, argument=%s",what,how,first)
- end
- return resolver(specification,...)
- elseif trace_methods then
- report_methods("resolver: method=%s, how=%s, no handler",what,how)
- end
- end
- elseif how == "tag" then
- local resolver = namespace and namespace[first]
- if resolver then
- if trace_methods then
- report_methods("resolver: method=%s, how=%s, tag=%s",what,how,first)
- end
- return resolver(...)
- else
- resolver = namespace.default or namespace.file
- if resolver then
- if trace_methods then
- report_methods("resolver: method=%s, how=%s, default",what,how)
- end
- return resolver(...)
- elseif trace_methods then
- report_methods("resolver: method=%s, how=%s, unknown",what,how)
- end
- end
- end
- else
- report_methods("resolver: method=%s, unknown",what)
- end
-end
-
-resolvers.methodhandler = methodhandler
-
-function resolvers.registermethod(name,namespace,how)
- registered[name] = { how = how or "tag", namespace = namespace }
- namespace["byscheme"] = function(scheme,filename,...)
- if scheme == "file" then
- return methodhandler(name,filename,...)
- else
- return methodhandler(name,addurlscheme(filename,scheme),...)
- end
- end
-end
-
-local concatinators = allocate { notfound = file.join } -- concatinate paths
-local locators = allocate { notfound = function() end } -- locate databases
-local hashers = allocate { notfound = function() end } -- load databases
-local generators = allocate { notfound = function() end } -- generate databases
-
-resolvers.concatinators = concatinators
-resolvers.locators = locators
-resolvers.hashers = hashers
-resolvers.generators = generators
-
-local registermethod = resolvers.registermethod
-
-registermethod("concatinators",concatinators,"tag")
-registermethod("locators", locators, "uri")
-registermethod("hashers", hashers, "uri")
-registermethod("generators", generators, "uri")
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['data-res'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files",
-}
-
--- In practice we will work within one tds tree, but i want to keep
--- the option open to build tools that look at multiple trees, which is
--- why we keep the tree specific data in a table. We used to pass the
--- instance but for practical purposes we now avoid this and use a
--- instance variable. We always have one instance active (sort of global).
-
--- todo: cache:/// home:/// selfautoparent:/// (sometime end 2012)
-
-local format, gsub, find, lower, upper, match, gmatch = string.format, string.gsub, string.find, string.lower, string.upper, string.match, string.gmatch
-local concat, insert, sortedkeys = table.concat, table.insert, table.sortedkeys
-local next, type, rawget = next, type, rawget
-local os = os
-
-local P, S, R, C, Cc, Cs, Ct, Carg = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.Cc, lpeg.Cs, lpeg.Ct, lpeg.Carg
-local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
-
-local filedirname = file.dirname
-local filebasename = file.basename
-local fileextname = file.extname
-local filejoin = file.join
-local collapsepath = file.collapsepath
-local joinpath = file.joinpath
-local allocate = utilities.storage.allocate
-local setmetatableindex = table.setmetatableindex
-
-local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
-local trace_detail = false trackers.register("resolvers.details", function(v) trace_detail = v end)
-local trace_expansions = false trackers.register("resolvers.expansions", function(v) trace_expansions = v end)
-
-local report_resolving = logs.reporter("resolvers","resolving")
-
-local resolvers = resolvers
-
-local expandedpathfromlist = resolvers.expandedpathfromlist
-local checkedvariable = resolvers.checkedvariable
-local splitconfigurationpath = resolvers.splitconfigurationpath
-local methodhandler = resolvers.methodhandler
-
-local initializesetter = utilities.setters.initialize
-
-local ostype, osname, osenv, ossetenv, osgetenv = os.type, os.name, os.env, os.setenv, os.getenv
-
-resolvers.cacheversion = '1.0.1'
-resolvers.configbanner = ''
-resolvers.homedir = environment.homedir
-resolvers.criticalvars = allocate { "SELFAUTOLOC", "SELFAUTODIR", "SELFAUTOPARENT", "TEXMFCNF", "TEXMF", "TEXOS" }
-resolvers.luacnfname = 'texmfcnf.lua'
-resolvers.luacnfstate = "unknown"
-
--- The web2c tex binaries as well as kpse have built in paths for the configuration
--- files and there can be a depressing truckload of them. This is actually the weak
--- spot of a distribution. So we don't want:
---
--- resolvers.luacnfspec = '{$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,}/web2c}'
---
--- but instead use:
---
--- resolvers.luacnfspec = 'selfautoparent:{/texmf{-local,}{,/web2c}}'
---
--- which does not make texlive happy as there is a texmf-local tree one level up
--- (sigh), so we need this. We can assume web2c as mkiv does not run on older
--- texlives anyway.
---
--- texlive:
---
--- selfautodir:
--- selfautoparent:
--- selfautodir:share/texmf-local/web2c
--- selfautodir:share/texmf/web2c
--- selfautodir:texmf-local/web2c
--- selfautodir:texmf/web2c
--- selfautoparent:share/texmf-local/web2c
--- selfautoparent:share/texmf/web2c
--- selfautoparent:texmf-local/web2c
--- selfautoparent:texmf/web2c
---
--- minimals:
---
--- home:texmf/web2c
--- selfautoparent:texmf-local/web2c
--- selfautoparent:texmf-context/web2c
--- selfautoparent:texmf/web2c
-
-if environment.default_texmfcnf then
- -- unfortunately we now have quite some overkill in the spec (not so nice on a network)
- resolvers.luacnfspec = environment.default_texmfcnf
-else
- -- resolvers.luacnfspec = "selfautoparent:texmf{-local,-context,}/web2c"
- resolvers.luacnfspec = "{selfautoloc:,selfautodir:,selfautoparent:}{,/texmf{-local,}/web2c}"
-end
-
-resolvers.luacnfspec = 'home:texmf/web2c;' .. resolvers.luacnfspec
-
--- which (as we want users to use the web2c path) be can be simplified to this:
---
--- if environment and environment.ownpath and string.find(environment.ownpath,"[\\/]texlive[\\/]") then
--- resolvers.luacnfspec = 'selfautodir:/texmf-local/web2c,selfautoparent:/texmf-local/web2c,selfautoparent:/texmf/web2c'
--- else
--- resolvers.luacnfspec = 'selfautoparent:/texmf-local/web2c,selfautoparent:/texmf/web2c'
--- end
-
-
-
-local unset_variable = "unset"
-
-local formats = resolvers.formats
-local suffixes = resolvers.suffixes
-local dangerous = resolvers.dangerous
-local suffixmap = resolvers.suffixmap
-
-resolvers.defaultsuffixes = { "tex" } -- "mkiv", "cld" -- too tricky
-
-resolvers.instance = resolvers.instance or nil -- the current one (slow access)
-local instance = resolvers.instance or nil -- the current one (fast access)
-
--- An instance has an environment (coming from the outside, kept raw), variables
--- (coming from the configuration file), and expansions (variables with nested
--- variables replaced). One can push something into the outer environment and
--- its internal copy, but only the later one will be the raw unprefixed variant.
-
-function resolvers.setenv(key,value,raw)
- if instance then
- -- this one will be consulted first when we stay inside
- -- the current environment (prefixes are not resolved here)
- instance.environment[key] = value
- -- we feed back into the environment, and as this is used
- -- by other applications (via os.execute) we need to make
- -- sure that prefixes are resolve
- ossetenv(key,raw and value or resolvers.resolve(value))
- end
-end
-
--- Beware we don't want empty here as this one can be called early on
--- and therefore we use rawget.
-
-local function getenv(key)
- local value = rawget(instance.environment,key)
- if value and value ~= "" then
- return value
- else
- local e = osgetenv(key)
- return e ~= nil and e ~= "" and checkedvariable(e) or ""
- end
-end
-
-resolvers.getenv = getenv
-resolvers.env = getenv
-
--- We are going to use some metatable trickery where we backtrack from
--- expansion to variable to environment.
-
-local function resolve(k)
- return instance.expansions[k]
-end
-
-local dollarstripper = lpeg.stripper("$")
-local inhibitstripper = P("!")^0 * Cs(P(1)^0)
-local backslashswapper = lpeg.replacer("\\","/")
-
-local somevariable = P("$") / ""
-local somekey = C(R("az","AZ","09","__","--")^1)
-local somethingelse = P(";") * ((1-S("!{}/\\"))^1 * P(";") / "")
- + P(";") * (P(";") / "")
- + P(1)
-local variableexpander = Cs( (somevariable * (somekey/resolve) + somethingelse)^1 )
-
-local cleaner = P("\\") / "/" + P(";") * S("!{}/\\")^0 * P(";")^1 / ";"
-local variablecleaner = Cs((cleaner + P(1))^0)
-
-local somevariable = R("az","AZ","09","__","--")^1 / resolve
-local variable = (P("$")/"") * (somevariable + (P("{")/"") * somevariable * (P("}")/""))
-local variableresolver = Cs((variable + P(1))^0)
-
-local function expandedvariable(var)
- return lpegmatch(variableexpander,var) or var
-end
-
-function resolvers.newinstance() -- todo: all vars will become lowercase and alphanum only
-
- if trace_locating then
- report_resolving("creating instance")
- end
-
- local environment, variables, expansions, order = allocate(), allocate(), allocate(), allocate()
-
- local newinstance = {
- environment = environment,
- variables = variables,
- expansions = expansions,
- order = order,
- files = allocate(),
- setups = allocate(),
- found = allocate(),
- foundintrees = allocate(),
- hashes = allocate(),
- hashed = allocate(),
- specification = allocate(),
- lists = allocate(),
- data = allocate(), -- only for loading
- fakepaths = allocate(),
- remember = true,
- diskcache = true,
- renewcache = false,
- renewtree = false,
- loaderror = false,
- savelists = true,
- pattern = nil, -- lists
- force_suffixes = true,
- }
-
- setmetatableindex(variables,function(t,k)
- local v
- for i=1,#order do
- v = order[i][k]
- if v ~= nil then
- t[k] = v
- return v
- end
- end
- if v == nil then
- v = ""
- end
- t[k] = v
- return v
- end)
-
- setmetatableindex(environment, function(t,k)
- local v = osgetenv(k)
- if v == nil then
- v = variables[k]
- end
- if v ~= nil then
- v = checkedvariable(v) or ""
- end
- v = resolvers.repath(v) -- for taco who has a : separated osfontdir
- t[k] = v
- return v
- end)
-
- setmetatableindex(expansions, function(t,k)
- local v = environment[k]
- if type(v) == "string" then
- v = lpegmatch(variableresolver,v)
- v = lpegmatch(variablecleaner,v)
- end
- t[k] = v
- return v
- end)
-
- return newinstance
-
-end
-
-function resolvers.setinstance(someinstance) -- only one instance is active
- instance = someinstance
- resolvers.instance = someinstance
- return someinstance
-end
-
-function resolvers.reset()
- return resolvers.setinstance(resolvers.newinstance())
-end
-
-local function reset_hashes()
- instance.lists = { }
- instance.found = { }
-end
-
-local slash = P("/")
-
-local pathexpressionpattern = Cs (
- Cc("^") * (
- Cc("%") * S(".-")
- + slash^2 * P(-1) / "/.*"
- + slash^2 / "/.-/"
- + (1-slash) * P(-1) * Cc("/")
- + P(1)
- )^1 * Cc("$") -- yes or no $
-)
-
-local cache = { }
-
-local function makepathexpression(str)
- if str == "." then
- return "^%./$"
- else
- local c = cache[str]
- if not c then
- c = lpegmatch(pathexpressionpattern,str)
- cache[str] = c
- end
- return c
- end
-end
-
-local function reportcriticalvariables(cnfspec)
- if trace_locating then
- for i=1,#resolvers.criticalvars do
- local k = resolvers.criticalvars[i]
- local v = resolvers.getenv(k) or "unknown" -- this one will not resolve !
- report_resolving("variable '%s' set to '%s'",k,v)
- end
- report_resolving()
- if cnfspec then
- if type(cnfspec) == "table" then
- report_resolving("using configuration specification '%s'",concat(cnfspec,","))
- else
- report_resolving("using configuration specification '%s'",cnfspec)
- end
- end
- report_resolving()
- end
- reportcriticalvariables = function() end
-end
-
-local function identify_configuration_files()
- local specification = instance.specification
- if #specification == 0 then
- local cnfspec = getenv('TEXMFCNF')
- if cnfspec == "" then
- cnfspec = resolvers.luacnfspec
- resolvers.luacnfstate = "default"
- else
- resolvers.luacnfstate = "environment"
- end
- reportcriticalvariables(cnfspec)
- local cnfpaths = expandedpathfromlist(resolvers.splitpath(cnfspec))
- local luacnfname = resolvers.luacnfname
- for i=1,#cnfpaths do
- local filename = collapsepath(filejoin(cnfpaths[i],luacnfname))
- local realname = resolvers.resolve(filename)
- if lfs.isfile(realname) then
- specification[#specification+1] = filename
- if trace_locating then
- report_resolving("found configuration file '%s'",realname)
- end
- elseif trace_locating then
- report_resolving("unknown configuration file '%s'",realname)
- end
- end
- if trace_locating then
- report_resolving()
- end
- elseif trace_locating then
- report_resolving("configuration files already identified")
- end
-end
-
-local function load_configuration_files()
- local specification = instance.specification
- if #specification > 0 then
- local luacnfname = resolvers.luacnfname
- for i=1,#specification do
- local filename = specification[i]
- local pathname = filedirname(filename)
- local filename = filejoin(pathname,luacnfname)
- local realname = resolvers.resolve(filename) -- no shortcut
- local blob = loadfile(realname)
- if blob then
- local setups = instance.setups
- local data = blob()
- local parent = data and data.parent
- if parent then
- local filename = filejoin(pathname,parent)
- local realname = resolvers.resolve(filename) -- no shortcut
- local blob = loadfile(realname)
- if blob then
- local parentdata = blob()
- if parentdata then
- report_resolving("loading configuration file '%s'",filename)
- data = table.merged(parentdata,data)
- end
- end
- end
- data = data and data.content
- if data then
- if trace_locating then
- report_resolving("loading configuration file '%s'",filename)
- report_resolving()
- end
- local variables = data.variables or { }
- local warning = false
- for k, v in next, data do
- local variant = type(v)
- if variant == "table" then
- initializesetter(filename,k,v)
- elseif variables[k] == nil then
- if trace_locating and not warning then
- report_resolving("variables like '%s' in configuration file '%s' should move to the 'variables' subtable",
- k,resolvers.resolve(filename))
- warning = true
- end
- variables[k] = v
- end
- end
- setups[pathname] = variables
- if resolvers.luacnfstate == "default" then
- -- the following code is not tested
- local cnfspec = variables["TEXMFCNF"]
- if cnfspec then
- if trace_locating then
- report_resolving("reloading configuration due to TEXMF redefinition")
- end
- -- we push the value into the main environment (osenv) so
- -- that it takes precedence over the default one and therefore
- -- also over following definitions
- resolvers.setenv('TEXMFCNF',cnfspec) -- resolves prefixes
- -- we now identify and load the specified configuration files
- instance.specification = { }
- identify_configuration_files()
- load_configuration_files()
- -- we prevent further overload of the configuration variable
- resolvers.luacnfstate = "configuration"
- -- we quit the outer loop
- break
- end
- end
-
- else
- if trace_locating then
- report_resolving("skipping configuration file '%s' (no content)",filename)
- end
- setups[pathname] = { }
- instance.loaderror = true
- end
- elseif trace_locating then
- report_resolving("skipping configuration file '%s' (no valid format)",filename)
- end
- instance.order[#instance.order+1] = instance.setups[pathname]
- if instance.loaderror then
- break
- end
- end
- elseif trace_locating then
- report_resolving("warning: no lua configuration files found")
- end
-end
-
--- scheme magic ... database loading
-
-local function load_file_databases()
- instance.loaderror, instance.files = false, allocate()
- if not instance.renewcache then
- local hashes = instance.hashes
- for k=1,#hashes do
- local hash = hashes[k]
- resolvers.hashers.byscheme(hash.type,hash.name)
- if instance.loaderror then break end
- end
- end
-end
-
-local function locate_file_databases()
- -- todo: cache:// and tree:// (runtime)
- local texmfpaths = resolvers.expandedpathlist('TEXMF')
- if #texmfpaths > 0 then
- for i=1,#texmfpaths do
- local path = collapsepath(texmfpaths[i])
- local stripped = lpegmatch(inhibitstripper,path) -- the !! thing
- if stripped ~= "" then
- local runtime = stripped == path
- path = resolvers.cleanpath(path)
- local spec = resolvers.splitmethod(stripped)
- if runtime and (spec.noscheme or spec.scheme == "file") then
- stripped = "tree:///" .. stripped
- elseif spec.scheme == "cache" or spec.scheme == "file" then
- stripped = spec.path
- end
- if trace_locating then
- if runtime then
- report_resolving("locating list of '%s' (runtime) (%s)",path,stripped)
- else
- report_resolving("locating list of '%s' (cached)",path)
- end
- end
- methodhandler('locators',stripped)
- end
- end
- if trace_locating then
- report_resolving()
- end
- elseif trace_locating then
- report_resolving("no texmf paths are defined (using TEXMF)")
- end
-end
-
-local function generate_file_databases()
- local hashes = instance.hashes
- for k=1,#hashes do
- local hash = hashes[k]
- methodhandler('generators',hash.name)
- end
- if trace_locating then
- report_resolving()
- end
-end
-
-local function save_file_databases() -- will become cachers
- for i=1,#instance.hashes do
- local hash = instance.hashes[i]
- local cachename = hash.name
- if hash.cache then
- local content = instance.files[cachename]
- caches.collapsecontent(content)
- if trace_locating then
- report_resolving("saving tree '%s'",cachename)
- end
- caches.savecontent(cachename,"files",content)
- elseif trace_locating then
- report_resolving("not saving runtime tree '%s'",cachename)
- end
- end
-end
-
-function resolvers.renew(hashname)
- if hashname and hashname ~= "" then
- local expanded = resolvers.expansion(hashname) or ""
- if expanded ~= "" then
- if trace_locating then
- report_resolving("identifying tree '%s' from '%s'",expanded,hashname)
- end
- hashname = expanded
- else
- if trace_locating then
- report_resolving("identifying tree '%s'",hashname)
- end
- end
- local realpath = resolvers.resolve(hashname)
- if lfs.isdir(realpath) then
- if trace_locating then
- report_resolving("using path '%s'",realpath)
- end
- methodhandler('generators',hashname)
- -- could be shared
- local content = instance.files[hashname]
- caches.collapsecontent(content)
- if trace_locating then
- report_resolving("saving tree '%s'",hashname)
- end
- caches.savecontent(hashname,"files",content)
- -- till here
- else
- report_resolving("invalid path '%s'",realpath)
- end
- end
-end
-
-local function load_databases()
- locate_file_databases()
- if instance.diskcache and not instance.renewcache then
- load_file_databases()
- if instance.loaderror then
- generate_file_databases()
- save_file_databases()
- end
- else
- generate_file_databases()
- if instance.renewcache then
- save_file_databases()
- end
- end
-end
-
-function resolvers.appendhash(type,name,cache)
- -- safeguard ... tricky as it's actually a bug when seen twice
- if not instance.hashed[name] then
- if trace_locating then
- report_resolving("hash '%s' appended",name)
- end
- insert(instance.hashes, { type = type, name = name, cache = cache } )
- instance.hashed[name] = cache
- end
-end
-
-function resolvers.prependhash(type,name,cache)
- -- safeguard ... tricky as it's actually a bug when seen twice
- if not instance.hashed[name] then
- if trace_locating then
- report_resolving("hash '%s' prepended",name)
- end
- insert(instance.hashes, 1, { type = type, name = name, cache = cache } )
- instance.hashed[name] = cache
- end
+local function tagstostring(list)
+ if #list==0 then
+ return "no elements"
+ else
+ local t={}
+ for i=1,#list do
+ local li=list[i]
+ local ns,tg=li.ns,li.tg
+ if not ns or ns=="" then ns="*" end
+ if not tg or tg=="" then tg="*" end
+ t[i]=(tg=="@rt@" and "[root]") or format("%s:%s",ns,tg)
+ end
+ return concat(t," ")
+ end
+end
+xml.nodesettostring=nodesettostring
+local lpath
+local lshowoptions={ functions=false }
+local function lshow(parsed)
+ if type(parsed)=="string" then
+ parsed=lpath(parsed)
+ end
+ report_lpath("%s://%s => %s",parsed.protocol or xml.defaultprotocol,parsed.pattern,
+ table.serialize(parsed,false,lshowoptions))
end
-
-function resolvers.extendtexmfvariable(specification) -- crap, we could better prepend the hash
- local t = resolvers.splitpath(getenv('TEXMF'))
- insert(t,1,specification)
- local newspec = concat(t,";")
- if instance.environment["TEXMF"] then
- instance.environment["TEXMF"] = newspec
- elseif instance.variables["TEXMF"] then
- instance.variables["TEXMF"] = newspec
+xml.lshow=lshow
+local function add_comment(p,str)
+ local pc=p.comment
+ if not pc then
+ p.comment={ str }
+ else
+ pc[#pc+1]=str
+ end
+end
+lpath=function (pattern)
+ lpathcalls=lpathcalls+1
+ if type(pattern)=="table" then
+ return pattern
+ else
+ local parsed=cache[pattern]
+ if parsed then
+ lpathcached=lpathcached+1
else
- -- weird
- end
- reset_hashes()
-end
-
-function resolvers.splitexpansions()
- local ie = instance.expansions
- for k,v in next, ie do
- local t, tn, h, p = { }, 0, { }, splitconfigurationpath(v)
- for kk=1,#p do
- local vv = p[kk]
- if vv ~= "" and not h[vv] then
- tn = tn + 1
- t[tn] = vv
- h[vv] = true
- end
- end
- if #t > 1 then
- ie[k] = t
+ parsed=lpegmatch(pathparser,pattern)
+ if parsed then
+ parsed.pattern=pattern
+ local np=#parsed
+ if np==0 then
+ parsed={ pattern=pattern,register_self,state="parsing error" }
+ report_lpath("parsing error in pattern: %s",pattern)
+ lshow(parsed)
else
- ie[k] = t[1]
- end
+ local pi=parsed[1]
+ if pi.axis=="auto-child" then
+ if false then
+ add_comment(parsed,"auto-child replaced by auto-descendant-or-self")
+ parsed[1]=register_auto_descendant_or_self
+ else
+ add_comment(parsed,"auto-child replaced by auto-descendant")
+ parsed[1]=register_auto_descendant
+ end
+ elseif pi.axis=="initial-child" and np>1 and parsed[2].axis then
+ add_comment(parsed,"initial-child removed")
+ remove(parsed,1)
+ end
+ local np=#parsed
+ if np>1 then
+ local pnp=parsed[np]
+ if pnp.kind=="nodes" and pnp.nodetest==true then
+ local nodes=pnp.nodes
+ if nodes[1]==true and nodes[2]==false and nodes[3]==false then
+ add_comment(parsed,"redundant final wildcard filter removed")
+ remove(parsed,np)
+ end
+ end
+ end
+ end
+ else
+ parsed={ pattern=pattern }
+ end
+ cache[pattern]=parsed
+ if trace_lparse and not trace_lprofile then
+ lshow(parsed)
+ end
end
+ return parsed
+ end
end
-
--- end of split/join code
-
--- we used to have 'files' and 'configurations' so therefore the following
--- shared function
-
-function resolvers.datastate()
- return caches.contentstate()
+xml.lpath=lpath
+local profiled={} xml.profiled=profiled
+local function profiled_apply(list,parsed,nofparsed,order)
+ local p=profiled[parsed.pattern]
+ if p then
+ p.tested=p.tested+1
+ else
+ p={ tested=1,matched=0,finalized=0 }
+ profiled[parsed.pattern]=p
+ end
+ local collected=list
+ for i=1,nofparsed do
+ local pi=parsed[i]
+ local kind=pi.kind
+ if kind=="axis" then
+ collected=apply_axis[pi.axis](collected)
+ elseif kind=="nodes" then
+ collected=apply_nodes(collected,pi.nodetest,pi.nodes)
+ elseif kind=="expression" then
+ collected=apply_expression(collected,pi.evaluator,order)
+ elseif kind=="finalizer" then
+ collected=pi.finalizer(collected)
+ p.matched=p.matched+1
+ p.finalized=p.finalized+1
+ return collected
+ end
+ if not collected or #collected==0 then
+ local pn=i %s",(collected and #collected) or 0,pi.expression,pi.converted)
+ elseif kind=="finalizer" then
+ collected=pi.finalizer(collected)
+ report_lpath("% 10i : fi : %s : %s(%s)",(type(collected)=="table" and #collected) or 0,parsed.protocol or xml.defaultprotocol,pi.name,pi.arguments or "")
+ return collected
+ end
+ if not collected or #collected==0 then
+ local pn=i 0 then
- instance.lists, done = { }, { }
+local function selection(root,pattern,handle)
+ local collected=applylpath(root,pattern)
+ if collected then
+ if handle then
+ for c=1,#collected do
+ handle(collected[c])
+ end
+ else
+ return collected
end
+ end
end
-
-function resolvers.registerextrapath(paths,subpaths)
- local ep = instance.extra_paths or { }
- local oldn = #ep
- local newn = oldn
- if paths and paths ~= "" then
- if subpaths and subpaths ~= "" then
- for p in gmatch(paths,"[^,]+") do
- -- we gmatch each step again, not that fast, but used seldom
- for s in gmatch(subpaths,"[^,]+") do
- local ps = p .. "/" .. s
- if not done[ps] then
- newn = newn + 1
- ep[newn] = resolvers.cleanpath(ps)
- done[ps] = true
- end
- end
- end
+xml.traverse=traverse
+xml.selection=selection
+local function dofunction(collected,fnc,...)
+ if collected then
+ local f=functions[fnc]
+ if f then
+ for c=1,#collected do
+ f(collected[c],...)
+ end
+ else
+ report_lpath("unknown function %a",fnc)
+ end
+ end
+end
+finalizers.xml["function"]=dofunction
+finalizers.tex["function"]=dofunction
+expressions.text=function(e,n)
+ local rdt=e.__p__.dt
+ return rdt and rdt[n] or ""
+end
+expressions.name=function(e,n)
+ local found=false
+ n=tonumber(n) or 0
+ if n==0 then
+ found=type(e)=="table" and e
+ elseif n<0 then
+ local d,k=e.__p__.dt,e.ni
+ for i=k-1,1,-1 do
+ local di=d[i]
+ if type(di)=="table" then
+ if n==-1 then
+ found=di
+ break
else
- for p in gmatch(paths,"[^,]+") do
- if not done[p] then
- newn = newn + 1
- ep[newn] = resolvers.cleanpath(p)
- done[p] = true
- end
- end
- end
- elseif subpaths and subpaths ~= "" then
- for i=1,oldn do
- -- we gmatch each step again, not that fast, but used seldom
- for s in gmatch(subpaths,"[^,]+") do
- local ps = ep[i] .. "/" .. s
- if not done[ps] then
- newn = newn + 1
- ep[newn] = resolvers.cleanpath(ps)
- done[ps] = true
- end
- end
+ n=n+1
+ end
+ end
+ end
+ else
+ local d,k=e.__p__.dt,e.ni
+ for i=k+1,#d,1 do
+ local di=d[i]
+ if type(di)=="table" then
+ if n==1 then
+ found=di
+ break
+ else
+ n=n-1
end
+ end
end
- if newn > 0 then
- instance.extra_paths = ep -- register paths
- end
- if newn > oldn then
- instance.lists = { } -- erase the cache
- end
-end
-
-local function made_list(instance,list)
- local ep = instance.extra_paths
- if not ep or #ep == 0 then
- return list
+ end
+ if found then
+ local ns,tg=found.rn or found.ns or "",found.tg
+ if ns~="" then
+ return ns..":"..tg
else
- local done, new, newn = { }, { }, 0
- -- honour . .. ../.. but only when at the start
- for k=1,#list do
- local v = list[k]
- if not done[v] then
- if find(v,"^[%.%/]$") then
- done[v] = true
- newn = newn + 1
- new[newn] = v
- else
- break
- end
- end
- end
- -- first the extra paths
- for k=1,#ep do
- local v = ep[k]
- if not done[v] then
- done[v] = true
- newn = newn + 1
- new[newn] = v
- end
- end
- -- next the formal paths
- for k=1,#list do
- local v = list[k]
- if not done[v] then
- done[v] = true
- newn = newn + 1
- new[newn] = v
- end
- end
- return new
+ return tg
end
+ else
+ return ""
+ end
end
-
-function resolvers.cleanpathlist(str)
- local t = resolvers.expandedpathlist(str)
- if t then
- for i=1,#t do
- t[i] = collapsepath(resolvers.cleanpath(t[i]))
+expressions.tag=function(e,n)
+ if not e then
+ return ""
+ else
+ local found=false
+ n=tonumber(n) or 0
+ if n==0 then
+ found=(type(e)=="table") and e
+ elseif n<0 then
+ local d,k=e.__p__.dt,e.ni
+ for i=k-1,1,-1 do
+ local di=d[i]
+ if type(di)=="table" then
+ if n==-1 then
+ found=di
+ break
+ else
+ n=n+1
+ end
end
+ end
+ else
+ local d,k=e.__p__.dt,e.ni
+ for i=k+1,#d,1 do
+ local di=d[i]
+ if type(di)=="table" then
+ if n==1 then
+ found=di
+ break
+ else
+ n=n-1
+ end
+ end
+ end
+ end
+ return (found and found.tg) or ""
+ end
+end
+local dummy=function() end
+function xml.elements(root,pattern,reverse)
+ local collected=applylpath(root,pattern)
+ if not collected then
+ return dummy
+ elseif reverse then
+ local c=#collected+1
+ return function()
+ if c>1 then
+ c=c-1
+ local e=collected[c]
+ local r=e.__p__
+ return r,r.dt,e.ni
+ end
+ end
+ else
+ local n,c=#collected,0
+ return function()
+ if c1 then
+ c=c-1
+ return collected[c]
+ end
end
- return t
+ else
+ local n,c=#collected,0
+ return function()
+ if c"))^0
+local special=P("<")/"<"+P(">")/">"+P("&")/"&"
+local escaped=Cs(normal*(special*normal)^0)
+local normal=(1-S"&")^0
+local special=P("<")/"<"+P(">")/">"+P("&")/"&"
+local unescaped=Cs(normal*(special*normal)^0)
+local cleansed=Cs(((P("<")*(1-P(">"))^0*P(">"))/""+1)^0)
+xmlpatterns.escaped=escaped
+xmlpatterns.unescaped=unescaped
+xmlpatterns.cleansed=cleansed
+function xml.escaped (str) return lpegmatch(escaped,str) end
+function xml.unescaped(str) return lpegmatch(unescaped,str) end
+function xml.cleansed (str) return lpegmatch(cleansed,str) end
+function xml.fillin(root,pattern,str,check)
+ local e=xml.first(root,pattern)
+ if e then
+ local n=#e.dt
+ if not check or n==0 or (n==1 and e.dt[1]=="") then
+ e.dt={ str }
end
- return readable
+ end
end
--- name
--- name/name
-local function collect_files(names)
- local filelist, noffiles = { }, 0
- for k=1,#names do
- local fname = names[k]
- if trace_detail then
- report_resolving("checking name '%s'",fname)
- end
- local bname = filebasename(fname)
- local dname = filedirname(fname)
- if dname == "" or find(dname,"^%.") then
- dname = false
- else
-dname = gsub(dname,"*","%.*")
- dname = "/" .. dname .. "$"
- end
- local hashes = instance.hashes
- for h=1,#hashes do
- local hash = hashes[h]
- local blobpath = hash.name
- local files = blobpath and instance.files[blobpath]
- if files then
- if trace_detail then
- report_resolving("deep checking '%s' (%s)",blobpath,bname)
- end
- local blobfile = files[bname]
- if not blobfile then
- local rname = "remap:"..bname
- blobfile = files[rname]
- if blobfile then
- bname = files[rname]
- blobfile = files[bname]
- end
- end
- if blobfile then
- local blobroot = files.__path__ or blobpath
- if type(blobfile) == 'string' then
- if not dname or find(blobfile,dname) then
- local variant = hash.type
- -- local search = filejoin(blobpath,blobfile,bname)
- local search = filejoin(blobroot,blobfile,bname)
- local result = methodhandler('concatinators',hash.type,blobroot,blobfile,bname)
- if trace_detail then
- report_resolving("match: variant '%s', search '%s', result '%s'",variant,search,result)
- end
- noffiles = noffiles + 1
- filelist[noffiles] = { variant, search, result }
- end
- else
- for kk=1,#blobfile do
- local vv = blobfile[kk]
- if not dname or find(vv,dname) then
- local variant = hash.type
- -- local search = filejoin(blobpath,vv,bname)
- local search = filejoin(blobroot,vv,bname)
- local result = methodhandler('concatinators',hash.type,blobroot,vv,bname)
- if trace_detail then
- report_resolving("match: variant '%s', search '%s', result '%s'",variant,search,result)
- end
- noffiles = noffiles + 1
- filelist[noffiles] = { variant, search, result }
- end
- end
- end
- end
- elseif trace_locating then
- report_resolving("no match in '%s' (%s)",blobpath,bname)
- end
- end
- end
- return noffiles > 0 and filelist or nil
-end
+end -- of closure
-local fit = { }
+do -- create closure to overcome 200 locals limit
-function resolvers.registerintrees(filename,format,filetype,usedmethod,foundname)
- local foundintrees = instance.foundintrees
- if usedmethod == "direct" and filename == foundname and fit[foundname] then
- -- just an extra lookup after a test on presence
- else
- local t = {
- filename = filename,
- format = format ~= "" and format or nil,
- filetype = filetype ~= "" and filetype or nil,
- usedmethod = usedmethod,
- foundname = foundname,
- }
- fit[foundname] = t
- foundintrees[#foundintrees+1] = t
- end
-end
+package.loaded["lxml-aux"] = package.loaded["lxml-aux"] or true
--- split the next one up for readability (but this module needs a cleanup anyway)
+-- original size: 23804, stripped down to: 16817
-local function can_be_dir(name) -- can become local
- local fakepaths = instance.fakepaths
- if not fakepaths[name] then
- if lfs.isdir(name) then
- fakepaths[name] = 1 -- directory
- else
- fakepaths[name] = 2 -- no directory
+if not modules then modules={} end modules ['lxml-aux']={
+ version=1.001,
+ comment="this module is the basis for the lxml-* ones",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local trace_manipulations=false trackers.register("lxml.manipulations",function(v) trace_manipulations=v end)
+local report_xml=logs.reporter("xml")
+local xml=xml
+local xmlconvert,xmlcopy,xmlname=xml.convert,xml.copy,xml.name
+local xmlinheritedconvert=xml.inheritedconvert
+local xmlapplylpath=xml.applylpath
+local xmlfilter=xml.filter
+local type,setmetatable,getmetatable=type,setmetatable,getmetatable
+local insert,remove,fastcopy,concat=table.insert,table.remove,table.fastcopy,table.concat
+local gmatch,gsub,format,find,strip=string.gmatch,string.gsub,string.format,string.find,string.strip
+local utfbyte=utf.byte
+local function report(what,pattern,c,e)
+ report_xml("%s element %a, root %a, position %a, index %a, pattern %a",what,xmlname(e),xmlname(e.__p__),c,e.ni,pattern)
+end
+local function withelements(e,handle,depth)
+ if e and handle then
+ local edt=e.dt
+ if edt then
+ depth=depth or 0
+ for i=1,#edt do
+ local e=edt[i]
+ if type(e)=="table" then
+ handle(e,depth)
+ withelements(e,handle,depth+1)
end
+ end
end
- return fakepaths[name] == 1
+ end
end
-
-local preparetreepattern = Cs((P(".")/"%%." + P("-")/"%%-" + P(1))^0 * Cc("$"))
-
--- -- -- begin of main file search routing -- -- -- needs checking as previous has been patched
-
-local collect_instance_files
-
-local function find_analyze(filename,askedformat,allresults)
- local filetype, wantedfiles, ext = '', { }, fileextname(filename)
- -- too tricky as filename can be bla.1.2.3:
- --
- -- if not suffixmap[ext] then
- -- wantedfiles[#wantedfiles+1] = filename
- -- end
- wantedfiles[#wantedfiles+1] = filename
- if askedformat == "" then
- if ext == "" or not suffixmap[ext] then
- local defaultsuffixes = resolvers.defaultsuffixes
- for i=1,#defaultsuffixes do
- local forcedname = filename .. '.' .. defaultsuffixes[i]
- wantedfiles[#wantedfiles+1] = forcedname
- filetype = resolvers.formatofsuffix(forcedname)
- if trace_locating then
- report_resolving("forcing filetype '%s'",filetype)
- end
- end
- else
- filetype = resolvers.formatofsuffix(filename)
- if trace_locating then
- report_resolving("using suffix based filetype '%s'",filetype)
+xml.withelements=withelements
+function xml.withelement(e,n,handle)
+ if e and n~=0 and handle then
+ local edt=e.dt
+ if edt then
+ if n>0 then
+ for i=1,#edt do
+ local ei=edt[i]
+ if type(ei)=="table" then
+ if n==1 then
+ handle(ei)
+ return
+ else
+ n=n-1
end
+ end
end
- else
- if ext == "" or not suffixmap[ext] then
- local format_suffixes = suffixes[askedformat]
- if format_suffixes then
- for i=1,#format_suffixes do
- wantedfiles[#wantedfiles+1] = filename .. "." .. format_suffixes[i]
- end
+ elseif n<0 then
+ for i=#edt,1,-1 do
+ local ei=edt[i]
+ if type(ei)=="table" then
+ if n==-1 then
+ handle(ei)
+ return
+ else
+ n=n+1
end
+ end
end
- filetype = askedformat
- if trace_locating then
- report_resolving("using given filetype '%s'",filetype)
- end
+ end
end
- return filetype, wantedfiles
+ end
end
-
-local function find_direct(filename,allresults)
- if not dangerous[askedformat] and isreadable(filename) then
- if trace_detail then
- report_resolving("file '%s' found directly",filename)
- end
- return "direct", { filename }
+function xml.each(root,pattern,handle,reverse)
+ local collected=xmlapplylpath(root,pattern)
+ if collected then
+ if reverse then
+ for c=#collected,1,-1 do
+ handle(collected[c])
+ end
+ else
+ for c=1,#collected do
+ handle(collected[c])
+ end
end
+ return collected
+ end
end
-
-local function find_wildcard(filename,allresults)
- if find(filename,'%*') then
- if trace_locating then
- report_resolving("checking wildcard '%s'", filename)
- end
- local method, result = resolvers.findwildcardfiles(filename)
- if result then
- return "wildcard", result
- end
+function xml.processattributes(root,pattern,handle)
+ local collected=xmlapplylpath(root,pattern)
+ if collected and handle then
+ for c=1,#collected do
+ handle(collected[c].at)
end
+ end
+ return collected
end
-
-local function find_qualified(filename,allresults) -- this one will be split too
- if not file.is_qualified_path(filename) then
- return
+function xml.collect(root,pattern)
+ return xmlapplylpath(root,pattern)
+end
+function xml.collecttexts(root,pattern,flatten)
+ local collected=xmlapplylpath(root,pattern)
+ if collected and flatten then
+ local xmltostring=xml.tostring
+ for c=1,#collected do
+ collected[c]=xmltostring(collected[c].dt)
end
- if trace_locating then
- report_resolving("checking qualified name '%s'", filename)
+ end
+ return collected or {}
+end
+function xml.collect_tags(root,pattern,nonamespace)
+ local collected=xmlapplylpath(root,pattern)
+ if collected then
+ local t,n={},0
+ for c=1,#collected do
+ local e=collected[c]
+ local ns,tg=e.ns,e.tg
+ n=n+1
+ if nonamespace then
+ t[n]=tg
+ elseif ns=="" then
+ t[n]=tg
+ else
+ t[n]=ns..":"..tg
+ end
end
- if isreadable(filename) then
- if trace_detail then
- report_resolving("qualified file '%s' found", filename)
- end
- return "qualified", { filename }
+ return t
+ end
+end
+local no_root={ no_root=true }
+local function redo_ni(d)
+ for k=1,#d do
+ local dk=d[k]
+ if type(dk)=="table" then
+ dk.ni=k
end
- if trace_detail then
- report_resolving("locating qualified file '%s'", filename)
- end
- local forcedname, suffix = "", fileextname(filename)
- if suffix == "" then -- why
- local format_suffixes = askedformat == "" and resolvers.defaultsuffixes or suffixes[askedformat]
- if format_suffixes then
- for i=1,#format_suffixes do
- local s = format_suffixes[i]
- forcedname = filename .. "." .. s
- if isreadable(forcedname) then
- if trace_locating then
- report_resolving("no suffix, forcing format filetype '%s'", s)
- end
- return "qualified", { forcedname }
- end
- end
- end
+ end
+end
+local function xmltoelement(whatever,root)
+ if not whatever then
+ return nil
+ end
+ local element
+ if type(whatever)=="string" then
+ element=xmlinheritedconvert(whatever,root)
+ else
+ element=whatever
+ end
+ if element.error then
+ return whatever
+ end
+ if element then
+ end
+ return element
+end
+xml.toelement=xmltoelement
+local function copiedelement(element,newparent)
+ if type(element)=="string" then
+ return element
+ else
+ element=xmlcopy(element).dt
+ if newparent and type(element)=="table" then
+ element.__p__=newparent
end
- if suffix and suffix ~= "" then
- -- try to find in tree (no suffix manipulation), here we search for the
- -- matching last part of the name
- local basename = filebasename(filename)
- local pattern = lpegmatch(preparetreepattern,filename)
- -- messy .. to be sorted out
- local savedformat = askedformat
- local format = savedformat or ""
- if format == "" then
- askedformat = resolvers.formatofsuffix(suffix)
- end
- if not format then
- askedformat = "othertextfiles" -- kind of everything, maybe all
- end
- --
- if basename ~= filename then
- local resolved = collect_instance_files(basename,askedformat,allresults)
- if #resolved == 0 then
- local lowered = lower(basename)
- if filename ~= lowered then
- resolved = collect_instance_files(lowered,askedformat,allresults)
- end
- end
- resolvers.format = savedformat
- --
- if #resolved > 0 then
- local result = { }
- for r=1,#resolved do
- local rr = resolved[r]
- if find(rr,pattern) then
- result[#result+1] = rr
- end
- end
- if #result > 0 then
- return "qualified", result
- end
- end
+ return element
+ end
+end
+function xml.delete(root,pattern)
+ if not pattern or pattern=="" then
+ local p=root.__p__
+ if p then
+ if trace_manipulations then
+ report('deleting',"--",c,root)
+ end
+ local d=p.dt
+ remove(d,root.ni)
+ redo_ni(d)
+ end
+ else
+ local collected=xmlapplylpath(root,pattern)
+ if collected then
+ for c=1,#collected do
+ local e=collected[c]
+ local p=e.__p__
+ if p then
+ if trace_manipulations then
+ report('deleting',pattern,c,e)
+ end
+ local d=p.dt
+ remove(d,e.ni)
+ redo_ni(d)
end
- -- a real wildcard:
- --
- -- local filelist = collect_files({basename})
- -- result = { }
- -- for f=1,#filelist do
- -- local ff = filelist[f][3] or ""
- -- if find(ff,pattern) then
- -- result[#result+1], ok = ff, true
- -- end
- -- end
- -- if #result > 0 then
- -- return "qualified", result
- -- end
+ end
end
+ end
end
-
-local function check_subpath(fname)
- if isreadable(fname) then
- if trace_detail then
- report_resolving("found '%s' by deep scanning",fname)
+function xml.replace(root,pattern,whatever)
+ local element=root and xmltoelement(whatever,root)
+ local collected=element and xmlapplylpath(root,pattern)
+ if collected then
+ for c=1,#collected do
+ local e=collected[c]
+ local p=e.__p__
+ if p then
+ if trace_manipulations then
+ report('replacing',pattern,c,e)
end
- return fname
+ local d=p.dt
+ d[e.ni]=copiedelement(element,p)
+ redo_ni(d)
+ end
end
+ end
end
-
-local function find_intree(filename,filetype,wantedfiles,allresults)
- local typespec = resolvers.variableofformat(filetype)
- local pathlist = resolvers.expandedpathlist(typespec)
- local method = "intree"
- if pathlist and #pathlist > 0 then
- -- list search
- local filelist = collect_files(wantedfiles)
- local dirlist = { }
- if filelist then
- for i=1,#filelist do
- dirlist[i] = filedirname(filelist[i][3]) .. "/" -- was [2] .. gamble
- end
- end
- if trace_detail then
- report_resolving("checking filename '%s'",filename)
- end
- local result = { }
- for k=1,#pathlist do
- local path = pathlist[k]
- local pathname = lpegmatch(inhibitstripper,path)
- local doscan = path == pathname -- no ^!!
- if not find (pathname,'//$') then
- doscan = false -- we check directly on the path
- end
- local done = false
- -- using file list
- if filelist then -- database
- -- compare list entries with permitted pattern -- /xx /xx//
- local expression = makepathexpression(pathname)
- if trace_detail then
- report_resolving("using pattern '%s' for path '%s'",expression,pathname)
- end
- for k=1,#filelist do
- local fl = filelist[k]
- local f = fl[2]
- local d = dirlist[k]
- if find(d,expression) then
- -- todo, test for readable
- result[#result+1] = resolvers.resolve(fl[3]) -- no shortcut
- done = true
- if allresults then
- if trace_detail then
- report_resolving("match to '%s' in hash for file '%s' and path '%s', continue scanning",expression,f,d)
- end
- else
- if trace_detail then
- report_resolving("match to '%s' in hash for file '%s' and path '%s', quit scanning",expression,f,d)
- end
- break
- end
- elseif trace_detail then
- report_resolving("no match to '%s' in hash for file '%s' and path '%s'",expression,f,d)
- end
- end
- end
- if done then
- method = "database"
- else
- method = "filesystem" -- bonus, even when !! is specified
- pathname = gsub(pathname,"/+$","")
- pathname = resolvers.resolve(pathname)
- local scheme = url.hasscheme(pathname)
- if not scheme or scheme == "file" then
- local pname = gsub(pathname,"%.%*$",'')
- if not find(pname,"%*") then
- if can_be_dir(pname) then
- -- quick root scan first
- for k=1,#wantedfiles do
- local w = wantedfiles[k]
- local fname = check_subpath(filejoin(pname,w))
- if fname then
- result[#result+1] = fname
- done = true
- if not allresults then
- break
- end
- end
- end
- if not done and doscan then
- -- collect files in path (and cache the result)
- local files = resolvers.simplescanfiles(pname,false,true)
- for k=1,#wantedfiles do
- local w = wantedfiles[k]
- local subpath = files[w]
- if not subpath or subpath == "" then
- -- rootscan already done
- elseif type(subpath) == "string" then
- local fname = check_subpath(filejoin(pname,subpath,w))
- if fname then
- result[#result+1] = fname
- done = true
- if not allresults then
- break
- end
- end
- else
- for i=1,#subpath do
- local sp = subpath[i]
- if sp == "" then
- -- roottest already done
- else
- local fname = check_subpath(filejoin(pname,sp,w))
- if fname then
- result[#result+1] = fname
- done = true
- if not allresults then
- break
- end
- end
- end
- end
- if done and not allresults then
- break
- end
- end
- end
- end
- end
- else
- -- no access needed for non existing path, speedup (esp in large tree with lots of fake)
- end
- end
- end
- -- todo recursive scanning
- if done and not allresults then
- break
- end
- end
- if #result > 0 then
- return method, result
+local function wrap(e,wrapper)
+ local t={
+ rn=e.rn,
+ tg=e.tg,
+ ns=e.ns,
+ at=e.at,
+ dt=e.dt,
+ __p__=e,
+ }
+ setmetatable(t,getmetatable(e))
+ e.rn=wrapper.rn or e.rn or ""
+ e.tg=wrapper.tg or e.tg or ""
+ e.ns=wrapper.ns or e.ns or ""
+ e.at=fastcopy(wrapper.at)
+ e.dt={ t }
+end
+function xml.wrap(root,pattern,whatever)
+ if whatever then
+ local wrapper=xmltoelement(whatever,root)
+ local collected=xmlapplylpath(root,pattern)
+ if collected then
+ for c=1,#collected do
+ local e=collected[c]
+ if trace_manipulations then
+ report('wrapping',pattern,c,e)
end
+ wrap(e,wrapper)
+ end
+ end
+ else
+ wrap(root,xmltoelement(pattern))
+ end
+end
+local function inject_element(root,pattern,whatever,prepend)
+ local element=root and xmltoelement(whatever,root)
+ local collected=element and xmlapplylpath(root,pattern)
+ local function inject_e(e)
+ local r=e.__p__
+ local d,k,rri=r.dt,e.ni,r.ri
+ local edt=(rri and d[rri].dt) or (d and d[k] and d[k].dt)
+ if edt then
+ local be,af
+ local cp=copiedelement(element,e)
+ if prepend then
+ be,af=cp,edt
+ else
+ be,af=edt,cp
+ end
+ local bn=#be
+ for i=1,#af do
+ bn=bn+1
+ be[bn]=af[i]
+ end
+ if rri then
+ r.dt[rri].dt=be
+ else
+ d[k].dt=be
+ end
+ redo_ni(d)
+ end
+ end
+ if not collected then
+ elseif collected.tg then
+ inject_e(collected)
+ else
+ for c=1,#collected do
+ inject_e(collected[c])
+ end
+ end
+end
+local function insert_element(root,pattern,whatever,before)
+ local element=root and xmltoelement(whatever,root)
+ local collected=element and xmlapplylpath(root,pattern)
+ local function insert_e(e)
+ local r=e.__p__
+ local d,k=r.dt,e.ni
+ if not before then
+ k=k+1
+ end
+ insert(d,k,copiedelement(element,r))
+ redo_ni(d)
+ end
+ if not collected then
+ elseif collected.tg then
+ insert_e(collected)
+ else
+ for c=1,#collected do
+ insert_e(collected[c])
end
+ end
end
-
-local function find_onpath(filename,filetype,wantedfiles,allresults)
- if trace_detail then
- report_resolving("checking filename '%s', filetype '%s', wanted files '%s'",filename, filetype or '?',concat(wantedfiles," | "))
- end
- local result = { }
- for k=1,#wantedfiles do
- local fname = wantedfiles[k]
- if fname and isreadable(fname) then
- filename = fname
- result[#result+1] = filejoin('.',fname)
- if not allresults then
- break
- end
+xml.insert_element=insert_element
+xml.insertafter=insert_element
+xml.insertbefore=function(r,p,e) insert_element(r,p,e,true) end
+xml.injectafter=inject_element
+xml.injectbefore=function(r,p,e) inject_element(r,p,e,true) end
+local function include(xmldata,pattern,attribute,recursive,loaddata)
+ pattern=pattern or 'include'
+ loaddata=loaddata or io.loaddata
+ local collected=xmlapplylpath(xmldata,pattern)
+ if collected then
+ for c=1,#collected do
+ local ek=collected[c]
+ local name=nil
+ local ekdt=ek.dt
+ local ekat=ek.at
+ local epdt=ek.__p__.dt
+ if not attribute or attribute=="" then
+ name=(type(ekdt)=="table" and ekdt[1]) or ekdt
+ end
+ if not name then
+ for a in gmatch(attribute or "href","([^|]+)") do
+ name=ekat[a]
+ if name then break end
+ end
+ end
+ local data=(name and name~="" and loaddata(name)) or ""
+ if data=="" then
+ epdt[ek.ni]=""
+ elseif ekat["parse"]=="text" then
+ epdt[ek.ni]=xml.escaped(data)
+ else
+ local xi=xmlinheritedconvert(data,xmldata)
+ if not xi then
+ epdt[ek.ni]=""
+ else
+ if recursive then
+ include(xi,pattern,attribute,recursive,loaddata)
+ end
+ epdt[ek.ni]=xml.body(xi)
end
+ end
end
- if #result > 0 then
- return "onpath", result
- end
-end
-
-local function find_otherwise(filename,filetype,wantedfiles,allresults) -- other text files | any | whatever
- local filelist = collect_files(wantedfiles)
- local fl = filelist and filelist[1]
- if fl then
- return "otherwise", { resolvers.resolve(fl[3]) } -- filename
- end
-end
-
--- we could have a loop over the 6 functions but then we'd have to
--- always analyze
-
-collect_instance_files = function(filename,askedformat,allresults) -- uses nested
- askedformat = askedformat or ""
- filename = collapsepath(filename)
- if allresults then
- -- no need for caching, only used for tracing
- local filetype, wantedfiles = find_analyze(filename,askedformat)
- local results = {
- { find_direct (filename,true) },
- { find_wildcard (filename,true) },
- { find_qualified(filename,true) },
- { find_intree (filename,filetype,wantedfiles,true) },
- { find_onpath (filename,filetype,wantedfiles,true) },
- { find_otherwise(filename,filetype,wantedfiles,true) },
- }
- local result, status, done = { }, { }, { }
- for k, r in next, results do
- local method, list = r[1], r[2]
- if method and list then
- for i=1,#list do
- local c = collapsepath(list[i])
- if not done[c] then
- result[#result+1] = c
- done[c] = true
- end
- status[#status+1] = format("%-10s: %s",method,c)
- end
- end
- end
- if trace_detail then
- report_resolving("lookup status: %s",table.serialize(status,filename))
- end
- return result, status
+ end
+end
+xml.include=include
+local function stripelement(e,nolines,anywhere)
+ local edt=e.dt
+ if edt then
+ if anywhere then
+ local t,n={},0
+ for e=1,#edt do
+ local str=edt[e]
+ if type(str)~="string" then
+ n=n+1
+ t[n]=str
+ elseif str~="" then
+ if nolines then
+ str=gsub(str,"%s+"," ")
+ end
+ str=gsub(str,"^%s*(.-)%s*$","%1")
+ if str~="" then
+ n=n+1
+ t[n]=str
+ end
+ end
+ end
+ e.dt=t
else
- local method, result, stamp, filetype, wantedfiles
- if instance.remember then
- stamp = format("%s--%s", filename, askedformat)
- result = stamp and instance.found[stamp]
- if result then
- if trace_locating then
- report_resolving("remembered file '%s'",filename)
- end
- return result
- end
- end
- method, result = find_direct(filename)
- if not result then
- method, result = find_wildcard(filename)
- if not result then
- method, result = find_qualified(filename)
- if not result then
- filetype, wantedfiles = find_analyze(filename,askedformat)
- method, result = find_intree(filename,filetype,wantedfiles)
- if not result then
- method, result = find_onpath(filename,filetype,wantedfiles)
- if not result then
- method, result = find_otherwise(filename,filetype,wantedfiles)
- end
- end
- end
- end
- end
- if result and #result > 0 then
- local foundname = collapsepath(result[1])
- resolvers.registerintrees(filename,askedformat,filetype,method,foundname)
- result = { foundname }
+ if #edt>0 then
+ local str=edt[1]
+ if type(str)~="string" then
+ elseif str=="" then
+ remove(edt,1)
else
- result = { } -- maybe false
- end
- if stamp then
- if trace_locating then
- report_resolving("remembering file '%s'",filename)
- end
- instance.found[stamp] = result
- end
- return result
+ if nolines then
+ str=gsub(str,"%s+"," ")
+ end
+ str=gsub(str,"^%s+","")
+ if str=="" then
+ remove(edt,1)
+ else
+ edt[1]=str
+ end
+ end
+ end
+ local nedt=#edt
+ if nedt>0 then
+ local str=edt[nedt]
+ if type(str)~="string" then
+ elseif str=="" then
+ remove(edt)
+ else
+ if nolines then
+ str=gsub(str,"%s+"," ")
+ end
+ str=gsub(str,"%s+$","")
+ if str=="" then
+ remove(edt)
+ else
+ edt[nedt]=str
+ end
+ end
+ end
+ end
+ end
+ return e
+end
+xml.stripelement=stripelement
+function xml.strip(root,pattern,nolines,anywhere)
+ local collected=xmlapplylpath(root,pattern)
+ if collected then
+ for i=1,#collected do
+ stripelement(collected[i],nolines,anywhere)
+ end
+ end
+end
+local function renamespace(root,oldspace,newspace)
+ local ndt=#root.dt
+ for i=1,ndt or 0 do
+ local e=root[i]
+ if type(e)=="table" then
+ if e.ns==oldspace then
+ e.ns=newspace
+ if e.rn then
+ e.rn=newspace
+ end
+ end
+ local edt=e.dt
+ if edt then
+ renamespace(edt,oldspace,newspace)
+ end
+ end
+ end
+end
+xml.renamespace=renamespace
+function xml.remaptag(root,pattern,newtg)
+ local collected=xmlapplylpath(root,pattern)
+ if collected then
+ for c=1,#collected do
+ collected[c].tg=newtg
end
+ end
end
-
--- -- -- end of main file search routing -- -- --
-
-
-local function findfiles(filename,filetype,allresults)
- local result, status = collect_instance_files(filename,filetype or "",allresults)
- if not result or #result == 0 then
- local lowered = lower(filename)
- if filename ~= lowered then
- result, status = collect_instance_files(lowered,filetype or "",allresults)
- end
+function xml.remapnamespace(root,pattern,newns)
+ local collected=xmlapplylpath(root,pattern)
+ if collected then
+ for c=1,#collected do
+ collected[c].ns=newns
end
- return result or { }, status
+ end
end
-
-function resolvers.findfiles(filename,filetype)
- return findfiles(filename,filetype,true)
+function xml.checknamespace(root,pattern,newns)
+ local collected=xmlapplylpath(root,pattern)
+ if collected then
+ for c=1,#collected do
+ local e=collected[c]
+ if (not e.rn or e.rn=="") and e.ns=="" then
+ e.rn=newns
+ end
+ end
+ end
end
-
-function resolvers.findfile(filename,filetype)
- return findfiles(filename,filetype,false)[1] or ""
+function xml.remapname(root,pattern,newtg,newns,newrn)
+ local collected=xmlapplylpath(root,pattern)
+ if collected then
+ for c=1,#collected do
+ local e=collected[c]
+ e.tg,e.ns,e.rn=newtg,newns,newrn
+ end
+ end
end
-
-function resolvers.findpath(filename,filetype)
- return filedirname(findfiles(filename,filetype,false)[1] or "")
+function xml.cdatatotext(e)
+ local dt=e.dt
+ if #dt==1 then
+ local first=dt[1]
+ if first.tg=="@cd@" then
+ e.dt=first.dt
+ end
+ else
+ end
+end
+function xml.texttocdata(e)
+ local dt=e.dt
+ local s=xml.tostring(dt)
+ e.tg="@cd@"
+ e.special=true
+ e.ns=""
+ e.rn=""
+ e.dt={ s }
+ e.at=nil
+end
+function xml.elementtocdata(e)
+ local dt=e.dt
+ local s=xml.tostring(e)
+ e.tg="@cd@"
+ e.special=true
+ e.ns=""
+ e.rn=""
+ e.dt={ s }
+ e.at=nil
+end
+xml.builtinentities=table.tohash { "amp","quot","apos","lt","gt" }
+local entities=characters and characters.entities or nil
+local builtinentities=xml.builtinentities
+function xml.addentitiesdoctype(root,option)
+ if not entities then
+ require("char-ent")
+ entities=characters.entities
+ end
+ if entities and root and root.tg=="@rt@" and root.statistics then
+ local list={}
+ local hexify=option=="hexadecimal"
+ for k,v in table.sortedhash(root.statistics.entities.names) do
+ if not builtinentities[k] then
+ local e=entities[k]
+ if not e then
+ e=format("[%s]",k)
+ elseif hexify then
+ e=format("%05X;",utfbyte(k))
+ end
+ list[#list+1]=format(" ",k,e)
+ end
+ end
+ local dt=root.dt
+ local n=dt[1].tg=="@pi@" and 2 or 1
+ if #list>0 then
+ insert(dt,n,{ "\n" })
+ insert(dt,n,{
+ tg="@dt@",
+ dt={ format("Something [\n%s\n] ",concat(list)) },
+ ns="",
+ special=true,
+ })
+ insert(dt,n,{ "\n\n" })
+ else
+ end
+ end
+end
+xml.all=xml.each
+xml.insert=xml.insertafter
+xml.inject=xml.injectafter
+xml.after=xml.insertafter
+xml.before=xml.insertbefore
+xml.process=xml.each
+xml.obsolete=xml.obsolete or {}
+local obsolete=xml.obsolete
+xml.strip_whitespace=xml.strip obsolete.strip_whitespace=xml.strip
+xml.collect_elements=xml.collect obsolete.collect_elements=xml.collect
+xml.delete_element=xml.delete obsolete.delete_element=xml.delete
+xml.replace_element=xml.replace obsolete.replace_element=xml.replacet
+xml.each_element=xml.each obsolete.each_element=xml.each
+xml.process_elements=xml.process obsolete.process_elements=xml.process
+xml.insert_element_after=xml.insertafter obsolete.insert_element_after=xml.insertafter
+xml.insert_element_before=xml.insertbefore obsolete.insert_element_before=xml.insertbefore
+xml.inject_element_after=xml.injectafter obsolete.inject_element_after=xml.injectafter
+xml.inject_element_before=xml.injectbefore obsolete.inject_element_before=xml.injectbefore
+xml.process_attributes=xml.processattributes obsolete.process_attributes=xml.processattributes
+xml.collect_texts=xml.collecttexts obsolete.collect_texts=xml.collecttexts
+xml.inject_element=xml.inject obsolete.inject_element=xml.inject
+xml.remap_tag=xml.remaptag obsolete.remap_tag=xml.remaptag
+xml.remap_name=xml.remapname obsolete.remap_name=xml.remapname
+xml.remap_namespace=xml.remapnamespace obsolete.remap_namespace=xml.remapnamespace
+function xml.cdata(e)
+ if e then
+ local dt=e.dt
+ if dt and #dt==1 then
+ local first=dt[1]
+ return first.tg=="@cd@" and first.dt[1] or ""
+ end
+ end
+ return ""
end
-
-local function findgivenfiles(filename,allresults)
- local bname, result = filebasename(filename), { }
- local hashes = instance.hashes
- local noffound = 0
- for k=1,#hashes do
- local hash = hashes[k]
- local files = instance.files[hash.name] or { }
- local blist = files[bname]
- if not blist then
- local rname = "remap:"..bname
- blist = files[rname]
- if blist then
- bname = files[rname]
- blist = files[bname]
- end
- end
- if blist then
- if type(blist) == 'string' then
- local found = methodhandler('concatinators',hash.type,hash.name,blist,bname) or ""
- if found ~= "" then
- noffound = noffound + 1
- result[noffound] = resolvers.resolve(found)
- if not allresults then break end
- end
+function xml.finalizers.xml.cdata(collected)
+ if collected then
+ local e=collected[1]
+ if e then
+ local dt=e.dt
+ if dt and #dt==1 then
+ local first=dt[1]
+ return first.tg=="@cd@" and first.dt[1] or ""
+ end
+ end
+ end
+ return ""
+end
+function xml.insertcomment(e,str,n)
+ table.insert(e.dt,n or 1,{
+ tg="@cm@",
+ ns="",
+ special=true,
+ at={},
+ dt={ str },
+ })
+end
+function xml.setcdata(e,str)
+ e.dt={ {
+ tg="@cd@",
+ ns="",
+ special=true,
+ at={},
+ dt={ str },
+ } }
+end
+function xml.separate(x,pattern)
+ local collected=xmlapplylpath(x,pattern)
+ if collected then
+ for c=1,#collected do
+ local e=collected[c]
+ local d=e.dt
+ if d==x then
+ report_xml("warning: xml.separate changes root")
+ x=d
+ end
+ local t,n={ "\n" },1
+ local i,nd=1,#d
+ while i<=nd do
+ while i<=nd do
+ local di=d[i]
+ if type(di)=="string" then
+ if di=="\n" or find(di,"^%s+$") then
+ i=i+1
else
- for kk=1,#blist do
- local vv = blist[kk]
- local found = methodhandler('concatinators',hash.type,hash.name,vv,bname) or ""
- if found ~= "" then
- noffound = noffound + 1
- result[noffound] = resolvers.resolve(found)
- if not allresults then break end
- end
- end
+ d[i]=strip(di)
+ break
end
+ else
+ break
+ end
+ end
+ if i>nd then
+ break
+ end
+ t[n+1]="\n"
+ t[n+2]=d[i]
+ t[n+3]="\n"
+ n=n+3
+ i=i+1
+ end
+ t[n+1]="\n"
+ setmetatable(t,getmetatable(d))
+ e.dt=t
+ end
+ end
+ return x
+end
+local helpers=xml.helpers or {}
+xml.helpers=helpers
+local function normal(e,action)
+ local edt=e.dt
+ if edt then
+ for i=1,#edt do
+ local str=edt[i]
+ if type(str)=="string" and str~="" then
+ edt[i]=action(str)
+ end
+ end
+ end
+end
+local function recurse(e,action)
+ local edt=e.dt
+ if edt then
+ for i=1,#edt do
+ local str=edt[i]
+ if type(str)~="string" then
+ recurse(str,action,recursive)
+ elseif str~="" then
+ edt[i]=action(str)
+ end
+ end
+ end
+end
+function helpers.recursetext(collected,action,recursive)
+ if recursive then
+ for i=1,#collected do
+ recurse(collected[i],action)
+ end
+ else
+ for i=1,#collected do
+ normal(collected[i],action)
+ end
+ end
+end
+
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
+package.loaded["lxml-xml"] = package.loaded["lxml-xml"] or true
+
+-- original size: 10274, stripped down to: 7538
+
+if not modules then modules={} end modules ['lxml-xml']={
+ version=1.001,
+ comment="this module is the basis for the lxml-* ones",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local concat=table.concat
+local find,lower,upper=string.find,string.lower,string.upper
+local xml=xml
+local finalizers=xml.finalizers.xml
+local xmlfilter=xml.filter
+local xmltostring=xml.tostring
+local xmlserialize=xml.serialize
+local xmlcollected=xml.collected
+local xmlnewhandlers=xml.newhandlers
+local function first(collected)
+ return collected and collected[1]
+end
+local function last(collected)
+ return collected and collected[#collected]
+end
+local function all(collected)
+ return collected
+end
+local reverse=table.reversed
+local function attribute(collected,name)
+ if collected and #collected>0 then
+ local at=collected[1].at
+ return at and at[name]
+ end
+end
+local function att(id,name)
+ local at=id.at
+ return at and at[name]
+end
+local function count(collected)
+ return collected and #collected or 0
+end
+local function position(collected,n)
+ if not collected then
+ return 0
+ end
+ local nc=#collected
+ if nc==0 then
+ return 0
+ end
+ n=tonumber(n) or 0
+ if n<0 then
+ return collected[nc+n+1]
+ elseif n>0 then
+ return collected[n]
+ else
+ return collected[1].mi or 0
+ end
+end
+local function match(collected)
+ return collected and #collected>0 and collected[1].mi or 0
+end
+local function index(collected)
+ return collected and #collected>0 and collected[1].ni or 0
+end
+local function attributes(collected,arguments)
+ if collected and #collected>0 then
+ local at=collected[1].at
+ if arguments then
+ return at[arguments]
+ elseif next(at) then
+ return at
+ end
+ end
+end
+local function chainattribute(collected,arguments)
+ if collected and #collected>0 then
+ local e=collected[1]
+ while e do
+ local at=e.at
+ if at then
+ local a=at[arguments]
+ if a then
+ return a
end
+ else
+ break
+ end
+ e=e.__p__
end
+ end
+ return ""
+end
+local function raw(collected)
+ if collected and #collected>0 then
+ local e=collected[1] or collected
+ return e and xmltostring(e) or ""
+ else
+ return ""
+ end
+end
+local xmltexthandler=xmlnewhandlers {
+ name="string",
+ initialize=function()
+ result={}
return result
+ end,
+ finalize=function()
+ return concat(result)
+ end,
+ handle=function(...)
+ result[#result+1]=concat {... }
+ end,
+ escape=false,
+}
+local function xmltotext(root)
+ local dt=root.dt
+ if not dt then
+ return ""
+ end
+ local nt=#dt
+ if nt==0 then
+ return ""
+ elseif nt==1 and type(dt[1])=="string" then
+ return dt[1]
+ else
+ return xmlserialize(root,xmltexthandler) or ""
+ end
+end
+local function text(collected)
+ if collected then
+ local e=collected[1] or collected
+ return e and xmltotext(e) or ""
+ else
+ return ""
+ end
end
-
-function resolvers.findgivenfiles(filename)
- return findgivenfiles(filename,true)
+local function texts(collected)
+ if not collected then
+ return {}
+ end
+ local nc=#collected
+ if nc==0 then
+ return {}
+ end
+ local t,n={},0
+ for c=1,nc do
+ local e=collected[c]
+ if e and e.dt then
+ n=n+1
+ t[n]=e.dt
+ end
+ end
+ return t
end
-
-function resolvers.findgivenfile(filename)
- return findgivenfiles(filename,false)[1] or ""
+local function tag(collected,n)
+ if not collected then
+ return
+ end
+ local nc=#collected
+ if nc==0 then
+ return
+ end
+ local c
+ if n==0 or not n then
+ c=collected[1]
+ elseif n>1 then
+ c=collected[n]
+ else
+ c=collected[nc-n+1]
+ end
+ return c and c.tg
end
-
-local function doit(path,blist,bname,tag,variant,result,allresults)
- local done = false
- if blist and variant then
- local resolve = resolvers.resolve -- added
- if type(blist) == 'string' then
- -- make function and share code
- if find(lower(blist),path) then
- local full = methodhandler('concatinators',variant,tag,blist,bname) or ""
- result[#result+1] = resolve(full)
- done = true
- end
+local function name(collected,n)
+ if not collected then
+ return
+ end
+ local nc=#collected
+ if nc==0 then
+ return
+ end
+ local c
+ if n==0 or not n then
+ c=collected[1]
+ elseif n>1 then
+ c=collected[n]
+ else
+ c=collected[nc-n+1]
+ end
+ if not c then
+ elseif c.ns=="" then
+ return c.tg
+ else
+ return c.ns..":"..c.tg
+ end
+end
+local function tags(collected,nonamespace)
+ if not collected then
+ return
+ end
+ local nc=#collected
+ if nc==0 then
+ return
+ end
+ local t,n={},0
+ for c=1,nc do
+ local e=collected[c]
+ local ns,tg=e.ns,e.tg
+ n=n+1
+ if nonamespace or ns=="" then
+ t[n]=tg
+ else
+ t[n]=ns..":"..tg
+ end
+ end
+ return t
+end
+local function empty(collected,spacesonly)
+ if not collected then
+ return true
+ end
+ local nc=#collected
+ if nc==0 then
+ return true
+ end
+ for c=1,nc do
+ local e=collected[c]
+ if e then
+ local edt=e.dt
+ if edt then
+ local n=#edt
+ if n==1 then
+ local edk=edt[1]
+ local typ=type(edk)
+ if typ=="table" then
+ return false
+ elseif edk~="" then
+ return false
+ elseif spacesonly and not find(edk,"%S") then
+ return false
+ end
+ elseif n>1 then
+ return false
+ end
+ end
+ end
+ end
+ return true
+end
+finalizers.first=first
+finalizers.last=last
+finalizers.all=all
+finalizers.reverse=reverse
+finalizers.elements=all
+finalizers.default=all
+finalizers.attribute=attribute
+finalizers.att=att
+finalizers.count=count
+finalizers.position=position
+finalizers.match=match
+finalizers.index=index
+finalizers.attributes=attributes
+finalizers.chainattribute=chainattribute
+finalizers.text=text
+finalizers.texts=texts
+finalizers.tag=tag
+finalizers.name=name
+finalizers.tags=tags
+finalizers.empty=empty
+function xml.first(id,pattern)
+ return first(xmlfilter(id,pattern))
+end
+function xml.last(id,pattern)
+ return last(xmlfilter(id,pattern))
+end
+function xml.count(id,pattern)
+ return count(xmlfilter(id,pattern))
+end
+function xml.attribute(id,pattern,a,default)
+ return attribute(xmlfilter(id,pattern),a,default)
+end
+function xml.raw(id,pattern)
+ if pattern then
+ return raw(xmlfilter(id,pattern))
+ else
+ return raw(id)
+ end
+end
+function xml.text(id,pattern)
+ if pattern then
+ local collected=xmlfilter(id,pattern)
+ return collected and #collected>0 and xmltotext(collected[1]) or ""
+ elseif id then
+ return xmltotext(id) or ""
+ else
+ return ""
+ end
+end
+xml.content=text
+function xml.position(id,pattern,n)
+ return position(xmlfilter(id,pattern),n)
+end
+function xml.match(id,pattern)
+ return match(xmlfilter(id,pattern))
+end
+function xml.empty(id,pattern,spacesonly)
+ return empty(xmlfilter(id,pattern),spacesonly)
+end
+xml.all=xml.filter
+xml.index=xml.position
+xml.found=xml.filter
+local function totable(x)
+ local t={}
+ for e in xmlcollected(x[1] or x,"/*") do
+ t[e.tg]=xmltostring(e.dt) or ""
+ end
+ return next(t) and t or nil
+end
+xml.table=totable
+finalizers.table=totable
+local function textonly(e,t)
+ if e then
+ local edt=e.dt
+ if edt then
+ for i=1,#edt do
+ local e=edt[i]
+ if type(e)=="table" then
+ textonly(e,t)
else
- for kk=1,#blist do
- local vv = blist[kk]
- if find(lower(vv),path) then
- local full = methodhandler('concatinators',variant,tag,vv,bname) or ""
- result[#result+1] = resolve(full)
- done = true
- if not allresults then break end
- end
- end
+ t[#t+1]=e
end
+ end
end
- return done
+ end
+ return t
end
-
-
-local makewildcard = Cs(
- (P("^")^0 * P("/") * P(-1) + P(-1)) /".*"
- + (P("^")^0 * P("/") / "")^0 * (P("*")/".*" + P("-")/"%%-" + P(".")/"%%." + P("?")/"."+ P("\\")/"/" + P(1))^0
-)
-
-function resolvers.wildcardpattern(pattern)
- return lpegmatch(makewildcard,pattern) or pattern
-end
-
-local function findwildcardfiles(filename,allresults,result) -- todo: remap: and lpeg
- result = result or { }
- local base = filebasename(filename)
- local dirn = filedirname(filename)
- local path = lower(lpegmatch(makewildcard,dirn) or dirn)
- local name = lower(lpegmatch(makewildcard,base) or base)
- local files, done = instance.files, false
- if find(name,"%*") then
- local hashes = instance.hashes
- for k=1,#hashes do
- local hash = hashes[k]
- local hashname, hashtype = hash.name, hash.type
- for kk, hh in next, files[hashname] do
- if not find(kk,"^remap:") then
- if find(lower(kk),name) then
- if doit(path,hh,kk,hashname,hashtype,result,allresults) then done = true end
- if done and not allresults then break end
- end
- end
- end
+function xml.textonly(e)
+ return concat(textonly(e,{}))
+end
+function finalizers.lowerall(collected)
+ for c=1,#collected do
+ local e=collected[c]
+ if not e.special then
+ e.tg=lower(e.tg)
+ local eat=e.at
+ if eat then
+ local t={}
+ for k,v in next,eat do
+ t[lower(k)]=v
end
- else
- local hashes = instance.hashes
- for k=1,#hashes do
- local hash = hashes[k]
- local hashname, hashtype = hash.name, hash.type
- if doit(path,files[hashname][bname],bname,hashname,hashtype,result,allresults) then done = true end
- if done and not allresults then break end
+ e.at=t
+ end
+ end
+ end
+end
+function finalizers.upperall(collected)
+ for c=1,#collected do
+ local e=collected[c]
+ if not e.special then
+ e.tg=upper(e.tg)
+ local eat=e.at
+ if eat then
+ local t={}
+ for k,v in next,eat do
+ t[upper(k)]=v
end
+ e.at=t
+ end
end
- -- we can consider also searching the paths not in the database, but then
- -- we end up with a messy search (all // in all path specs)
- return result
+ end
end
-function resolvers.findwildcardfiles(filename,result)
- return findwildcardfiles(filename,true,result)
-end
-function resolvers.findwildcardfile(filename)
- return findwildcardfiles(filename,false)[1] or ""
-end
+end -- of closure
--- main user functions
+do -- create closure to overcome 200 locals limit
-function resolvers.automount()
- -- implemented later
-end
+package.loaded["trac-xml"] = package.loaded["trac-xml"] or true
-function resolvers.load(option)
- statistics.starttiming(instance)
- identify_configuration_files()
- load_configuration_files()
- if option ~= "nofiles" then
- load_databases()
- resolvers.automount()
- end
- statistics.stoptiming(instance)
- local files = instance.files
- return files and next(files) and true
-end
+-- original size: 6351, stripped down to: 4919
-function resolvers.loadtime()
- return statistics.elapsedtime(instance)
+if not modules then modules={} end modules ['trac-xml']={
+ version=1.001,
+ comment="companion to trac-log.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local formatters=string.formatters
+local reporters=logs.reporters
+local xmlserialize=xml.serialize
+local xmlcollected=xml.collected
+local xmltext=xml.text
+local xmlfirst=xml.first
+local function showhelp(specification,...)
+ local root=xml.convert(specification.helpinfo or "")
+ if not root then
+ return
+ end
+ local xs=xml.gethandlers("string")
+ xml.sethandlersfunction(xs,"short",function(e,handler) xmlserialize(e.dt,handler) end)
+ xml.sethandlersfunction(xs,"ref",function(e,handler) handler.handle("--"..e.at.name) end)
+ local wantedcategories=select("#",...)==0 and true or table.tohash {... }
+ local nofcategories=xml.count(root,"/application/flags/category")
+ local report=specification.report
+ for category in xmlcollected(root,"/application/flags/category") do
+ local categoryname=category.at.name or ""
+ if wantedcategories==true or wantedcategories[categoryname] then
+ if nofcategories>1 then
+ report("%s options:",categoryname)
+ report()
+ end
+ for subcategory in xmlcollected(category,"/subcategory") do
+ for flag in xmlcollected(subcategory,"/flag") do
+ local name=flag.at.name
+ local value=flag.at.value
+ local short=xmltext(xmlfirst(flag,"/short"))
+ if value then
+ report("--%-20s %s",formatters["%s=%s"](name,value),short)
+ else
+ report("--%-20s %s",name,short)
+ end
+ end
+ report()
+ end
+ end
+ end
+ for category in xmlcollected(root,"/application/examples/category") do
+ local title=xmltext(xmlfirst(category,"/title"))
+ if title and title~="" then
+ report()
+ report(title)
+ report()
+ end
+ for subcategory in xmlcollected(category,"/subcategory") do
+ for example in xmlcollected(subcategory,"/example") do
+ local command=xmltext(xmlfirst(example,"/command"))
+ local comment=xmltext(xmlfirst(example,"/comment"))
+ report(command)
+ end
+ report()
+ end
+ end
+ for comment in xmlcollected(root,"/application/comments/comment") do
+ local comment=xmltext(comment)
+ report()
+ report(comment)
+ report()
+ end
end
-
-local function report(str)
- if trace_locating then
- report_resolving(str) -- has already verbose
+local reporthelp=reporters.help
+local exporthelp=reporters.export
+local function xmlfound(t)
+ local helpinfo=t.helpinfo
+ if type(helpinfo)=="table" then
+ return false
+ end
+ if type(helpinfo)~="string" then
+ helpinfo="Warning: no helpinfo found."
+ t.helpinfo=helpinfo
+ return false
+ end
+ if string.find(helpinfo,".xml$") then
+ local ownscript=environment.ownscript
+ local helpdata=false
+ if ownscript then
+ local helpfile=file.join(file.pathpart(ownscript),helpinfo)
+ helpdata=io.loaddata(helpfile)
+ if helpdata=="" then
+ helpdata=false
+ end
+ end
+ if not helpdata then
+ local helpfile=resolvers.findfile(helpinfo,"tex")
+ helpdata=helpfile and io.loaddata(helpfile)
+ end
+ if helpdata and helpdata~="" then
+ helpinfo=helpdata
+ else
+ helpinfo=formatters["Warning: help file %a is not found."](helpinfo)
+ end
+ end
+ t.helpinfo=helpinfo
+ return string.find(t.helpinfo,"^<%?xml") and true or false
+end
+function reporters.help(t,...)
+ if xmlfound(t) then
+ showhelp(t,...)
+ else
+ reporthelp(t,...)
+ end
+end
+function reporters.export(t,methods,filename)
+ if not xmlfound(t) then
+ return exporthelp(t)
+ end
+ if not methods or methods=="" then
+ methods=environment.arguments["exporthelp"]
+ end
+ if not filename or filename=="" then
+ filename=environment.files[1]
+ end
+ dofile(resolvers.findfile("trac-exp.lua","tex"))
+ local exporters=logs.exporters
+ if not exporters or not methods then
+ return exporthelp(t)
+ end
+ if methods=="all" then
+ methods=table.keys(exporters)
+ elseif type(methods)=="string" then
+ methods=utilities.parsers.settings_to_array(methods)
+ else
+ return exporthelp(t)
+ end
+ if type(filename)~="string" or filename=="" then
+ filename=false
+ elseif file.pathpart(filename)=="" then
+ t.report("export file %a will not be saved on the current path (safeguard)",filename)
+ return
+ end
+ for i=1,#methods do
+ local method=methods[i]
+ local exporter=exporters[method]
+ if exporter then
+ local result=exporter(t,method)
+ if result and result~="" then
+ if filename then
+ local fullname=file.replacesuffix(filename,method)
+ t.report("saving export in %a",fullname)
+ io.savedata(fullname,result)
+ else
+ reporters.lines(t,result)
+ end
+ else
+ t.report("no output from exporter %a",method)
+ end
else
- print(str)
+ t.report("unknown exporter %a",method)
end
+ end
end
-function resolvers.dowithfilesandreport(command, files, ...) -- will move
- if files and #files > 0 then
- if trace_locating then
- report('') -- ?
- end
- if type(files) == "string" then
- files = { files }
- end
- for f=1,#files do
- local file = files[f]
- local result = command(file,...)
- if type(result) == 'string' then
- report(result)
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
+package.loaded["data-ini"] = package.loaded["data-ini"] or true
+
+-- original size: 7898, stripped down to: 5501
+
+if not modules then modules={} end modules ['data-ini']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files",
+}
+local gsub,find,gmatch,char=string.gsub,string.find,string.gmatch,string.char
+local next,type=next,type
+local filedirname,filebasename,filejoin=file.dirname,file.basename,file.join
+local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end)
+local trace_detail=false trackers.register("resolvers.details",function(v) trace_detail=v end)
+local trace_expansions=false trackers.register("resolvers.expansions",function(v) trace_expansions=v end)
+local report_initialization=logs.reporter("resolvers","initialization")
+local ostype,osname,ossetenv,osgetenv=os.type,os.name,os.setenv,os.getenv
+resolvers=resolvers or {}
+local resolvers=resolvers
+texconfig.kpse_init=false
+texconfig.shell_escape='t'
+if not (environment and environment.default_texmfcnf) and kpse and kpse.default_texmfcnf then
+ local default_texmfcnf=kpse.default_texmfcnf()
+ default_texmfcnf=gsub(default_texmfcnf,"$SELFAUTOLOC","selfautoloc:")
+ default_texmfcnf=gsub(default_texmfcnf,"$SELFAUTODIR","selfautodir:")
+ default_texmfcnf=gsub(default_texmfcnf,"$SELFAUTOPARENT","selfautoparent:")
+ default_texmfcnf=gsub(default_texmfcnf,"$HOME","home:")
+ environment.default_texmfcnf=default_texmfcnf
+end
+kpse={ original=kpse }
+setmetatable(kpse,{
+ __index=function(kp,name)
+ report_initialization("fatal error: kpse library is accessed (key: %s)",name)
+ os.exit()
+ end
+} )
+do
+ local osfontdir=osgetenv("OSFONTDIR")
+ if osfontdir and osfontdir~="" then
+ elseif osname=="windows" then
+ ossetenv("OSFONTDIR","c:/windows/fonts//")
+ elseif osname=="macosx" then
+ ossetenv("OSFONTDIR","$HOME/Library/Fonts//;/Library/Fonts//;/System/Library/Fonts//")
+ end
+end
+do
+ local homedir=osgetenv(ostype=="windows" and 'USERPROFILE' or 'HOME') or ''
+ if not homedir or homedir=="" then
+ homedir=char(127)
+ end
+ homedir=file.collapsepath(homedir)
+ ossetenv("HOME",homedir)
+ ossetenv("USERPROFILE",homedir)
+ environment.homedir=homedir
+end
+do
+ local args=environment.originalarguments or arg
+ if not environment.ownmain then
+ environment.ownmain=status and string.match(string.lower(status.banner),"this is ([%a]+)") or "luatex"
+ end
+ local ownbin=environment.ownbin or args[-2] or arg[-2] or args[-1] or arg[-1] or arg[0] or "luatex"
+ local ownpath=environment.ownpath or os.selfdir
+ ownbin=file.collapsepath(ownbin)
+ ownpath=file.collapsepath(ownpath)
+ if not ownpath or ownpath=="" or ownpath=="unset" then
+ ownpath=args[-1] or arg[-1]
+ ownpath=ownpath and filedirname(gsub(ownpath,"\\","/"))
+ if not ownpath or ownpath=="" then
+ ownpath=args[-0] or arg[-0]
+ ownpath=ownpath and filedirname(gsub(ownpath,"\\","/"))
+ end
+ local binary=ownbin
+ if not ownpath or ownpath=="" then
+ ownpath=ownpath and filedirname(binary)
+ end
+ if not ownpath or ownpath=="" then
+ if os.binsuffix~="" then
+ binary=file.replacesuffix(binary,os.binsuffix)
+ end
+ local path=osgetenv("PATH")
+ if path then
+ for p in gmatch(path,"[^"..io.pathseparator.."]+") do
+ local b=filejoin(p,binary)
+ if lfs.isfile(b) then
+ local olddir=lfs.currentdir()
+ if lfs.chdir(p) then
+ local pp=lfs.currentdir()
+ if trace_locating and p~=pp then
+ report_initialization("following symlink %a to %a",p,pp)
+ end
+ ownpath=pp
+ lfs.chdir(olddir)
else
- for i=1,#result do
- report(result[i]) -- could be unpack
- end
+ if trace_locating then
+ report_initialization("unable to check path %a",p)
+ end
+ ownpath=p
end
+ break
+ end
end
+ end
+ end
+ if not ownpath or ownpath=="" then
+ ownpath="."
+ report_initialization("forcing fallback to ownpath %a",ownpath)
+ elseif trace_locating then
+ report_initialization("using ownpath %a",ownpath)
end
+ end
+ environment.ownbin=ownbin
+ environment.ownpath=ownpath
+end
+resolvers.ownpath=environment.ownpath
+function resolvers.getownpath()
+ return environment.ownpath
+end
+do
+ local ownpath=environment.ownpath or dir.current()
+ if ownpath then
+ ossetenv('SELFAUTOLOC',file.collapsepath(ownpath))
+ ossetenv('SELFAUTODIR',file.collapsepath(ownpath.."/.."))
+ ossetenv('SELFAUTOPARENT',file.collapsepath(ownpath.."/../.."))
+ else
+ report_initialization("error: unable to locate ownpath")
+ os.exit()
+ end
+end
+local texos=environment.texos or osgetenv("TEXOS")
+local texmfos=environment.texmfos or osgetenv('SELFAUTODIR')
+if not texos or texos=="" then
+ texos=file.basename(texmfos)
+end
+ossetenv('TEXMFOS',texmfos)
+ossetenv('TEXOS',texos)
+ossetenv('SELFAUTOSYSTEM',os.platform)
+environment.texos=texos
+environment.texmfos=texmfos
+local texroot=environment.texroot or osgetenv("TEXROOT")
+if not texroot or texroot=="" then
+ texroot=osgetenv('SELFAUTOPARENT')
+ ossetenv('TEXROOT',texroot)
+end
+environment.texroot=file.collapsepath(texroot)
+if profiler then
+ directives.register("system.profile",function()
+ profiler.start("luatex-profile.log")
+ end)
+end
+if not resolvers.resolve then
+ function resolvers.resolve (s) return s end
+ function resolvers.unresolve(s) return s end
+ function resolvers.repath (s) return s end
end
--- obsolete
--- resolvers.varvalue = resolvers.variable -- output the value of variable $STRING.
--- resolvers.expandvar = resolvers.expansion -- output variable expansion of STRING.
+end -- of closure
-function resolvers.showpath(str) -- output search path for file type NAME
- return joinpath(resolvers.expandedpathlist(resolvers.formatofvariable(str)))
-end
+do -- create closure to overcome 200 locals limit
-function resolvers.registerfile(files, name, path)
- if files[name] then
- if type(files[name]) == 'string' then
- files[name] = { files[name], path }
- else
- files[name] = path
- end
- else
- files[name] = path
+package.loaded["data-exp"] = package.loaded["data-exp"] or true
+
+-- original size: 14643, stripped down to: 9517
+
+if not modules then modules={} end modules ['data-exp']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files",
+}
+local format,find,gmatch,lower,char,sub=string.format,string.find,string.gmatch,string.lower,string.char,string.sub
+local concat,sort=table.concat,table.sort
+local lpegmatch,lpegpatterns=lpeg.match,lpeg.patterns
+local Ct,Cs,Cc,P,C,S=lpeg.Ct,lpeg.Cs,lpeg.Cc,lpeg.P,lpeg.C,lpeg.S
+local type,next=type,next
+local ostype=os.type
+local collapsepath=file.collapsepath
+local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end)
+local trace_expansions=false trackers.register("resolvers.expansions",function(v) trace_expansions=v end)
+local report_expansions=logs.reporter("resolvers","expansions")
+local resolvers=resolvers
+local function f_first(a,b)
+ local t,n={},0
+ for s in gmatch(b,"[^,]+") do
+ n=n+1;t[n]=a..s
+ end
+ return concat(t,",")
+end
+local function f_second(a,b)
+ local t,n={},0
+ for s in gmatch(a,"[^,]+") do
+ n=n+1;t[n]=s..b
+ end
+ return concat(t,",")
+end
+local function f_both(a,b)
+ local t,n={},0
+ for sb in gmatch(b,"[^,]+") do
+ for sa in gmatch(a,"[^,]+") do
+ n=n+1;t[n]=sa..sb
+ end
+ end
+ return concat(t,",")
+end
+local left=P("{")
+local right=P("}")
+local var=P((1-S("{}" ))^0)
+local set=P((1-S("{},"))^0)
+local other=P(1)
+local l_first=Cs((Cc("{")*(C(set)*left*C(var)*right/f_first)*Cc("}")+other )^0 )
+local l_second=Cs((Cc("{")*(left*C(var)*right*C(set)/f_second)*Cc("}")+other )^0 )
+local l_both=Cs((Cc("{")*(left*C(var)*right*left*C(var)*right/f_both)*Cc("}")+other )^0 )
+local l_rest=Cs((left*var*(left/"")*var*(right/"")*var*right+other )^0 )
+local stripper_1=lpeg.stripper ("{}@")
+local replacer_1=lpeg.replacer { { ",}",",@}" },{ "{,","{@," },}
+local function splitpathexpr(str,newlist,validate)
+ if trace_expansions then
+ report_expansions("expanding variable %a",str)
+ end
+ local t,ok,done=newlist or {},false,false
+ local n=#t
+ str=lpegmatch(replacer_1,str)
+ repeat
+ local old=str
+ repeat
+ local old=str
+ str=lpegmatch(l_first,str)
+ until old==str
+ repeat
+ local old=str
+ str=lpegmatch(l_second,str)
+ until old==str
+ repeat
+ local old=str
+ str=lpegmatch(l_both,str)
+ until old==str
+ repeat
+ local old=str
+ str=lpegmatch(l_rest,str)
+ until old==str
+ until old==str
+ str=lpegmatch(stripper_1,str)
+ if validate then
+ for s in gmatch(str,"[^,]+") do
+ s=validate(s)
+ if s then
+ n=n+1
+ t[n]=s
+ end
+ end
+ else
+ for s in gmatch(str,"[^,]+") do
+ n=n+1
+ t[n]=s
+ end
+ end
+ if trace_expansions then
+ for k=1,#t do
+ report_expansions("% 4i: %s",k,t[k])
end
+ end
+ return t
end
-
-function resolvers.dowithpath(name,func)
- local pathlist = resolvers.expandedpathlist(name)
- for i=1,#pathlist do
- func("^"..resolvers.cleanpath(pathlist[i]))
+local function validate(s)
+ s=collapsepath(s)
+ return s~="" and not find(s,"^!*unset/*$") and s
+end
+resolvers.validatedpath=validate
+function resolvers.expandedpathfromlist(pathlist)
+ local newlist={}
+ for k=1,#pathlist do
+ splitpathexpr(pathlist[k],newlist,validate)
+ end
+ return newlist
+end
+local cleanup=lpeg.replacer {
+ { "!","" },
+ { "\\","/" },
+}
+function resolvers.cleanpath(str)
+ local doslashes=(P("\\")/"/"+1)^0
+ local donegation=(P("!")/"" )^0
+ local homedir=lpegmatch(Cs(donegation*doslashes),environment.homedir or "")
+ if homedir=="~" or homedir=="" or not lfs.isdir(homedir) then
+ if trace_expansions then
+ report_expansions("no home dir set, ignoring dependent paths")
+ end
+ function resolvers.cleanpath(str)
+ if not str or find(str,"~") then
+ return ""
+ else
+ return lpegmatch(cleanup,str)
+ end
+ end
+ else
+ local dohome=((P("~")+P("$HOME"))/homedir)^0
+ local cleanup=Cs(donegation*dohome*doslashes)
+ function resolvers.cleanpath(str)
+ return str and lpegmatch(cleanup,str) or ""
+ end
+ end
+ return resolvers.cleanpath(str)
+end
+local expandhome=P("~")/"$HOME"
+local dodouble=P('"')/""*(expandhome+(1-P('"')))^0*P('"')/""
+local dosingle=P("'")/""*(expandhome+(1-P("'")))^0*P("'")/""
+local dostring=(expandhome+1 )^0
+local stripper=Cs(
+ lpegpatterns.unspacer*(dosingle+dodouble+dostring)*lpegpatterns.unspacer
+)
+function resolvers.checkedvariable(str)
+ return type(str)=="string" and lpegmatch(stripper,str) or str
+end
+local cache={}
+local splitter=lpeg.tsplitat(";")
+local backslashswapper=lpeg.replacer("\\","/")
+local function splitconfigurationpath(str)
+ if str then
+ local found=cache[str]
+ if not found then
+ if str=="" then
+ found={}
+ else
+ local split=lpegmatch(splitter,lpegmatch(backslashswapper,str))
+ found={}
+ local noffound=0
+ for i=1,#split do
+ local s=split[i]
+ if not find(s,"^{*unset}*") then
+ noffound=noffound+1
+ found[noffound]=s
+ end
+ end
+ if trace_expansions then
+ report_expansions("splitting path specification %a",str)
+ for k=1,noffound do
+ report_expansions("% 4i: %s",k,found[k])
+ end
+ end
+ cache[str]=found
+ end
end
+ return found
+ end
end
-
-function resolvers.dowithvariable(name,func)
- func(expandedvariable(name))
+resolvers.splitconfigurationpath=splitconfigurationpath
+function resolvers.splitpath(str)
+ if type(str)=='table' then
+ return str
+ else
+ return splitconfigurationpath(str)
+ end
end
-
-function resolvers.locateformat(name)
- local barename = file.removesuffix(name) -- gsub(name,"%.%a+$","")
- local fmtname = caches.getfirstreadablefile(barename..".fmt","formats") or ""
- if fmtname == "" then
- fmtname = resolvers.findfile(barename..".fmt")
- fmtname = resolvers.cleanpath(fmtname)
- end
- if fmtname ~= "" then
- local barename = file.removesuffix(fmtname)
- local luaname, lucname, luiname = barename .. ".lua", barename .. ".luc", barename .. ".lui"
- if lfs.isfile(luiname) then
- return barename, luiname
- elseif lfs.isfile(lucname) then
- return barename, lucname
- elseif lfs.isfile(luaname) then
- return barename, luaname
+function resolvers.joinpath(str)
+ if type(str)=='table' then
+ return file.joinpath(str)
+ else
+ return str
+ end
+end
+local attributes,directory=lfs.attributes,lfs.dir
+local weird=P(".")^1+lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+local timer={}
+local scanned={}
+local nofscans=0
+local scancache={}
+local function scan(files,spec,path,n,m,r)
+ local full=(path=="" and spec) or (spec..path..'/')
+ local dirs={}
+ local nofdirs=0
+ for name in directory(full) do
+ if not lpegmatch(weird,name) then
+ local mode=attributes(full..name,'mode')
+ if mode=='file' then
+ n=n+1
+ local f=files[name]
+ if f then
+ if type(f)=='string' then
+ files[name]={ f,path }
+ else
+ f[#f+1]=path
+ end
+ else
+ files[name]=path
+ local lower=lower(name)
+ if name~=lower then
+ files["remap:"..lower]=name
+ r=r+1
+ end
+ end
+ elseif mode=='directory' then
+ m=m+1
+ nofdirs=nofdirs+1
+ if path~="" then
+ dirs[nofdirs]=path..'/'..name
+ else
+ dirs[nofdirs]=name
end
+ end
end
- return nil, nil
-end
-
-function resolvers.booleanvariable(str,default)
- local b = resolvers.expansion(str)
- if b == "" then
- return default
- else
- b = toboolean(b)
- return (b == nil and default) or b
+ end
+ if nofdirs>0 then
+ sort(dirs)
+ for i=1,nofdirs do
+ files,n,m,r=scan(files,spec,dirs[i],n,m,r)
end
+ end
+ scancache[sub(full,1,-2)]=files
+ return files,n,m,r
end
-
-function resolvers.dowithfilesintree(pattern,handle,before,after) -- will move, can be a nice iterator instead
- local instance = resolvers.instance
- local hashes = instance.hashes
- for i=1,#hashes do
- local hash = hashes[i]
- local blobtype = hash.type
- local blobpath = hash.name
- if blobpath then
- if before then
- before(blobtype,blobpath,pattern)
- end
- local files = instance.files[blobpath]
- local total, checked, done = 0, 0, 0
- if files then
- for k,v in next, files do
- total = total + 1
- if find(k,"^remap:") then
- k = files[k]
- v = k -- files[k] -- chained
- end
- if find(k,pattern) then
- if type(v) == "string" then
- checked = checked + 1
- if handle(blobtype,blobpath,v,k) then
- done = done + 1
- end
- else
- checked = checked + #v
- for i=1,#v do
- if handle(blobtype,blobpath,v[i],k) then
- done = done + 1
- end
- end
- end
- end
- end
- end
- if after then
- after(blobtype,blobpath,pattern,total,checked,done)
- end
+local fullcache={}
+function resolvers.scanfiles(path,branch,usecache)
+ statistics.starttiming(timer)
+ local realpath=resolvers.resolve(path)
+ if usecache then
+ local files=fullcache[realpath]
+ if files then
+ if trace_locating then
+ report_expansions("using caches scan of path %a, branch %a",path,branch or path)
+ end
+ return files
+ end
+ end
+ if trace_locating then
+ report_expansions("scanning path %a, branch %a",path,branch or path)
+ end
+ local files,n,m,r=scan({},realpath..'/',"",0,0,0)
+ files.__path__=path
+ files.__files__=n
+ files.__directories__=m
+ files.__remappings__=r
+ if trace_locating then
+ report_expansions("%s files found on %s directories with %s uppercase remappings",n,m,r)
+ end
+ if usecache then
+ scanned[#scanned+1]=realpath
+ fullcache[realpath]=files
+ end
+ nofscans=nofscans+1
+ statistics.stoptiming(timer)
+ return files
+end
+local function simplescan(files,spec,path)
+ local full=(path=="" and spec) or (spec..path..'/')
+ local dirs={}
+ local nofdirs=0
+ for name in directory(full) do
+ if not lpegmatch(weird,name) then
+ local mode=attributes(full..name,'mode')
+ if mode=='file' then
+ if not files[name] then
+ files[name]=path
+ end
+ elseif mode=='directory' then
+ nofdirs=nofdirs+1
+ if path~="" then
+ dirs[nofdirs]=path..'/'..name
+ else
+ dirs[nofdirs]=name
end
+ end
end
+ end
+ if nofdirs>0 then
+ sort(dirs)
+ for i=1,nofdirs do
+ files=simplescan(files,spec,dirs[i])
+ end
+ end
+ return files
+end
+local simplecache={}
+local nofsharedscans=0
+function resolvers.simplescanfiles(path,branch,usecache)
+ statistics.starttiming(timer)
+ local realpath=resolvers.resolve(path)
+ if usecache then
+ local files=simplecache[realpath]
+ if not files then
+ files=scancache[realpath]
+ if files then
+ nofsharedscans=nofsharedscans+1
+ end
+ end
+ if files then
+ if trace_locating then
+ report_expansions("using caches scan of path %a, branch %a",path,branch or path)
+ end
+ return files
+ end
+ end
+ if trace_locating then
+ report_expansions("scanning path %a, branch %a",path,branch or path)
+ end
+ local files=simplescan({},realpath..'/',"")
+ if trace_locating then
+ report_expansions("%s files found",table.count(files))
+ end
+ if usecache then
+ scanned[#scanned+1]=realpath
+ simplecache[realpath]=files
+ end
+ nofscans=nofscans+1
+ statistics.stoptiming(timer)
+ return files
+end
+function resolvers.scandata()
+ table.sort(scanned)
+ return {
+ n=nofscans,
+ shared=nofsharedscans,
+ time=statistics.elapsedtime(timer),
+ paths=scanned,
+ }
end
-
-resolvers.obsolete = resolvers.obsolete or { }
-local obsolete = resolvers.obsolete
-
-resolvers.find_file = resolvers.findfile obsolete.find_file = resolvers.findfile
-resolvers.find_files = resolvers.findfiles obsolete.find_files = resolvers.findfiles
end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['data-pre'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- It could be interesting to hook the resolver in the file
--- opener so that unresolved prefixes travel around and we
--- get more abstraction.
-
--- As we use this beforehand we will move this up in the chain
--- of loading.
-
-
-local resolvers = resolvers
-local prefixes = utilities.storage.allocate()
-resolvers.prefixes = prefixes
+package.loaded["data-env"] = package.loaded["data-env"] or true
-local gsub = string.gsub
-local cleanpath, findgivenfile, expansion = resolvers.cleanpath, resolvers.findgivenfile, resolvers.expansion
-local getenv = resolvers.getenv -- we can probably also use resolvers.expansion
-local P, Cs, lpegmatch = lpeg.P, lpeg.Cs, lpeg.match
+-- original size: 8762, stripped down to: 6484
--- getenv = function(...) return resolvers.getenv(...) end -- needs checking (definitions changes later on)
-
-prefixes.environment = function(str)
- return cleanpath(expansion(str))
+if not modules then modules={} end modules ['data-env']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files",
+}
+local lower,gsub=string.lower,string.gsub
+local resolvers=resolvers
+local allocate=utilities.storage.allocate
+local setmetatableindex=table.setmetatableindex
+local suffixonly=file.suffixonly
+local formats=allocate()
+local suffixes=allocate()
+local dangerous=allocate()
+local suffixmap=allocate()
+resolvers.formats=formats
+resolvers.suffixes=suffixes
+resolvers.dangerous=dangerous
+resolvers.suffixmap=suffixmap
+local luasuffixes=utilities.lua.suffixes
+local relations=allocate {
+ core={
+ ofm={
+ names={ "ofm","omega font metric","omega font metrics" },
+ variable='OFMFONTS',
+ suffixes={ 'ofm','tfm' },
+ },
+ ovf={
+ names={ "ovf","omega virtual font","omega virtual fonts" },
+ variable='OVFFONTS',
+ suffixes={ 'ovf','vf' },
+ },
+ tfm={
+ names={ "tfm","tex font metric","tex font metrics" },
+ variable='TFMFONTS',
+ suffixes={ 'tfm' },
+ },
+ vf={
+ names={ "vf","virtual font","virtual fonts" },
+ variable='VFFONTS',
+ suffixes={ 'vf' },
+ },
+ otf={
+ names={ "otf","opentype","opentype font","opentype fonts"},
+ variable='OPENTYPEFONTS',
+ suffixes={ 'otf' },
+ },
+ ttf={
+ names={ "ttf","truetype","truetype font","truetype fonts","truetype collection","truetype collections","truetype dictionary","truetype dictionaries" },
+ variable='TTFONTS',
+ suffixes={ 'ttf','ttc','dfont' },
+ },
+ afm={
+ names={ "afm","adobe font metric","adobe font metrics" },
+ variable="AFMFONTS",
+ suffixes={ "afm" },
+ },
+ pfb={
+ names={ "pfb","type1","type 1","type1 font","type 1 font","type1 fonts","type 1 fonts" },
+ variable='T1FONTS',
+ suffixes={ 'pfb','pfa' },
+ },
+ fea={
+ names={ "fea","font feature","font features","font feature file","font feature files" },
+ variable='FONTFEATURES',
+ suffixes={ 'fea' },
+ },
+ cid={
+ names={ "cid","cid map","cid maps","cid file","cid files" },
+ variable='FONTCIDMAPS',
+ suffixes={ 'cid','cidmap' },
+ },
+ fmt={
+ names={ "fmt","format","tex format" },
+ variable='TEXFORMATS',
+ suffixes={ 'fmt' },
+ },
+ mem={
+ names={ 'mem',"metapost format" },
+ variable='MPMEMS',
+ suffixes={ 'mem' },
+ },
+ mp={
+ names={ "mp" },
+ variable='MPINPUTS',
+ suffixes={ 'mp','mpvi','mpiv','mpii' },
+ },
+ tex={
+ names={ "tex" },
+ variable='TEXINPUTS',
+ suffixes={ 'tex',"mkvi","mkiv","mkii" },
+ },
+ icc={
+ names={ "icc","icc profile","icc profiles" },
+ variable='ICCPROFILES',
+ suffixes={ 'icc' },
+ },
+ texmfscripts={
+ names={ "texmfscript","texmfscripts","script","scripts" },
+ variable='TEXMFSCRIPTS',
+ suffixes={ 'rb','pl','py' },
+ },
+ lua={
+ names={ "lua" },
+ variable='LUAINPUTS',
+ suffixes={ luasuffixes.lua,luasuffixes.luc,luasuffixes.tma,luasuffixes.tmc },
+ },
+ lib={
+ names={ "lib" },
+ variable='CLUAINPUTS',
+ suffixes=os.libsuffix and { os.libsuffix } or { 'dll','so' },
+ },
+ bib={
+ names={ 'bib' },
+ suffixes={ 'bib' },
+ },
+ bst={
+ names={ 'bst' },
+ suffixes={ 'bst' },
+ },
+ fontconfig={
+ names={ 'fontconfig','fontconfig file','fontconfig files' },
+ variable='FONTCONFIG_PATH',
+ },
+ },
+ obsolete={
+ enc={
+ names={ "enc","enc files","enc file","encoding files","encoding file" },
+ variable='ENCFONTS',
+ suffixes={ 'enc' },
+ },
+ map={
+ names={ "map","map files","map file" },
+ variable='TEXFONTMAPS',
+ suffixes={ 'map' },
+ },
+ lig={
+ names={ "lig files","lig file","ligature file","ligature files" },
+ variable='LIGFONTS',
+ suffixes={ 'lig' },
+ },
+ opl={
+ names={ "opl" },
+ variable='OPLFONTS',
+ suffixes={ 'opl' },
+ },
+ ovp={
+ names={ "ovp" },
+ variable='OVPFONTS',
+ suffixes={ 'ovp' },
+ },
+ },
+ kpse={
+ base={
+ names={ 'base',"metafont format" },
+ variable='MFBASES',
+ suffixes={ 'base','bas' },
+ },
+ cmap={
+ names={ 'cmap','cmap files','cmap file' },
+ variable='CMAPFONTS',
+ suffixes={ 'cmap' },
+ },
+ cnf={
+ names={ 'cnf' },
+ suffixes={ 'cnf' },
+ },
+ web={
+ names={ 'web' },
+ suffixes={ 'web','ch' }
+ },
+ cweb={
+ names={ 'cweb' },
+ suffixes={ 'w','web','ch' },
+ },
+ gf={
+ names={ 'gf' },
+ suffixes={ 'gf' },
+ },
+ mf={
+ names={ 'mf' },
+ variable='MFINPUTS',
+ suffixes={ 'mf' },
+ },
+ mft={
+ names={ 'mft' },
+ suffixes={ 'mft' },
+ },
+ pk={
+ names={ 'pk' },
+ suffixes={ 'pk' },
+ },
+ },
+}
+resolvers.relations=relations
+function resolvers.updaterelations()
+ for category,categories in next,relations do
+ for name,relation in next,categories do
+ local rn=relation.names
+ local rv=relation.variable
+ local rs=relation.suffixes
+ if rn and rv then
+ for i=1,#rn do
+ local rni=lower(gsub(rn[i]," ",""))
+ formats[rni]=rv
+ if rs then
+ suffixes[rni]=rs
+ for i=1,#rs do
+ local rsi=rs[i]
+ suffixmap[rsi]=rni
+ end
+ end
+ end
+ end
+ if rs then
+ end
+ end
+ end
+end
+resolvers.updaterelations()
+local function simplified(t,k)
+ return k and rawget(t,lower(gsub(k," ",""))) or nil
end
-
-prefixes.relative = function(str,n) -- lfs.isfile
- if io.exists(str) then
- -- nothing
- elseif io.exists("./" .. str) then
- str = "./" .. str
- else
- local p = "../"
- for i=1,n or 2 do
- if io.exists(p .. str) then
- str = p .. str
- break
- else
- p = p .. "../"
- end
- end
- end
- return cleanpath(str)
+setmetatableindex(formats,simplified)
+setmetatableindex(suffixes,simplified)
+setmetatableindex(suffixmap,simplified)
+function resolvers.suffixofformat(str)
+ local s=suffixes[str]
+ return s and s[1] or ""
end
-
-prefixes.auto = function(str)
- local fullname = prefixes.relative(str)
- if not lfs.isfile(fullname) then
- fullname = prefixes.locate(str)
- end
- return fullname
+function resolvers.suffixofformat(str)
+ return suffixes[str] or {}
end
-
-prefixes.locate = function(str)
- local fullname = findgivenfile(str) or ""
- return cleanpath((fullname ~= "" and fullname) or str)
+for name,format in next,formats do
+ dangerous[name]=true
end
-
-prefixes.filename = function(str)
- local fullname = findgivenfile(str) or ""
- return cleanpath(file.basename((fullname ~= "" and fullname) or str)) -- no cleanpath needed here
+dangerous.tex=nil
+function resolvers.formatofvariable(str)
+ return formats[str] or ''
end
-
-prefixes.pathname = function(str)
- local fullname = findgivenfile(str) or ""
- return cleanpath(file.dirname((fullname ~= "" and fullname) or str))
+function resolvers.formatofsuffix(str)
+ return suffixmap[suffixonly(str)] or 'tex'
end
-
-prefixes.selfautoloc = function(str)
- return cleanpath(file.join(getenv('SELFAUTOLOC'),str))
+function resolvers.variableofformat(str)
+ return formats[str] or ''
end
-
-prefixes.selfautoparent = function(str)
- return cleanpath(file.join(getenv('SELFAUTOPARENT'),str))
+function resolvers.variableofformatorsuffix(str)
+ local v=formats[str]
+ if v then
+ return v
+ end
+ v=suffixmap[suffixonly(str)]
+ if v then
+ return formats[v]
+ end
+ return ''
end
-prefixes.selfautodir = function(str)
- return cleanpath(file.join(getenv('SELFAUTODIR'),str))
-end
-prefixes.home = function(str)
- return cleanpath(file.join(getenv('HOME'),str))
-end
+end -- of closure
-prefixes.env = prefixes.environment
-prefixes.rel = prefixes.relative
-prefixes.loc = prefixes.locate
-prefixes.kpse = prefixes.locate
-prefixes.full = prefixes.locate
-prefixes.file = prefixes.filename
-prefixes.path = prefixes.pathname
+do -- create closure to overcome 200 locals limit
-function resolvers.allprefixes(separator)
- local all = table.sortedkeys(prefixes)
- if separator then
- for i=1,#all do
- all[i] = all[i] .. ":"
+package.loaded["data-tmp"] = package.loaded["data-tmp"] or true
+
+-- original size: 14308, stripped down to: 10956
+
+if not modules then modules={} end modules ['data-tmp']={
+ version=1.100,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local format,lower,gsub,concat=string.format,string.lower,string.gsub,table.concat
+local serialize,serializetofile=table.serialize,table.tofile
+local mkdirs,isdir,isfile=dir.mkdirs,lfs.isdir,lfs.isfile
+local addsuffix,is_writable,is_readable=file.addsuffix,file.is_writable,file.is_readable
+local formatters=string.formatters
+local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end)
+local trace_cache=false trackers.register("resolvers.cache",function(v) trace_cache=v end)
+local report_caches=logs.reporter("resolvers","caches")
+local report_resolvers=logs.reporter("resolvers","caching")
+local resolvers=resolvers
+local directive_cleanup=false directives.register("system.compile.cleanup",function(v) directive_cleanup=v end)
+local directive_strip=false directives.register("system.compile.strip",function(v) directive_strip=v end)
+local compile=utilities.lua.compile
+function utilities.lua.compile(luafile,lucfile,cleanup,strip)
+ if cleanup==nil then cleanup=directive_cleanup end
+ if strip==nil then strip=directive_strip end
+ return compile(luafile,lucfile,cleanup,strip)
+end
+caches=caches or {}
+local caches=caches
+local luasuffixes=utilities.lua.suffixes
+caches.base=caches.base or "luatex-cache"
+caches.more=caches.more or "context"
+caches.direct=false
+caches.tree=false
+caches.force=true
+caches.ask=false
+caches.relocate=false
+caches.defaults={ "TMPDIR","TEMPDIR","TMP","TEMP","HOME","HOMEPATH" }
+local writable,readables,usedreadables=nil,{},{}
+local function identify()
+ local texmfcaches=resolvers.cleanpathlist("TEXMFCACHE")
+ if texmfcaches then
+ for k=1,#texmfcaches do
+ local cachepath=texmfcaches[k]
+ if cachepath~="" then
+ cachepath=resolvers.resolve(cachepath)
+ cachepath=resolvers.cleanpath(cachepath)
+ cachepath=file.collapsepath(cachepath)
+ local valid=isdir(cachepath)
+ if valid then
+ if is_readable(cachepath) then
+ readables[#readables+1]=cachepath
+ if not writable and is_writable(cachepath) then
+ writable=cachepath
+ end
+ end
+ elseif not writable and caches.force then
+ local cacheparent=file.dirname(cachepath)
+ if is_writable(cacheparent) and true then
+ if not caches.ask or io.ask(format("\nShould I create the cache path %s?",cachepath),"no",{ "yes","no" })=="yes" then
+ mkdirs(cachepath)
+ if isdir(cachepath) and is_writable(cachepath) then
+ report_caches("path %a created",cachepath)
+ writable=cachepath
+ readables[#readables+1]=cachepath
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ local texmfcaches=caches.defaults
+ if texmfcaches then
+ for k=1,#texmfcaches do
+ local cachepath=texmfcaches[k]
+ cachepath=resolvers.expansion(cachepath)
+ if cachepath~="" then
+ cachepath=resolvers.resolve(cachepath)
+ cachepath=resolvers.cleanpath(cachepath)
+ local valid=isdir(cachepath)
+ if valid and is_readable(cachepath) then
+ if not writable and is_writable(cachepath) then
+ readables[#readables+1]=cachepath
+ writable=cachepath
+ break
+ end
end
+ end
+ end
+ end
+ if not writable then
+ report_caches("fatal error: there is no valid writable cache path defined")
+ os.exit()
+ elseif #readables==0 then
+ report_caches("fatal error: there is no valid readable cache path defined")
+ os.exit()
+ end
+ writable=dir.expandname(resolvers.cleanpath(writable))
+ local base,more,tree=caches.base,caches.more,caches.tree or caches.treehash()
+ if tree then
+ caches.tree=tree
+ writable=mkdirs(writable,base,more,tree)
+ for i=1,#readables do
+ readables[i]=file.join(readables[i],base,more,tree)
+ end
+ else
+ writable=mkdirs(writable,base,more)
+ for i=1,#readables do
+ readables[i]=file.join(readables[i],base,more)
end
- return all
+ end
+ if trace_cache then
+ for i=1,#readables do
+ report_caches("using readable path %a (order %s)",readables[i],i)
+ end
+ report_caches("using writable path %a",writable)
+ end
+ identify=function()
+ return writable,readables
+ end
+ return writable,readables
end
-
-local function _resolve_(method,target)
- local action = prefixes[method]
- if action then
- return action(target)
- else
- return method .. ":" .. target
+function caches.usedpaths()
+ local writable,readables=identify()
+ if #readables>1 then
+ local result={}
+ for i=1,#readables do
+ local readable=readables[i]
+ if usedreadables[i] or readable==writable then
+ result[#result+1]=formatters["readable: %a (order %s)"](readable,i)
+ end
end
+ result[#result+1]=formatters["writable: %a"](writable)
+ return result
+ else
+ return writable
+ end
end
-
-local resolved, abstract = { }, { }
-
-function resolvers.resetresolve(str)
- resolved, abstract = { }, { }
+function caches.configfiles()
+ return concat(resolvers.instance.specification,";")
end
-
-local function resolve(str) -- use schemes, this one is then for the commandline only
- if type(str) == "table" then
- local t = { }
- for i=1,#str do
- t[i] = resolve(str[i])
- end
- return t
+function caches.hashed(tree)
+ tree=gsub(tree,"[\\/]+$","")
+ tree=lower(tree)
+ local hash=md5.hex(tree)
+ if trace_cache or trace_locating then
+ report_caches("hashing tree %a, hash %a",tree,hash)
+ end
+ return hash
+end
+function caches.treehash()
+ local tree=caches.configfiles()
+ if not tree or tree=="" then
+ return false
+ else
+ return caches.hashed(tree)
+ end
+end
+local r_cache,w_cache={},{}
+local function getreadablepaths(...)
+ local tags={... }
+ local hash=concat(tags,"/")
+ local done=r_cache[hash]
+ if not done then
+ local writable,readables=identify()
+ if #tags>0 then
+ done={}
+ for i=1,#readables do
+ done[i]=file.join(readables[i],...)
+ end
else
- local res = resolved[str]
- if not res then
- res = gsub(str,"([a-z][a-z]+):([^ \"\';,]*)",_resolve_) -- home:xx;selfautoparent:xx; etc (comma added)
- resolved[str] = res
- abstract[res] = str
- end
- return res
+ done=readables
end
+ r_cache[hash]=done
+ end
+ return done
end
-
-local function unresolve(str)
- return abstract[str] or str
+local function getwritablepath(...)
+ local tags={... }
+ local hash=concat(tags,"/")
+ local done=w_cache[hash]
+ if not done then
+ local writable,readables=identify()
+ if #tags>0 then
+ done=mkdirs(writable,...)
+ else
+ done=writable
+ end
+ w_cache[hash]=done
+ end
+ return done
end
-
-resolvers.resolve = resolve
-resolvers.unresolve = unresolve
-
-if os.uname then
-
- for k, v in next, os.uname() do
- if not prefixes[k] then
- prefixes[k] = function() return v end
- end
+caches.getreadablepaths=getreadablepaths
+caches.getwritablepath=getwritablepath
+function caches.getfirstreadablefile(filename,...)
+ local rd=getreadablepaths(...)
+ for i=1,#rd do
+ local path=rd[i]
+ local fullname=file.join(path,filename)
+ if is_readable(fullname) then
+ usedreadables[i]=true
+ return fullname,path
end
-
+ end
+ return caches.setfirstwritablefile(filename,...)
end
-
-if os.type == "unix" then
-
- local pattern
-
- local function makepattern(t,k,v)
- local colon = P(":")
- local p
- for k, v in table.sortedpairs(prefixes) do
- if p then
- p = P(k) + p
- else
- p = P(k)
- end
- end
- pattern = Cs((p * colon + colon/";" + P(1))^0)
- if t then
- t[k] = v
+function caches.setfirstwritablefile(filename,...)
+ local wr=getwritablepath(...)
+ local fullname=file.join(wr,filename)
+ return fullname,wr
+end
+function caches.define(category,subcategory)
+ return function()
+ return getwritablepath(category,subcategory)
+ end
+end
+function caches.setluanames(path,name)
+ return format("%s/%s.%s",path,name,luasuffixes.tma),format("%s/%s.%s",path,name,luasuffixes.tmc)
+end
+function caches.loaddata(readables,name)
+ if type(readables)=="string" then
+ readables={ readables }
+ end
+ for i=1,#readables do
+ local path=readables[i]
+ local tmaname,tmcname=caches.setluanames(path,name)
+ local loader=false
+ if isfile(tmcname) then
+ loader=loadfile(tmcname)
+ end
+ if not loader and isfile(tmaname) then
+ utilities.lua.compile(tmaname,tmcname)
+ if isfile(tmcname) then
+ loader=loadfile(tmcname)
+ end
+ if not loader then
+ loader=loadfile(tmaname)
+ end
+ end
+ if loader then
+ loader=loader()
+ collectgarbage("step")
+ return loader
+ end
+ end
+ return false
+end
+function caches.is_writable(filepath,filename)
+ local tmaname,tmcname=caches.setluanames(filepath,filename)
+ return is_writable(tmaname)
+end
+local saveoptions={ compact=true }
+function caches.savedata(filepath,filename,data,raw)
+ local tmaname,tmcname=caches.setluanames(filepath,filename)
+ local reduce,simplify=true,true
+ if raw then
+ reduce,simplify=false,false
+ end
+ data.cache_uuid=os.uuid()
+ if caches.direct then
+ file.savedata(tmaname,serialize(data,true,saveoptions))
+ else
+ serializetofile(tmaname,data,true,saveoptions)
+ end
+ utilities.lua.compile(tmaname,tmcname)
+end
+local content_state={}
+function caches.contentstate()
+ return content_state or {}
+end
+function caches.loadcontent(cachename,dataname)
+ local name=caches.hashed(cachename)
+ local full,path=caches.getfirstreadablefile(addsuffix(name,luasuffixes.lua),"trees")
+ local filename=file.join(path,name)
+ local blob=loadfile(addsuffix(filename,luasuffixes.luc)) or loadfile(addsuffix(filename,luasuffixes.lua))
+ if blob then
+ local data=blob()
+ if data and data.content then
+ if data.type==dataname then
+ if data.version==resolvers.cacheversion then
+ content_state[#content_state+1]=data.uuid
+ if trace_locating then
+ report_resolvers("loading %a for %a from %a",dataname,cachename,filename)
+ end
+ return data.content
+ else
+ report_resolvers("skipping %a for %a from %a (version mismatch)",dataname,cachename,filename)
end
+ else
+ report_resolvers("skipping %a for %a from %a (datatype mismatch)",dataname,cachename,filename)
+ end
+ elseif trace_locating then
+ report_resolvers("skipping %a for %a from %a (no content)",dataname,cachename,filename)
end
-
- makepattern()
-
- getmetatable(prefixes).__newindex = makepattern
-
- function resolvers.repath(str)
- return lpegmatch(pattern,str)
+ elseif trace_locating then
+ report_resolvers("skipping %a for %a from %a (invalid file)",dataname,cachename,filename)
+ end
+end
+function caches.collapsecontent(content)
+ for k,v in next,content do
+ if type(v)=="table" and #v==1 then
+ content[k]=v[1]
end
-
-else -- already the default:
-
- function resolvers.repath(str)
- return str
+ end
+end
+function caches.savecontent(cachename,dataname,content)
+ local name=caches.hashed(cachename)
+ local full,path=caches.setfirstwritablefile(addsuffix(name,luasuffixes.lua),"trees")
+ local filename=file.join(path,name)
+ local luaname=addsuffix(filename,luasuffixes.lua)
+ local lucname=addsuffix(filename,luasuffixes.luc)
+ if trace_locating then
+ report_resolvers("preparing %a for %a",dataname,cachename)
+ end
+ local data={
+ type=dataname,
+ root=cachename,
+ version=resolvers.cacheversion,
+ date=os.date("%Y-%m-%d"),
+ time=os.date("%H:%M:%S"),
+ content=content,
+ uuid=os.uuid(),
+ }
+ local ok=io.savedata(luaname,serialize(data,true))
+ if ok then
+ if trace_locating then
+ report_resolvers("category %a, cachename %a saved in %a",dataname,cachename,luaname)
end
-
+ if utilities.lua.compile(luaname,lucname) then
+ if trace_locating then
+ report_resolvers("%a compiled to %a",dataname,lucname)
+ end
+ return true
+ else
+ if trace_locating then
+ report_resolvers("compiling failed for %a, deleting file %a",dataname,lucname)
+ end
+ os.remove(lucname)
+ end
+ elseif trace_locating then
+ report_resolvers("unable to save %a in %a (access error)",dataname,luaname)
+ end
end
@@ -14237,1074 +12513,2555 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['data-inp'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local allocate = utilities.storage.allocate
-local resolvers = resolvers
-
-local methodhandler = resolvers.methodhandler
-local registermethod = resolvers.registermethod
-
-local finders = allocate { helpers = { }, notfound = function() end }
-local openers = allocate { helpers = { }, notfound = function() end }
-local loaders = allocate { helpers = { }, notfound = function() return false, nil, 0 end }
-
-registermethod("finders", finders, "uri")
-registermethod("openers", openers, "uri")
-registermethod("loaders", loaders, "uri")
-
-resolvers.finders = finders
-resolvers.openers = openers
-resolvers.loaders = loaders
+package.loaded["data-met"] = package.loaded["data-met"] or true
+-- original size: 4915, stripped down to: 3942
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['data-out'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
+if not modules then modules={} end modules ['data-met']={
+ version=1.100,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
}
-
-local allocate = utilities.storage.allocate
-local resolvers = resolvers
-
-local registermethod = resolvers.registermethod
-
-local savers = allocate { helpers = { } }
-
-resolvers.savers = savers
-
-registermethod("savers", savers, "uri")
+local find,format=string.find,string.format
+local sequenced=table.sequenced
+local addurlscheme,urlhashed=url.addscheme,url.hashed
+local trace_locating=false
+trackers.register("resolvers.locating",function(v) trace_methods=v end)
+trackers.register("resolvers.methods",function(v) trace_methods=v end)
+local report_methods=logs.reporter("resolvers","methods")
+local allocate=utilities.storage.allocate
+local resolvers=resolvers
+local registered={}
+local function splitmethod(filename)
+ if not filename then
+ return { scheme="unknown",original=filename }
+ end
+ if type(filename)=="table" then
+ return filename
+ end
+ filename=file.collapsepath(filename)
+ if not find(filename,"://") then
+ return { scheme="file",path=filename,original=filename,filename=filename }
+ end
+ local specification=url.hashed(filename)
+ if not specification.scheme or specification.scheme=="" then
+ return { scheme="file",path=filename,original=filename,filename=filename }
+ else
+ return specification
+ end
+end
+resolvers.splitmethod=splitmethod
+local function methodhandler(what,first,...)
+ local method=registered[what]
+ if method then
+ local how,namespace=method.how,method.namespace
+ if how=="uri" or how=="url" then
+ local specification=splitmethod(first)
+ local scheme=specification.scheme
+ local resolver=namespace and namespace[scheme]
+ if resolver then
+ if trace_methods then
+ report_methods("resolving, method %a, how %a, handler %a, argument %a",what,how,scheme,first)
+ end
+ return resolver(specification,...)
+ else
+ resolver=namespace.default or namespace.file
+ if resolver then
+ if trace_methods then
+ report_methods("resolving, method %a, how %a, handler %a, argument %a",what,how,"default",first)
+ end
+ return resolver(specification,...)
+ elseif trace_methods then
+ report_methods("resolving, method %a, how %a, handler %a, argument %a",what,how,"unset")
+ end
+ end
+ elseif how=="tag" then
+ local resolver=namespace and namespace[first]
+ if resolver then
+ if trace_methods then
+ report_methods("resolving, method %a, how %a, tag %a",what,how,first)
+ end
+ return resolver(...)
+ else
+ resolver=namespace.default or namespace.file
+ if resolver then
+ if trace_methods then
+ report_methods("resolving, method %a, how %a, tag %a",what,how,"default")
+ end
+ return resolver(...)
+ elseif trace_methods then
+ report_methods("resolving, method %a, how %a, tag %a",what,how,"unset")
+ end
+ end
+ end
+ else
+ report_methods("resolving, invalid method %a")
+ end
+end
+resolvers.methodhandler=methodhandler
+function resolvers.registermethod(name,namespace,how)
+ registered[name]={ how=how or "tag",namespace=namespace }
+ namespace["byscheme"]=function(scheme,filename,...)
+ if scheme=="file" then
+ return methodhandler(name,filename,...)
+ else
+ return methodhandler(name,addurlscheme(filename,scheme),...)
+ end
+ end
+end
+local concatinators=allocate { notfound=file.join }
+local locators=allocate { notfound=function() end }
+local hashers=allocate { notfound=function() end }
+local generators=allocate { notfound=function() end }
+resolvers.concatinators=concatinators
+resolvers.locators=locators
+resolvers.hashers=hashers
+resolvers.generators=generators
+local registermethod=resolvers.registermethod
+registermethod("concatinators",concatinators,"tag")
+registermethod("locators",locators,"uri")
+registermethod("hashers",hashers,"uri")
+registermethod("generators",generators,"uri")
end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['data-fil'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
-
-local report_files = logs.reporter("resolvers","files")
-
-local resolvers = resolvers
+package.loaded["data-res"] = package.loaded["data-res"] or true
-local finders, openers, loaders, savers = resolvers.finders, resolvers.openers, resolvers.loaders, resolvers.savers
-local locators, hashers, generators, concatinators = resolvers.locators, resolvers.hashers, resolvers.generators, resolvers.concatinators
+-- original size: 60821, stripped down to: 42503
-local checkgarbage = utilities.garbagecollector and utilities.garbagecollector.check
-
-function locators.file(specification)
- local name = specification.filename
- local realname = resolvers.resolve(name) -- no shortcut
- if realname and realname ~= '' and lfs.isdir(realname) then
+if not modules then modules={} end modules ['data-res']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files",
+}
+local gsub,find,lower,upper,match,gmatch=string.gsub,string.find,string.lower,string.upper,string.match,string.gmatch
+local concat,insert,sortedkeys=table.concat,table.insert,table.sortedkeys
+local next,type,rawget=next,type,rawget
+local os=os
+local P,S,R,C,Cc,Cs,Ct,Carg=lpeg.P,lpeg.S,lpeg.R,lpeg.C,lpeg.Cc,lpeg.Cs,lpeg.Ct,lpeg.Carg
+local lpegmatch,lpegpatterns=lpeg.match,lpeg.patterns
+local formatters=string.formatters
+local filedirname=file.dirname
+local filebasename=file.basename
+local suffixonly=file.suffixonly
+local filejoin=file.join
+local collapsepath=file.collapsepath
+local joinpath=file.joinpath
+local allocate=utilities.storage.allocate
+local settings_to_array=utilities.parsers.settings_to_array
+local setmetatableindex=table.setmetatableindex
+local luasuffixes=utilities.lua.suffixes
+local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end)
+local trace_detail=false trackers.register("resolvers.details",function(v) trace_detail=v end)
+local trace_expansions=false trackers.register("resolvers.expansions",function(v) trace_expansions=v end)
+local report_resolving=logs.reporter("resolvers","resolving")
+local resolvers=resolvers
+local expandedpathfromlist=resolvers.expandedpathfromlist
+local checkedvariable=resolvers.checkedvariable
+local splitconfigurationpath=resolvers.splitconfigurationpath
+local methodhandler=resolvers.methodhandler
+local initializesetter=utilities.setters.initialize
+local ostype,osname,osenv,ossetenv,osgetenv=os.type,os.name,os.env,os.setenv,os.getenv
+resolvers.cacheversion='1.0.1'
+resolvers.configbanner=''
+resolvers.homedir=environment.homedir
+resolvers.criticalvars=allocate { "SELFAUTOLOC","SELFAUTODIR","SELFAUTOPARENT","TEXMFCNF","TEXMF","TEXOS" }
+resolvers.luacnfname="texmfcnf.lua"
+resolvers.luacnfstate="unknown"
+if environment.default_texmfcnf then
+ resolvers.luacnfspec=environment.default_texmfcnf
+else
+ resolvers.luacnfspec="{selfautoloc:,selfautodir:,selfautoparent:}{,/texmf{-local,}/web2c}"
+end
+resolvers.luacnfspec='home:texmf/web2c;'..resolvers.luacnfspec
+local unset_variable="unset"
+local formats=resolvers.formats
+local suffixes=resolvers.suffixes
+local dangerous=resolvers.dangerous
+local suffixmap=resolvers.suffixmap
+resolvers.defaultsuffixes={ "tex" }
+resolvers.instance=resolvers.instance or nil
+local instance=resolvers.instance or nil
+function resolvers.setenv(key,value,raw)
+ if instance then
+ instance.environment[key]=value
+ ossetenv(key,raw and value or resolvers.resolve(value))
+ end
+end
+local function getenv(key)
+ local value=rawget(instance.environment,key)
+ if value and value~="" then
+ return value
+ else
+ local e=osgetenv(key)
+ return e~=nil and e~="" and checkedvariable(e) or ""
+ end
+end
+resolvers.getenv=getenv
+resolvers.env=getenv
+local function resolve(k)
+ return instance.expansions[k]
+end
+local dollarstripper=lpeg.stripper("$")
+local inhibitstripper=P("!")^0*Cs(P(1)^0)
+local backslashswapper=lpeg.replacer("\\","/")
+local somevariable=P("$")/""
+local somekey=C(R("az","AZ","09","__","--")^1)
+local somethingelse=P(";")*((1-S("!{}/\\"))^1*P(";")/"")+P(";")*(P(";")/"")+P(1)
+local variableexpander=Cs((somevariable*(somekey/resolve)+somethingelse)^1 )
+local cleaner=P("\\")/"/"+P(";")*S("!{}/\\")^0*P(";")^1/";"
+local variablecleaner=Cs((cleaner+P(1))^0)
+local somevariable=R("az","AZ","09","__","--")^1/resolve
+local variable=(P("$")/"")*(somevariable+(P("{")/"")*somevariable*(P("}")/""))
+local variableresolver=Cs((variable+P(1))^0)
+local function expandedvariable(var)
+ return lpegmatch(variableexpander,var) or var
+end
+function resolvers.newinstance()
+ if trace_locating then
+ report_resolving("creating instance")
+ end
+ local environment,variables,expansions,order=allocate(),allocate(),allocate(),allocate()
+ local newinstance={
+ environment=environment,
+ variables=variables,
+ expansions=expansions,
+ order=order,
+ files=allocate(),
+ setups=allocate(),
+ found=allocate(),
+ foundintrees=allocate(),
+ hashes=allocate(),
+ hashed=allocate(),
+ specification=allocate(),
+ lists=allocate(),
+ data=allocate(),
+ fakepaths=allocate(),
+ remember=true,
+ diskcache=true,
+ renewcache=false,
+ renewtree=false,
+ loaderror=false,
+ savelists=true,
+ pattern=nil,
+ force_suffixes=true,
+ }
+ setmetatableindex(variables,function(t,k)
+ local v
+ for i=1,#order do
+ v=order[i][k]
+ if v~=nil then
+ t[k]=v
+ return v
+ end
+ end
+ if v==nil then
+ v=""
+ end
+ t[k]=v
+ return v
+ end)
+ setmetatableindex(environment,function(t,k)
+ local v=osgetenv(k)
+ if v==nil then
+ v=variables[k]
+ end
+ if v~=nil then
+ v=checkedvariable(v) or ""
+ end
+ v=resolvers.repath(v)
+ t[k]=v
+ return v
+ end)
+ setmetatableindex(expansions,function(t,k)
+ local v=environment[k]
+ if type(v)=="string" then
+ v=lpegmatch(variableresolver,v)
+ v=lpegmatch(variablecleaner,v)
+ end
+ t[k]=v
+ return v
+ end)
+ return newinstance
+end
+function resolvers.setinstance(someinstance)
+ instance=someinstance
+ resolvers.instance=someinstance
+ return someinstance
+end
+function resolvers.reset()
+ return resolvers.setinstance(resolvers.newinstance())
+end
+local function reset_hashes()
+ instance.lists={}
+ instance.found={}
+end
+local slash=P("/")
+local pathexpressionpattern=Cs (
+ Cc("^")*(
+ Cc("%")*S(".-")+slash^2*P(-1)/"/.*"
++slash^2/"/[^/]*/*"+(1-slash)*P(-1)*Cc("/")+P(1)
+ )^1*Cc("$")
+)
+local cache={}
+local function makepathexpression(str)
+ if str=="." then
+ return "^%./$"
+ else
+ local c=cache[str]
+ if not c then
+ c=lpegmatch(pathexpressionpattern,str)
+ cache[str]=c
+ end
+ return c
+ end
+end
+local function reportcriticalvariables(cnfspec)
+ if trace_locating then
+ for i=1,#resolvers.criticalvars do
+ local k=resolvers.criticalvars[i]
+ local v=resolvers.getenv(k) or "unknown"
+ report_resolving("variable %a set to %a",k,v)
+ end
+ report_resolving()
+ if cnfspec then
+ report_resolving("using configuration specification %a",type(cnfspec)=="table" and concat(cnfspec,",") or cnfspec)
+ end
+ report_resolving()
+ end
+ reportcriticalvariables=function() end
+end
+local function identify_configuration_files()
+ local specification=instance.specification
+ if #specification==0 then
+ local cnfspec=getenv("TEXMFCNF")
+ if cnfspec=="" then
+ cnfspec=resolvers.luacnfspec
+ resolvers.luacnfstate="default"
+ else
+ resolvers.luacnfstate="environment"
+ end
+ reportcriticalvariables(cnfspec)
+ local cnfpaths=expandedpathfromlist(resolvers.splitpath(cnfspec))
+ local luacnfname=resolvers.luacnfname
+ for i=1,#cnfpaths do
+ local filename=collapsepath(filejoin(cnfpaths[i],luacnfname))
+ local realname=resolvers.resolve(filename)
+ if lfs.isfile(realname) then
+ specification[#specification+1]=filename
+ if trace_locating then
+ report_resolving("found configuration file %a",realname)
+ end
+ elseif trace_locating then
+ report_resolving("unknown configuration file %a",realname)
+ end
+ end
+ if trace_locating then
+ report_resolving()
+ end
+ elseif trace_locating then
+ report_resolving("configuration files already identified")
+ end
+end
+local function load_configuration_files()
+ local specification=instance.specification
+ if #specification>0 then
+ local luacnfname=resolvers.luacnfname
+ for i=1,#specification do
+ local filename=specification[i]
+ local pathname=filedirname(filename)
+ local filename=filejoin(pathname,luacnfname)
+ local realname=resolvers.resolve(filename)
+ local blob=loadfile(realname)
+ if blob then
+ local setups=instance.setups
+ local data=blob()
+ local parent=data and data.parent
+ if parent then
+ local filename=filejoin(pathname,parent)
+ local realname=resolvers.resolve(filename)
+ local blob=loadfile(realname)
+ if blob then
+ local parentdata=blob()
+ if parentdata then
+ report_resolving("loading configuration file %a",filename)
+ data=table.merged(parentdata,data)
+ end
+ end
+ end
+ data=data and data.content
+ if data then
+ if trace_locating then
+ report_resolving("loading configuration file %a",filename)
+ report_resolving()
+ end
+ local variables=data.variables or {}
+ local warning=false
+ for k,v in next,data do
+ local variant=type(v)
+ if variant=="table" then
+ initializesetter(filename,k,v)
+ elseif variables[k]==nil then
+ if trace_locating and not warning then
+ report_resolving("variables like %a in configuration file %a should move to the 'variables' subtable",
+ k,resolvers.resolve(filename))
+ warning=true
+ end
+ variables[k]=v
+ end
+ end
+ setups[pathname]=variables
+ if resolvers.luacnfstate=="default" then
+ local cnfspec=variables["TEXMFCNF"]
+ if cnfspec then
+ if trace_locating then
+ report_resolving("reloading configuration due to TEXMF redefinition")
+ end
+ resolvers.setenv("TEXMFCNF",cnfspec)
+ instance.specification={}
+ identify_configuration_files()
+ load_configuration_files()
+ resolvers.luacnfstate="configuration"
+ break
+ end
+ end
+ else
+ if trace_locating then
+ report_resolving("skipping configuration file %a (no content)",filename)
+ end
+ setups[pathname]={}
+ instance.loaderror=true
+ end
+ elseif trace_locating then
+ report_resolving("skipping configuration file %a (no valid format)",filename)
+ end
+ instance.order[#instance.order+1]=instance.setups[pathname]
+ if instance.loaderror then
+ break
+ end
+ end
+ elseif trace_locating then
+ report_resolving("warning: no lua configuration files found")
+ end
+end
+local function load_file_databases()
+ instance.loaderror,instance.files=false,allocate()
+ if not instance.renewcache then
+ local hashes=instance.hashes
+ for k=1,#hashes do
+ local hash=hashes[k]
+ resolvers.hashers.byscheme(hash.type,hash.name)
+ if instance.loaderror then break end
+ end
+ end
+end
+local function locate_file_databases()
+ local texmfpaths=resolvers.expandedpathlist("TEXMF")
+ if #texmfpaths>0 then
+ for i=1,#texmfpaths do
+ local path=collapsepath(texmfpaths[i])
+ path=gsub(path,"/+$","")
+ local stripped=lpegmatch(inhibitstripper,path)
+ if stripped~="" then
+ local runtime=stripped==path
+ path=resolvers.cleanpath(path)
+ local spec=resolvers.splitmethod(stripped)
+ if runtime and (spec.noscheme or spec.scheme=="file") then
+ stripped="tree:///"..stripped
+ elseif spec.scheme=="cache" or spec.scheme=="file" then
+ stripped=spec.path
+ end
if trace_locating then
- report_files("file locator '%s' found as '%s'",name,realname)
+ if runtime then
+ report_resolving("locating list of %a (runtime) (%s)",path,stripped)
+ else
+ report_resolving("locating list of %a (cached)",path)
+ end
end
- resolvers.appendhash('file',name,true) -- cache
+ methodhandler('locators',stripped)
+ end
+ end
+ if trace_locating then
+ report_resolving()
+ end
+ elseif trace_locating then
+ report_resolving("no texmf paths are defined (using TEXMF)")
+ end
+end
+local function generate_file_databases()
+ local hashes=instance.hashes
+ for k=1,#hashes do
+ local hash=hashes[k]
+ methodhandler('generators',hash.name)
+ end
+ if trace_locating then
+ report_resolving()
+ end
+end
+local function save_file_databases()
+ for i=1,#instance.hashes do
+ local hash=instance.hashes[i]
+ local cachename=hash.name
+ if hash.cache then
+ local content=instance.files[cachename]
+ caches.collapsecontent(content)
+ if trace_locating then
+ report_resolving("saving tree %a",cachename)
+ end
+ caches.savecontent(cachename,"files",content)
elseif trace_locating then
- report_files("file locator '%s' not found",name)
+ report_resolving("not saving runtime tree %a",cachename)
end
+ end
end
-
-function hashers.file(specification)
- local name = specification.filename
- local content = caches.loadcontent(name,'files')
- resolvers.registerfilehash(name,content,content==nil)
+function resolvers.renew(hashname)
+ if hashname and hashname~="" then
+ local expanded=resolvers.expansion(hashname) or ""
+ if expanded~="" then
+ if trace_locating then
+ report_resolving("identifying tree %a from %a",expanded,hashname)
+ end
+ hashname=expanded
+ else
+ if trace_locating then
+ report_resolving("identifying tree %a",hashname)
+ end
+ end
+ local realpath=resolvers.resolve(hashname)
+ if lfs.isdir(realpath) then
+ if trace_locating then
+ report_resolving("using path %a",realpath)
+ end
+ methodhandler('generators',hashname)
+ local content=instance.files[hashname]
+ caches.collapsecontent(content)
+ if trace_locating then
+ report_resolving("saving tree %a",hashname)
+ end
+ caches.savecontent(hashname,"files",content)
+ else
+ report_resolving("invalid path %a",realpath)
+ end
+ end
end
-
-function generators.file(specification)
- local path = specification.filename
- local content = resolvers.scanfiles(path,false,true) -- scan once
- resolvers.registerfilehash(path,content,true)
+local function load_databases()
+ locate_file_databases()
+ if instance.diskcache and not instance.renewcache then
+ load_file_databases()
+ if instance.loaderror then
+ generate_file_databases()
+ save_file_databases()
+ end
+ else
+ generate_file_databases()
+ if instance.renewcache then
+ save_file_databases()
+ end
+ end
end
-
-concatinators.file = file.join
-
-function finders.file(specification,filetype)
- local filename = specification.filename
- local foundname = resolvers.findfile(filename,filetype)
- if foundname and foundname ~= "" then
- if trace_locating then
- report_files("file finder: '%s' found",filename)
- end
- return foundname
+function resolvers.appendhash(type,name,cache)
+ if not instance.hashed[name] then
+ if trace_locating then
+ report_resolving("hash %a appended",name)
+ end
+ insert(instance.hashes,{ type=type,name=name,cache=cache } )
+ instance.hashed[name]=cache
+ end
+end
+function resolvers.prependhash(type,name,cache)
+ if not instance.hashed[name] then
+ if trace_locating then
+ report_resolving("hash %a prepended",name)
+ end
+ insert(instance.hashes,1,{ type=type,name=name,cache=cache } )
+ instance.hashed[name]=cache
+ end
+end
+function resolvers.extendtexmfvariable(specification)
+ local t=resolvers.splitpath(getenv("TEXMF"))
+ insert(t,1,specification)
+ local newspec=concat(t,",")
+ if instance.environment["TEXMF"] then
+ instance.environment["TEXMF"]=newspec
+ elseif instance.variables["TEXMF"] then
+ instance.variables["TEXMF"]=newspec
+ else
+ end
+ reset_hashes()
+end
+function resolvers.splitexpansions()
+ local ie=instance.expansions
+ for k,v in next,ie do
+ local t,tn,h,p={},0,{},splitconfigurationpath(v)
+ for kk=1,#p do
+ local vv=p[kk]
+ if vv~="" and not h[vv] then
+ tn=tn+1
+ t[tn]=vv
+ h[vv]=true
+ end
+ end
+ if #t>1 then
+ ie[k]=t
else
- if trace_locating then
- report_files("file finder: %s' not found",filename)
- end
- return finders.notfound()
+ ie[k]=t[1]
end
+ end
end
-
--- The default textopener will be overloaded later on.
-
-function openers.helpers.textopener(tag,filename,f)
- return {
- reader = function() return f:read () end,
- close = function() logs.show_close(filename) return f:close() end,
- }
+function resolvers.datastate()
+ return caches.contentstate()
end
-
-function openers.file(specification,filetype)
- local filename = specification.filename
- if filename and filename ~= "" then
- local f = io.open(filename,"r")
- if f then
- if trace_locating then
- report_files("file opener, '%s' opened",filename)
- end
- return openers.helpers.textopener("file",filename,f)
+function resolvers.variable(name)
+ local name=name and lpegmatch(dollarstripper,name)
+ local result=name and instance.variables[name]
+ return result~=nil and result or ""
+end
+function resolvers.expansion(name)
+ local name=name and lpegmatch(dollarstripper,name)
+ local result=name and instance.expansions[name]
+ return result~=nil and result or ""
+end
+function resolvers.unexpandedpathlist(str)
+ local pth=resolvers.variable(str)
+ local lst=resolvers.splitpath(pth)
+ return expandedpathfromlist(lst)
+end
+function resolvers.unexpandedpath(str)
+ return joinpath(resolvers.unexpandedpathlist(str))
+end
+local done={}
+function resolvers.resetextrapath()
+ local ep=instance.extra_paths
+ if not ep then
+ ep,done={},{}
+ instance.extra_paths=ep
+ elseif #ep>0 then
+ instance.lists,done={},{}
+ end
+end
+function resolvers.registerextrapath(paths,subpaths)
+ paths=settings_to_array(paths)
+ subpaths=settings_to_array(subpaths)
+ local ep=instance.extra_paths or {}
+ local oldn=#ep
+ local newn=oldn
+ local nofpaths=#paths
+ local nofsubpaths=#subpaths
+ if nofpaths>0 then
+ if nofsubpaths>0 then
+ for i=1,nofpaths do
+ local p=paths[i]
+ for j=1,nofsubpaths do
+ local s=subpaths[j]
+ local ps=p.."/"..s
+ if not done[ps] then
+ newn=newn+1
+ ep[newn]=resolvers.cleanpath(ps)
+ done[ps]=true
+ end
+ end
+ end
+ else
+ for i=1,nofpaths do
+ local p=paths[i]
+ if not done[p] then
+ newn=newn+1
+ ep[newn]=resolvers.cleanpath(p)
+ done[p]=true
+ end
+ end
+ end
+ elseif nofsubpaths>0 then
+ for i=1,oldn do
+ for j=1,nofsubpaths do
+ local s=subpaths[j]
+ local ps=ep[i].."/"..s
+ if not done[ps] then
+ newn=newn+1
+ ep[newn]=resolvers.cleanpath(ps)
+ done[ps]=true
+ end
+ end
+ end
+ end
+ if newn>0 then
+ instance.extra_paths=ep
+ end
+ if newn>oldn then
+ instance.lists={}
+ end
+end
+local function made_list(instance,list)
+ local ep=instance.extra_paths
+ if not ep or #ep==0 then
+ return list
+ else
+ local done,new,newn={},{},0
+ for k=1,#list do
+ local v=list[k]
+ if not done[v] then
+ if find(v,"^[%.%/]$") then
+ done[v]=true
+ newn=newn+1
+ new[newn]=v
+ else
+ break
end
+ end
end
- if trace_locating then
- report_files("file opener, '%s' not found",filename)
+ for k=1,#ep do
+ local v=ep[k]
+ if not done[v] then
+ done[v]=true
+ newn=newn+1
+ new[newn]=v
+ end
+ end
+ for k=1,#list do
+ local v=list[k]
+ if not done[v] then
+ done[v]=true
+ newn=newn+1
+ new[newn]=v
+ end
end
- return openers.notfound()
+ return new
+ end
end
-
-function loaders.file(specification,filetype)
- local filename = specification.filename
- if filename and filename ~= "" then
- local f = io.open(filename,"rb")
- if f then
- logs.show_load(filename)
- if trace_locating then
- report_files("file loader, '%s' loaded",filename)
- end
- local s = f:read("*a")
- if checkgarbage then
- checkgarbage(#s)
- end
- f:close()
- if s then
- return true, s, #s
- end
- end
+function resolvers.cleanpathlist(str)
+ local t=resolvers.expandedpathlist(str)
+ if t then
+ for i=1,#t do
+ t[i]=collapsepath(resolvers.cleanpath(t[i]))
end
- if trace_locating then
- report_files("file loader, '%s' not found",filename)
+ end
+ return t
+end
+function resolvers.expandpath(str)
+ return joinpath(resolvers.expandedpathlist(str))
+end
+function resolvers.expandedpathlist(str)
+ if not str then
+ return {}
+ elseif instance.savelists then
+ str=lpegmatch(dollarstripper,str)
+ local lists=instance.lists
+ local lst=lists[str]
+ if not lst then
+ local l=made_list(instance,resolvers.splitpath(resolvers.expansion(str)))
+ lst=expandedpathfromlist(l)
+ lists[str]=lst
end
- return loaders.notfound()
+ return lst
+ else
+ local lst=resolvers.splitpath(resolvers.expansion(str))
+ return made_list(instance,expandedpathfromlist(lst))
+ end
end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['data-con'] = {
- version = 1.100,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local format, lower, gsub = string.format, string.lower, string.gsub
-
-local trace_cache = false trackers.register("resolvers.cache", function(v) trace_cache = v end)
-local trace_containers = false trackers.register("resolvers.containers", function(v) trace_containers = v end)
-local trace_storage = false trackers.register("resolvers.storage", function(v) trace_storage = v end)
-
---[[ldx--
-Once we found ourselves defining similar cache constructs
-several times, containers were introduced. Containers are used
-to collect tables in memory and reuse them when possible based
-on (unique) hashes (to be provided by the calling function).
-
-Caching to disk is disabled by default. Version numbers are
-stored in the saved table which makes it possible to change the
-table structures without bothering about the disk cache.
-
-Examples of usage can be found in the font related code.
---ldx]]--
-
-containers = containers or { }
-local containers = containers
-containers.usecache = true
-
-local report_containers = logs.reporter("resolvers","containers")
-
-local function report(container,tag,name)
- if trace_cache or trace_containers then
- report_containers("container: %s, tag: %s, name: %s",container.subcategory,tag,name or 'invalid')
+function resolvers.expandedpathlistfromvariable(str)
+ str=lpegmatch(dollarstripper,str)
+ local tmp=resolvers.variableofformatorsuffix(str)
+ return resolvers.expandedpathlist(tmp~="" and tmp or str)
+end
+function resolvers.expandpathfromvariable(str)
+ return joinpath(resolvers.expandedpathlistfromvariable(str))
+end
+function resolvers.expandbraces(str)
+ local ori=str
+ local pth=expandedpathfromlist(resolvers.splitpath(ori))
+ return joinpath(pth)
+end
+function resolvers.registerfilehash(name,content,someerror)
+ if content then
+ instance.files[name]=content
+ else
+ instance.files[name]={}
+ if somerror==true then
+ instance.loaderror=someerror
end
+ end
end
-
-local allocated = { }
-
-local mt = {
- __index = function(t,k)
- if k == "writable" then
- local writable = caches.getwritablepath(t.category,t.subcategory) or { "." }
- t.writable = writable
- return writable
- elseif k == "readables" then
- local readables = caches.getreadablepaths(t.category,t.subcategory) or { "." }
- t.readables = readables
- return readables
- end
- end,
- __storage__ = true
-}
-
-function containers.define(category, subcategory, version, enabled)
- if category and subcategory then
- local c = allocated[category]
- if not c then
- c = { }
- allocated[category] = c
- end
- local s = c[subcategory]
- if not s then
- s = {
- category = category,
- subcategory = subcategory,
- storage = { },
- enabled = enabled,
- version = version or math.pi, -- after all, this is TeX
- trace = false,
- -- writable = caches.getwritablepath and caches.getwritablepath (category,subcategory) or { "." },
- -- readables = caches.getreadablepaths and caches.getreadablepaths(category,subcategory) or { "." },
- }
- setmetatable(s,mt)
- c[subcategory] = s
+local function isreadable(name)
+ local readable=lfs.isfile(name)
+ if trace_detail then
+ if readable then
+ report_resolving("file %a is readable",name)
+ else
+ report_resolving("file %a is not readable",name)
+ end
+ end
+ return readable
+end
+local function collect_files(names)
+ local filelist,noffiles={},0
+ for k=1,#names do
+ local fname=names[k]
+ if trace_detail then
+ report_resolving("checking name %a",fname)
+ end
+ local bname=filebasename(fname)
+ local dname=filedirname(fname)
+ if dname=="" or find(dname,"^%.") then
+ dname=false
+ else
+ dname=gsub(dname,"%*",".*")
+ dname="/"..dname.."$"
+ end
+ local hashes=instance.hashes
+ for h=1,#hashes do
+ local hash=hashes[h]
+ local blobpath=hash.name
+ local files=blobpath and instance.files[blobpath]
+ if files then
+ if trace_detail then
+ report_resolving("deep checking %a, base %a, pattern %a",blobpath,bname,dname)
+ end
+ local blobfile=files[bname]
+ if not blobfile then
+ local rname="remap:"..bname
+ blobfile=files[rname]
+ if blobfile then
+ bname=files[rname]
+ blobfile=files[bname]
+ end
+ end
+ if blobfile then
+ local blobroot=files.__path__ or blobpath
+ if type(blobfile)=='string' then
+ if not dname or find(blobfile,dname) then
+ local variant=hash.type
+ local search=filejoin(blobroot,blobfile,bname)
+ local result=methodhandler('concatinators',hash.type,blobroot,blobfile,bname)
+ if trace_detail then
+ report_resolving("match: variant %a, search %a, result %a",variant,search,result)
+ end
+ noffiles=noffiles+1
+ filelist[noffiles]={ variant,search,result }
+ end
+ else
+ for kk=1,#blobfile do
+ local vv=blobfile[kk]
+ if not dname or find(vv,dname) then
+ local variant=hash.type
+ local search=filejoin(blobroot,vv,bname)
+ local result=methodhandler('concatinators',hash.type,blobroot,vv,bname)
+ if trace_detail then
+ report_resolving("match: variant %a, search %a, result %a",variant,search,result)
+ end
+ noffiles=noffiles+1
+ filelist[noffiles]={ variant,search,result }
+ end
+ end
+ end
end
- return s
+ elseif trace_locating then
+ report_resolving("no match in %a (%s)",blobpath,bname)
+ end
end
+ end
+ return noffiles>0 and filelist or nil
end
-
-function containers.is_usable(container, name)
- return container.enabled and caches and caches.is_writable(container.writable, name)
+local fit={}
+function resolvers.registerintrees(filename,format,filetype,usedmethod,foundname)
+ local foundintrees=instance.foundintrees
+ if usedmethod=="direct" and filename==foundname and fit[foundname] then
+ else
+ local t={
+ filename=filename,
+ format=format~="" and format or nil,
+ filetype=filetype~="" and filetype or nil,
+ usedmethod=usedmethod,
+ foundname=foundname,
+ }
+ fit[foundname]=t
+ foundintrees[#foundintrees+1]=t
+ end
end
-
-function containers.is_valid(container, name)
- if name and name ~= "" then
- local storage = container.storage[name]
- return storage and storage.cache_version == container.version
+local function can_be_dir(name)
+ local fakepaths=instance.fakepaths
+ if not fakepaths[name] then
+ if lfs.isdir(name) then
+ fakepaths[name]=1
else
- return false
+ fakepaths[name]=2
end
+ end
+ return fakepaths[name]==1
end
-
-function containers.read(container,name)
- local storage = container.storage
- local stored = storage[name]
- if not stored and container.enabled and caches and containers.usecache then
- stored = caches.loaddata(container.readables,name)
- if stored and stored.cache_version == container.version then
- report(container,"loaded",name)
- else
- stored = nil
+local preparetreepattern=Cs((P(".")/"%%."+P("-")/"%%-"+P(1))^0*Cc("$"))
+local collect_instance_files
+local function find_analyze(filename,askedformat,allresults)
+ local filetype,wantedfiles,ext='',{},suffixonly(filename)
+ wantedfiles[#wantedfiles+1]=filename
+ if askedformat=="" then
+ if ext=="" or not suffixmap[ext] then
+ local defaultsuffixes=resolvers.defaultsuffixes
+ for i=1,#defaultsuffixes do
+ local forcedname=filename..'.'..defaultsuffixes[i]
+ wantedfiles[#wantedfiles+1]=forcedname
+ filetype=resolvers.formatofsuffix(forcedname)
+ if trace_locating then
+ report_resolving("forcing filetype %a",filetype)
end
- storage[name] = stored
- elseif stored then
- report(container,"reusing",name)
+ end
+ else
+ filetype=resolvers.formatofsuffix(filename)
+ if trace_locating then
+ report_resolving("using suffix based filetype %a",filetype)
+ end
end
- return stored
-end
-
-function containers.write(container, name, data)
- if data then
- data.cache_version = container.version
- if container.enabled and caches then
- local unique, shared = data.unique, data.shared
- data.unique, data.shared = nil, nil
- caches.savedata(container.writable, name, data)
- report(container,"saved",name)
- data.unique, data.shared = unique, shared
+ else
+ if ext=="" or not suffixmap[ext] then
+ local format_suffixes=suffixes[askedformat]
+ if format_suffixes then
+ for i=1,#format_suffixes do
+ wantedfiles[#wantedfiles+1]=filename.."."..format_suffixes[i]
end
- report(container,"stored",name)
- container.storage[name] = data
+ end
end
- return data
+ filetype=askedformat
+ if trace_locating then
+ report_resolving("using given filetype %a",filetype)
+ end
+ end
+ return filetype,wantedfiles
end
-
-function containers.content(container,name)
- return container.storage[name]
+local function find_direct(filename,allresults)
+ if not dangerous[askedformat] and isreadable(filename) then
+ if trace_detail then
+ report_resolving("file %a found directly",filename)
+ end
+ return "direct",{ filename }
+ end
end
-
-function containers.cleanname(name)
- return (gsub(lower(name),"[^%w%d]+","-"))
+local function find_wildcard(filename,allresults)
+ if find(filename,'%*') then
+ if trace_locating then
+ report_resolving("checking wildcard %a",filename)
+ end
+ local method,result=resolvers.findwildcardfiles(filename)
+ if result then
+ return "wildcard",result
+ end
+ end
+end
+local function find_qualified(filename,allresults,askedformat,alsostripped)
+ if not file.is_qualified_path(filename) then
+ return
+ end
+ if trace_locating then
+ report_resolving("checking qualified name %a",filename)
+ end
+ if isreadable(filename) then
+ if trace_detail then
+ report_resolving("qualified file %a found",filename)
+ end
+ return "qualified",{ filename }
+ end
+ if trace_detail then
+ report_resolving("locating qualified file %a",filename)
+ end
+ local forcedname,suffix="",suffixonly(filename)
+ if suffix=="" then
+ local format_suffixes=askedformat=="" and resolvers.defaultsuffixes or suffixes[askedformat]
+ if format_suffixes then
+ for i=1,#format_suffixes do
+ local s=format_suffixes[i]
+ forcedname=filename.."."..s
+ if isreadable(forcedname) then
+ if trace_locating then
+ report_resolving("no suffix, forcing format filetype %a",s)
+ end
+ return "qualified",{ forcedname }
+ end
+ end
+ end
+ end
+ if alsostripped and suffix and suffix~="" then
+ local basename=filebasename(filename)
+ local pattern=lpegmatch(preparetreepattern,filename)
+ local savedformat=askedformat
+ local format=savedformat or ""
+ if format=="" then
+ askedformat=resolvers.formatofsuffix(suffix)
+ end
+ if not format then
+ askedformat="othertextfiles"
+ end
+ if basename~=filename then
+ local resolved=collect_instance_files(basename,askedformat,allresults)
+ if #resolved==0 then
+ local lowered=lower(basename)
+ if filename~=lowered then
+ resolved=collect_instance_files(lowered,askedformat,allresults)
+ end
+ end
+ resolvers.format=savedformat
+ if #resolved>0 then
+ local result={}
+ for r=1,#resolved do
+ local rr=resolved[r]
+ if find(rr,pattern) then
+ result[#result+1]=rr
+ end
+ end
+ if #result>0 then
+ return "qualified",result
+ end
+ end
+ end
+ end
end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['data-use'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local format, lower, gsub, find = string.format, string.lower, string.gsub, string.find
-
-local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
-
-local report_mounts = logs.reporter("resolvers","mounts")
-
-local resolvers = resolvers
-
--- we will make a better format, maybe something xml or just text or lua
-
-resolvers.automounted = resolvers.automounted or { }
-
-function resolvers.automount(usecache)
- local mountpaths = resolvers.cleanpathlist(resolvers.expansion('TEXMFMOUNT'))
- if (not mountpaths or #mountpaths == 0) and usecache then
- mountpaths = caches.getreadablepaths("mount")
- end
- if mountpaths and #mountpaths > 0 then
- statistics.starttiming(resolvers.instance)
- for k=1,#mountpaths do
- local root = mountpaths[k]
- local f = io.open(root.."/url.tmi")
- if f then
- for line in f:lines() do
- if line then
- if find(line,"^[%%#%-]") then -- or %W
- -- skip
- elseif find(line,"^zip://") then
- if trace_locating then
- report_mounts("mounting %s",line)
- end
- table.insert(resolvers.automounted,line)
- resolvers.usezipfile(line)
+local function check_subpath(fname)
+ if isreadable(fname) then
+ if trace_detail then
+ report_resolving("found %a by deep scanning",fname)
+ end
+ return fname
+ end
+end
+local function find_intree(filename,filetype,wantedfiles,allresults)
+ local typespec=resolvers.variableofformat(filetype)
+ local pathlist=resolvers.expandedpathlist(typespec)
+ local method="intree"
+ if pathlist and #pathlist>0 then
+ local filelist=collect_files(wantedfiles)
+ local dirlist={}
+ if filelist then
+ for i=1,#filelist do
+ dirlist[i]=filedirname(filelist[i][3]).."/"
+ end
+ end
+ if trace_detail then
+ report_resolving("checking filename %a",filename)
+ end
+ local resolve=resolvers.resolve
+ local result={}
+ for k=1,#pathlist do
+ local path=pathlist[k]
+ local pathname=lpegmatch(inhibitstripper,path)
+ local doscan=path==pathname
+ if not find (pathname,'//$') then
+ doscan=false
+ end
+ local done=false
+ if filelist then
+ local expression=makepathexpression(pathname)
+ if trace_detail then
+ report_resolving("using pattern %a for path %a",expression,pathname)
+ end
+ for k=1,#filelist do
+ local fl=filelist[k]
+ local f=fl[2]
+ local d=dirlist[k]
+ if find(d,expression) or find(resolve(d),expression) then
+ result[#result+1]=resolve(fl[3])
+ done=true
+ if allresults then
+ if trace_detail then
+ report_resolving("match to %a in hash for file %a and path %a, continue scanning",expression,f,d)
+ end
+ else
+ if trace_detail then
+ report_resolving("match to %a in hash for file %a and path %a, quit scanning",expression,f,d)
+ end
+ break
+ end
+ elseif trace_detail then
+ report_resolving("no match to %a in hash for file %a and path %a",expression,f,d)
+ end
+ end
+ end
+ if done then
+ method="database"
+ else
+ method="filesystem"
+ pathname=gsub(pathname,"/+$","")
+ pathname=resolve(pathname)
+ local scheme=url.hasscheme(pathname)
+ if not scheme or scheme=="file" then
+ local pname=gsub(pathname,"%.%*$",'')
+ if not find(pname,"%*") then
+ if can_be_dir(pname) then
+ for k=1,#wantedfiles do
+ local w=wantedfiles[k]
+ local fname=check_subpath(filejoin(pname,w))
+ if fname then
+ result[#result+1]=fname
+ done=true
+ if not allresults then
+ break
+ end
+ end
+ end
+ if not done and doscan then
+ local files=resolvers.simplescanfiles(pname,false,true)
+ for k=1,#wantedfiles do
+ local w=wantedfiles[k]
+ local subpath=files[w]
+ if not subpath or subpath=="" then
+ elseif type(subpath)=="string" then
+ local fname=check_subpath(filejoin(pname,subpath,w))
+ if fname then
+ result[#result+1]=fname
+ done=true
+ if not allresults then
+ break
+ end
+ end
+ else
+ for i=1,#subpath do
+ local sp=subpath[i]
+ if sp=="" then
+ else
+ local fname=check_subpath(filejoin(pname,sp,w))
+ if fname then
+ result[#result+1]=fname
+ done=true
+ if not allresults then
+ break
+ end
end
+ end
+ end
+ if done and not allresults then
+ break
end
+ end
end
- f:close()
+ end
end
+ else
+ end
end
- statistics.stoptiming(resolvers.instance)
+ end
+ if done and not allresults then
+ break
+ end
end
-end
-
--- status info
-
-statistics.register("used config file", function() return caches.configfiles() end)
-statistics.register("used cache path", function() return caches.usedpaths() end)
-
--- experiment (code will move)
-
-function statistics.savefmtstatus(texname,formatbanner,sourcefile) -- texname == formatname
- local enginebanner = status.list().banner
- if formatbanner and enginebanner and sourcefile then
- local luvname = file.replacesuffix(texname,"luv")
- local luvdata = {
- enginebanner = enginebanner,
- formatbanner = formatbanner,
- sourcehash = md5.hex(io.loaddata(resolvers.findfile(sourcefile)) or "unknown"),
- sourcefile = sourcefile,
- }
- io.savedata(luvname,table.serialize(luvdata,true))
+ if #result>0 then
+ return method,result
end
+ end
end
-
-function statistics.checkfmtstatus(texname)
- local enginebanner = status.list().banner
- if enginebanner and texname then
- local luvname = file.replacesuffix(texname,"luv")
- if lfs.isfile(luvname) then
- local luv = dofile(luvname)
- if luv and luv.sourcefile then
- local sourcehash = md5.hex(io.loaddata(resolvers.findfile(luv.sourcefile)) or "unknown")
- local luvbanner = luv.enginebanner or "?"
- if luvbanner ~= enginebanner then
- return format("engine mismatch (luv: %s <> bin: %s)",luvbanner,enginebanner)
- end
- local luvhash = luv.sourcehash or "?"
- if luvhash ~= sourcehash then
- return format("source mismatch (luv: %s <> bin: %s)",luvhash,sourcehash)
- end
- else
- return "invalid status file"
- end
- else
- return "missing status file"
+local function find_onpath(filename,filetype,wantedfiles,allresults)
+ if trace_detail then
+ report_resolving("checking filename %a, filetype %a, wanted files %a",filename,filetype,concat(wantedfiles," | "))
+ end
+ local result={}
+ for k=1,#wantedfiles do
+ local fname=wantedfiles[k]
+ if fname and isreadable(fname) then
+ filename=fname
+ result[#result+1]=filejoin('.',fname)
+ if not allresults then
+ break
+ end
+ end
+ end
+ if #result>0 then
+ return "onpath",result
+ end
+end
+local function find_otherwise(filename,filetype,wantedfiles,allresults)
+ local filelist=collect_files(wantedfiles)
+ local fl=filelist and filelist[1]
+ if fl then
+ return "otherwise",{ resolvers.resolve(fl[3]) }
+ end
+end
+collect_instance_files=function(filename,askedformat,allresults)
+ askedformat=askedformat or ""
+ filename=collapsepath(filename)
+ if allresults then
+ local filetype,wantedfiles=find_analyze(filename,askedformat)
+ local results={
+ { find_direct (filename,true) },
+ { find_wildcard (filename,true) },
+ { find_qualified(filename,true,askedformat) },
+ { find_intree (filename,filetype,wantedfiles,true) },
+ { find_onpath (filename,filetype,wantedfiles,true) },
+ { find_otherwise(filename,filetype,wantedfiles,true) },
+ }
+ local result,status,done={},{},{}
+ for k,r in next,results do
+ local method,list=r[1],r[2]
+ if method and list then
+ for i=1,#list do
+ local c=collapsepath(list[i])
+ if not done[c] then
+ result[#result+1]=c
+ done[c]=true
+ end
+ status[#status+1]=formatters["%-10s: %s"](method,c)
+ end
+ end
+ end
+ if trace_detail then
+ report_resolving("lookup status: %s",table.serialize(status,filename))
+ end
+ return result,status
+ else
+ local method,result,stamp,filetype,wantedfiles
+ if instance.remember then
+ stamp=formatters["%s--%s"](filename,askedformat)
+ result=stamp and instance.found[stamp]
+ if result then
+ if trace_locating then
+ report_resolving("remembered file %a",filename)
end
+ return result
+ end
end
- return true
-end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['data-zip'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- partly redone .. needs testing
-
-local format, find, match = string.format, string.find, string.match
-
-local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
-
-local report_zip = logs.reporter("resolvers","zip")
-
--- zip:///oeps.zip?name=bla/bla.tex
--- zip:///oeps.zip?tree=tex/texmf-local
--- zip:///texmf.zip?tree=/tex/texmf
--- zip:///texmf.zip?tree=/tex/texmf-local
--- zip:///texmf-mine.zip?tree=/tex/texmf-projects
-
-local resolvers = resolvers
-
-zip = zip or { }
-local zip = zip
-
-zip.archives = zip.archives or { }
-local archives = zip.archives
-
-zip.registeredfiles = zip.registeredfiles or { }
-local registeredfiles = zip.registeredfiles
-
-local limited = false
-
-directives.register("system.inputmode", function(v)
- if not limited then
- local i_limiter = io.i_limiter(v)
- if i_limiter then
- zip.open = i_limiter.protect(zip.open)
- limited = true
+ method,result=find_direct(filename)
+ if not result then
+ method,result=find_wildcard(filename)
+ if not result then
+ method,result=find_qualified(filename,false,askedformat)
+ if not result then
+ filetype,wantedfiles=find_analyze(filename,askedformat)
+ method,result=find_intree(filename,filetype,wantedfiles)
+ if not result then
+ method,result=find_onpath(filename,filetype,wantedfiles)
+ if not result then
+ method,result=find_otherwise(filename,filetype,wantedfiles)
+ end
+ end
end
+ end
end
-end)
-
-local function validzip(str) -- todo: use url splitter
- if not find(str,"^zip://") then
- return "zip:///" .. str
+ if result and #result>0 then
+ local foundname=collapsepath(result[1])
+ resolvers.registerintrees(filename,askedformat,filetype,method,foundname)
+ result={ foundname }
else
- return str
+ result={}
end
-end
-
-function zip.openarchive(name)
- if not name or name == "" then
- return nil
- else
- local arch = archives[name]
- if not arch then
- local full = resolvers.findfile(name) or ""
- arch = (full ~= "" and zip.open(full)) or false
- archives[name] = arch
- end
- return arch
+ if stamp then
+ if trace_locating then
+ report_resolving("remembering file %a",filename)
+ end
+ instance.found[stamp]=result
end
+ return result
+ end
end
-
-function zip.closearchive(name)
- if not name or (name == "" and archives[name]) then
- zip.close(archives[name])
- archives[name] = nil
+local function findfiles(filename,filetype,allresults)
+ local result,status=collect_instance_files(filename,filetype or "",allresults)
+ if not result or #result==0 then
+ local lowered=lower(filename)
+ if filename~=lowered then
+ result,status=collect_instance_files(lowered,filetype or "",allresults)
end
+ end
+ return result or {},status
+end
+function resolvers.findfiles(filename,filetype)
+ return findfiles(filename,filetype,true)
+end
+function resolvers.findfile(filename,filetype)
+ return findfiles(filename,filetype,false)[1] or ""
+end
+function resolvers.findpath(filename,filetype)
+ return filedirname(findfiles(filename,filetype,false)[1] or "")
end
-
-function resolvers.locators.zip(specification)
- local archive = specification.filename
- local zipfile = archive and archive ~= "" and zip.openarchive(archive) -- tricky, could be in to be initialized tree
- if trace_locating then
- if zipfile then
- report_zip("locator, archive '%s' found",archive)
- else
- report_zip("locator, archive '%s' not found",archive)
+local function findgivenfiles(filename,allresults)
+ local bname,result=filebasename(filename),{}
+ local hashes=instance.hashes
+ local noffound=0
+ for k=1,#hashes do
+ local hash=hashes[k]
+ local files=instance.files[hash.name] or {}
+ local blist=files[bname]
+ if not blist then
+ local rname="remap:"..bname
+ blist=files[rname]
+ if blist then
+ bname=files[rname]
+ blist=files[bname]
+ end
+ end
+ if blist then
+ if type(blist)=='string' then
+ local found=methodhandler('concatinators',hash.type,hash.name,blist,bname) or ""
+ if found~="" then
+ noffound=noffound+1
+ result[noffound]=resolvers.resolve(found)
+ if not allresults then
+ break
+ end
+ end
+ else
+ for kk=1,#blist do
+ local vv=blist[kk]
+ local found=methodhandler('concatinators',hash.type,hash.name,vv,bname) or ""
+ if found~="" then
+ noffound=noffound+1
+ result[noffound]=resolvers.resolve(found)
+ if not allresults then break end
+ end
end
+ end
end
+ end
+ return result
end
-
-function resolvers.hashers.zip(specification)
- local archive = specification.filename
- if trace_locating then
- report_zip("loading file '%s'",archive)
- end
- resolvers.usezipfile(specification.original)
+function resolvers.findgivenfiles(filename)
+ return findgivenfiles(filename,true)
end
-
-function resolvers.concatinators.zip(zipfile,path,name) -- ok ?
- if not path or path == "" then
- return format('%s?name=%s',zipfile,name)
- else
- return format('%s?name=%s/%s',zipfile,path,name)
- end
+function resolvers.findgivenfile(filename)
+ return findgivenfiles(filename,false)[1] or ""
end
-
-function resolvers.finders.zip(specification)
- local original = specification.original
- local archive = specification.filename
- if archive then
- local query = url.query(specification.query)
- local queryname = query.name
- if queryname then
- local zfile = zip.openarchive(archive)
- if zfile then
- if trace_locating then
- report_zip("finder, archive '%s' found",archive)
- end
- local dfile = zfile:open(queryname)
- if dfile then
- dfile = zfile:close()
- if trace_locating then
- report_zip("finder, file '%s' found",queryname)
- end
- return specification.original
- elseif trace_locating then
- report_zip("finder, file '%s' not found",queryname)
- end
- elseif trace_locating then
- report_zip("finder, unknown archive '%s'",archive)
- end
+local function doit(path,blist,bname,tag,variant,result,allresults)
+ local done=false
+ if blist and variant then
+ local resolve=resolvers.resolve
+ if type(blist)=='string' then
+ if find(lower(blist),path) then
+ local full=methodhandler('concatinators',variant,tag,blist,bname) or ""
+ result[#result+1]=resolve(full)
+ done=true
+ end
+ else
+ for kk=1,#blist do
+ local vv=blist[kk]
+ if find(lower(vv),path) then
+ local full=methodhandler('concatinators',variant,tag,vv,bname) or ""
+ result[#result+1]=resolve(full)
+ done=true
+ if not allresults then break end
end
+ end
end
- if trace_locating then
- report_zip("finder, '%s' not found",original)
- end
- return resolvers.finders.notfound()
+ end
+ return done
end
-
-function resolvers.openers.zip(specification)
- local original = specification.original
- local archive = specification.filename
- if archive then
- local query = url.query(specification.query)
- local queryname = query.name
- if queryname then
- local zfile = zip.openarchive(archive)
- if zfile then
- if trace_locating then
- report_zip("opener, archive '%s' opened",archive)
- end
- local dfile = zfile:open(queryname)
- if dfile then
- if trace_locating then
- report_zip("opener, file '%s' found",queryname)
- end
- return resolvers.openers.helpers.textopener('zip',original,dfile)
- elseif trace_locating then
- report_zip("opener, file '%s' not found",queryname)
- end
- elseif trace_locating then
- report_zip("opener, unknown archive '%s'",archive)
- end
+local makewildcard=Cs(
+ (P("^")^0*P("/")*P(-1)+P(-1))/".*"+(P("^")^0*P("/")/"")^0*(P("*")/".*"+P("-")/"%%-"+P(".")/"%%."+P("?")/"."+P("\\")/"/"+P(1))^0
+)
+function resolvers.wildcardpattern(pattern)
+ return lpegmatch(makewildcard,pattern) or pattern
+end
+local function findwildcardfiles(filename,allresults,result)
+ result=result or {}
+ local base=filebasename(filename)
+ local dirn=filedirname(filename)
+ local path=lower(lpegmatch(makewildcard,dirn) or dirn)
+ local name=lower(lpegmatch(makewildcard,base) or base)
+ local files,done=instance.files,false
+ if find(name,"%*") then
+ local hashes=instance.hashes
+ for k=1,#hashes do
+ local hash=hashes[k]
+ local hashname,hashtype=hash.name,hash.type
+ for kk,hh in next,files[hashname] do
+ if not find(kk,"^remap:") then
+ if find(lower(kk),name) then
+ if doit(path,hh,kk,hashname,hashtype,result,allresults) then done=true end
+ if done and not allresults then break end
+ end
end
+ end
end
- if trace_locating then
- report_zip("opener, '%s' not found",original)
+ else
+ local hashes=instance.hashes
+ for k=1,#hashes do
+ local hash=hashes[k]
+ local hashname,hashtype=hash.name,hash.type
+ if doit(path,files[hashname][bname],bname,hashname,hashtype,result,allresults) then done=true end
+ if done and not allresults then break end
end
- return resolvers.openers.notfound()
+ end
+ return result
end
-
-function resolvers.loaders.zip(specification)
- local original = specification.original
- local archive = specification.filename
- if archive then
- local query = url.query(specification.query)
- local queryname = query.name
- if queryname then
- local zfile = zip.openarchive(archive)
- if zfile then
- if trace_locating then
- report_zip("loader, archive '%s' opened",archive)
- end
- local dfile = zfile:open(queryname)
- if dfile then
- logs.show_load(original)
- if trace_locating then
- report_zip("loader, file '%s' loaded",original)
- end
- local s = dfile:read("*all")
- dfile:close()
- return true, s, #s
- elseif trace_locating then
- report_zip("loader, file '%s' not found",queryname)
- end
- elseif trace_locating then
- report_zip("loader, unknown archive '%s'",archive)
- end
- end
- end
+function resolvers.findwildcardfiles(filename,result)
+ return findwildcardfiles(filename,true,result)
+end
+function resolvers.findwildcardfile(filename)
+ return findwildcardfiles(filename,false)[1] or ""
+end
+function resolvers.automount()
+end
+function resolvers.load(option)
+ statistics.starttiming(instance)
+ identify_configuration_files()
+ load_configuration_files()
+ if option~="nofiles" then
+ load_databases()
+ resolvers.automount()
+ end
+ statistics.stoptiming(instance)
+ local files=instance.files
+ return files and next(files) and true
+end
+function resolvers.loadtime()
+ return statistics.elapsedtime(instance)
+end
+local function report(str)
+ if trace_locating then
+ report_resolving(str)
+ else
+ print(str)
+ end
+end
+function resolvers.dowithfilesandreport(command,files,...)
+ if files and #files>0 then
if trace_locating then
- report_zip("loader, '%s' not found",original)
+ report('')
end
- return resolvers.openers.notfound()
-end
-
--- zip:///somefile.zip
--- zip:///somefile.zip?tree=texmf-local -> mount
-
-function resolvers.usezipfile(archive)
- local specification = resolvers.splitmethod(archive) -- to be sure
- local archive = specification.filename
- if archive and not registeredfiles[archive] then
- local z = zip.openarchive(archive)
- if z then
- local instance = resolvers.instance
- local tree = url.query(specification.query).tree or ""
- if trace_locating then
- report_zip("registering, registering archive '%s'",archive)
- end
- statistics.starttiming(instance)
- resolvers.prependhash('zip',archive)
- resolvers.extendtexmfvariable(archive) -- resets hashes too
- registeredfiles[archive] = z
- instance.files[archive] = resolvers.registerzipfile(z,tree)
- statistics.stoptiming(instance)
- elseif trace_locating then
- report_zip("registering, unknown archive '%s'",archive)
+ if type(files)=="string" then
+ files={ files }
+ end
+ for f=1,#files do
+ local file=files[f]
+ local result=command(file,...)
+ if type(result)=='string' then
+ report(result)
+ else
+ for i=1,#result do
+ report(result[i])
end
- elseif trace_locating then
- report_zip("registering, '%s' not found",archive)
+ end
end
+ end
end
-
-function resolvers.registerzipfile(z,tree)
- local files, filter = { }, ""
- if tree == "" then
- filter = "^(.+)/(.-)$"
+function resolvers.showpath(str)
+ return joinpath(resolvers.expandedpathlist(resolvers.formatofvariable(str)))
+end
+function resolvers.registerfile(files,name,path)
+ if files[name] then
+ if type(files[name])=='string' then
+ files[name]={ files[name],path }
else
- filter = format("^%s/(.+)/(.-)$",tree)
+ files[name]=path
end
- if trace_locating then
- report_zip("registering, using filter '%s'",filter)
- end
- local register, n = resolvers.registerfile, 0
- for i in z:files() do
- local path, name = match(i.filename,filter)
- if path then
- if name and name ~= '' then
- register(files, name, path)
- n = n + 1
+ else
+ files[name]=path
+ end
+end
+function resolvers.dowithpath(name,func)
+ local pathlist=resolvers.expandedpathlist(name)
+ for i=1,#pathlist do
+ func("^"..resolvers.cleanpath(pathlist[i]))
+ end
+end
+function resolvers.dowithvariable(name,func)
+ func(expandedvariable(name))
+end
+function resolvers.locateformat(name)
+ local engine=environment.ownmain or "luatex"
+ local barename=file.removesuffix(name)
+ local fullname=file.addsuffix(barename,"fmt")
+ local fmtname=caches.getfirstreadablefile(fullname,"formats",engine) or ""
+ if fmtname=="" then
+ fmtname=resolvers.findfile(fullname)
+ fmtname=resolvers.cleanpath(fmtname)
+ end
+ if fmtname~="" then
+ local barename=file.removesuffix(fmtname)
+ local luaname=file.addsuffix(barename,luasuffixes.lua)
+ local lucname=file.addsuffix(barename,luasuffixes.luc)
+ local luiname=file.addsuffix(barename,luasuffixes.lui)
+ if lfs.isfile(luiname) then
+ return barename,luiname
+ elseif lfs.isfile(lucname) then
+ return barename,lucname
+ elseif lfs.isfile(luaname) then
+ return barename,luaname
+ end
+ end
+ return nil,nil
+end
+function resolvers.booleanvariable(str,default)
+ local b=resolvers.expansion(str)
+ if b=="" then
+ return default
+ else
+ b=toboolean(b)
+ return (b==nil and default) or b
+ end
+end
+function resolvers.dowithfilesintree(pattern,handle,before,after)
+ local instance=resolvers.instance
+ local hashes=instance.hashes
+ for i=1,#hashes do
+ local hash=hashes[i]
+ local blobtype=hash.type
+ local blobpath=hash.name
+ if blobpath then
+ if before then
+ before(blobtype,blobpath,pattern)
+ end
+ local files=instance.files[blobpath]
+ local total,checked,done=0,0,0
+ if files then
+ for k,v in table.sortedhash(files) do
+ total=total+1
+ if find(k,"^remap:") then
+ elseif find(k,pattern) then
+ if type(v)=="string" then
+ checked=checked+1
+ if handle(blobtype,blobpath,v,k) then
+ done=done+1
+ end
else
- -- directory
+ checked=checked+#v
+ for i=1,#v do
+ if handle(blobtype,blobpath,v[i],k) then
+ done=done+1
+ end
+ end
end
- else
- register(files, i.filename, '')
- n = n + 1
+ end
end
+ end
+ if after then
+ after(blobtype,blobpath,pattern,total,checked,done)
+ end
end
- report_zip("registering, %s files registered",n)
- return files
+ end
end
+resolvers.obsolete=resolvers.obsolete or {}
+local obsolete=resolvers.obsolete
+resolvers.find_file=resolvers.findfile obsolete.find_file=resolvers.findfile
+resolvers.find_files=resolvers.findfiles obsolete.find_files=resolvers.findfiles
end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['data-tre'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- \input tree://oeps1/**/oeps.tex
+package.loaded["data-pre"] = package.loaded["data-pre"] or true
-local find, gsub, format = string.find, string.gsub, string.format
+-- original size: 6430, stripped down to: 4219
-local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
-
-local report_trees = logs.reporter("resolvers","trees")
-
-local resolvers = resolvers
-
-local done, found, notfound = { }, { }, resolvers.finders.notfound
-
-function resolvers.finders.tree(specification)
- local spec = specification.filename
- local fnd = found[spec]
- if fnd == nil then
- if spec ~= "" then
- local path, name = file.dirname(spec), file.basename(spec)
- if path == "" then path = "." end
- local hash = done[path]
- if not hash then
- local pattern = path .. "/*" -- we will use the proper splitter
- hash = dir.glob(pattern)
- done[path] = hash
- end
- local pattern = "/" .. gsub(name,"([%.%-%+])", "%%%1") .. "$"
- for k=1,#hash do
- local v = hash[k]
- if find(v,pattern) then
- found[spec] = v
- return v
- end
- end
- end
- fnd = notfound() -- false
- found[spec] = fnd
+if not modules then modules={} end modules ['data-pre']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local resolvers=resolvers
+local prefixes=utilities.storage.allocate()
+resolvers.prefixes=prefixes
+local cleanpath,findgivenfile,expansion=resolvers.cleanpath,resolvers.findgivenfile,resolvers.expansion
+local getenv=resolvers.getenv
+local P,S,R,C,Cs,lpegmatch=lpeg.P,lpeg.S,lpeg.R,lpeg.C,lpeg.Cs,lpeg.match
+local joinpath,basename,dirname=file.join,file.basename,file.dirname
+local getmetatable,rawset,type=getmetatable,rawset,type
+prefixes.environment=function(str)
+ return cleanpath(expansion(str))
+end
+prefixes.relative=function(str,n)
+ if io.exists(str) then
+ elseif io.exists("./"..str) then
+ str="./"..str
+ else
+ local p="../"
+ for i=1,n or 2 do
+ if io.exists(p..str) then
+ str=p..str
+ break
+ else
+ p=p.."../"
+ end
+ end
+ end
+ return cleanpath(str)
+end
+prefixes.auto=function(str)
+ local fullname=prefixes.relative(str)
+ if not lfs.isfile(fullname) then
+ fullname=prefixes.locate(str)
+ end
+ return fullname
+end
+prefixes.locate=function(str)
+ local fullname=findgivenfile(str) or ""
+ return cleanpath((fullname~="" and fullname) or str)
+end
+prefixes.filename=function(str)
+ local fullname=findgivenfile(str) or ""
+ return cleanpath(basename((fullname~="" and fullname) or str))
+end
+prefixes.pathname=function(str)
+ local fullname=findgivenfile(str) or ""
+ return cleanpath(dirname((fullname~="" and fullname) or str))
+end
+prefixes.selfautoloc=function(str)
+ return cleanpath(joinpath(getenv('SELFAUTOLOC'),str))
+end
+prefixes.selfautoparent=function(str)
+ return cleanpath(joinpath(getenv('SELFAUTOPARENT'),str))
+end
+prefixes.selfautodir=function(str)
+ return cleanpath(joinpath(getenv('SELFAUTODIR'),str))
+end
+prefixes.home=function(str)
+ return cleanpath(joinpath(getenv('HOME'),str))
+end
+local function toppath()
+ local inputstack=resolvers.inputstack
+ if not inputstack then
+ return "."
+ end
+ local pathname=dirname(inputstack[#inputstack] or "")
+ if pathname=="" then
+ return "."
+ else
+ return pathname
+ end
+end
+resolvers.toppath=toppath
+prefixes.toppath=function(str)
+ return cleanpath(joinpath(toppath(),str))
+end
+prefixes.env=prefixes.environment
+prefixes.rel=prefixes.relative
+prefixes.loc=prefixes.locate
+prefixes.kpse=prefixes.locate
+prefixes.full=prefixes.locate
+prefixes.file=prefixes.filename
+prefixes.path=prefixes.pathname
+function resolvers.allprefixes(separator)
+ local all=table.sortedkeys(prefixes)
+ if separator then
+ for i=1,#all do
+ all[i]=all[i]..":"
end
- return fnd
+ end
+ return all
end
-
-function resolvers.locators.tree(specification)
- local name = specification.filename
- local realname = resolvers.resolve(name) -- no shortcut
- if realname and realname ~= '' and lfs.isdir(realname) then
- if trace_locating then
- report_trees("locator '%s' found",realname)
- end
- resolvers.appendhash('tree',name,false) -- don't cache
- elseif trace_locating then
- report_trees("locator '%s' not found",name)
+local function _resolve_(method,target)
+ local action=prefixes[method]
+ if action then
+ return action(target)
+ else
+ return method..":"..target
+ end
+end
+local resolved,abstract={},{}
+function resolvers.resetresolve(str)
+ resolved,abstract={},{}
+end
+local pattern=Cs((C(R("az")^2)*P(":")*C((1-S(" \"\';,"))^1)/_resolve_+P(1))^0)
+local function resolve(str)
+ if type(str)=="table" then
+ local t={}
+ for i=1,#str do
+ t[i]=resolve(str[i])
+ end
+ return t
+ else
+ local res=resolved[str]
+ if not res then
+ res=lpegmatch(pattern,str)
+ resolved[str]=res
+ abstract[res]=str
end
+ return res
+ end
end
-
-function resolvers.hashers.tree(specification)
- local name = specification.filename
- if trace_locating then
- report_trees("analysing '%s'",name)
+local function unresolve(str)
+ return abstract[str] or str
+end
+resolvers.resolve=resolve
+resolvers.unresolve=unresolve
+if type(os.uname)=="function" then
+ for k,v in next,os.uname() do
+ if not prefixes[k] then
+ prefixes[k]=function() return v end
end
- resolvers.methodhandler("hashers",name)
-
- resolvers.generators.file(specification)
+ end
+end
+if os.type=="unix" then
+ local pattern
+ local function makepattern(t,k,v)
+ if t then
+ rawset(t,k,v)
+ end
+ local colon=P(":")
+ for k,v in table.sortedpairs(prefixes) do
+ if p then
+ p=P(k)+p
+ else
+ p=P(k)
+ end
+ end
+ pattern=Cs((p*colon+colon/";"+P(1))^0)
+ end
+ makepattern()
+ getmetatable(prefixes).__newindex=makepattern
+ function resolvers.repath(str)
+ return lpegmatch(pattern,str)
+ end
+else
+ function resolvers.repath(str)
+ return str
+ end
end
-
-resolvers.concatinators.tree = resolvers.concatinators.file
-resolvers.generators.tree = resolvers.generators.file
-resolvers.openers.tree = resolvers.openers.file
-resolvers.loaders.tree = resolvers.loaders.file
end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['data-crl'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
+package.loaded["data-inp"] = package.loaded["data-inp"] or true
+
+-- original size: 910, stripped down to: 823
--- this one is replaced by data-sch.lua --
+if not modules then modules={} end modules ['data-inp']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local allocate=utilities.storage.allocate
+local resolvers=resolvers
+local methodhandler=resolvers.methodhandler
+local registermethod=resolvers.registermethod
+local finders=allocate { helpers={},notfound=function() end }
+local openers=allocate { helpers={},notfound=function() end }
+local loaders=allocate { helpers={},notfound=function() return false,nil,0 end }
+registermethod("finders",finders,"uri")
+registermethod("openers",openers,"uri")
+registermethod("loaders",loaders,"uri")
+resolvers.finders=finders
+resolvers.openers=openers
+resolvers.loaders=loaders
-local gsub = string.gsub
-local resolvers = resolvers
+end -- of closure
-local finders, openers, loaders = resolvers.finders, resolvers.openers, resolvers.loaders
+do -- create closure to overcome 200 locals limit
-resolvers.curl = resolvers.curl or { }
-local curl = resolvers.curl
+package.loaded["data-out"] = package.loaded["data-out"] or true
-local cached = { }
+-- original size: 530, stripped down to: 475
-local function runcurl(specification)
- local original = specification.original
- -- local scheme = specification.scheme
- local cleanname = gsub(original,"[^%a%d%.]+","-")
- local cachename = caches.setfirstwritablefile(cleanname,"curl")
- if not cached[original] then
- if not io.exists(cachename) then
- cached[original] = cachename
- local command = "curl --silent --create-dirs --output " .. cachename .. " " .. original
- os.spawn(command)
- end
- if io.exists(cachename) then
- cached[original] = cachename
- else
- cached[original] = ""
- end
- end
- return cached[original]
-end
+if not modules then modules={} end modules ['data-out']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local allocate=utilities.storage.allocate
+local resolvers=resolvers
+local registermethod=resolvers.registermethod
+local savers=allocate { helpers={} }
+resolvers.savers=savers
+registermethod("savers",savers,"uri")
--- old code: we could be cleaner using specification (see schemes)
-local function finder(specification,filetype)
- return resolvers.methodhandler("finders",runcurl(specification),filetype)
-end
+end -- of closure
-local opener = openers.file
-local loader = loaders.file
+do -- create closure to overcome 200 locals limit
-local function install(scheme)
- finders[scheme] = finder
- openers[scheme] = opener
- loaders[scheme] = loader
-end
+package.loaded["data-fil"] = package.loaded["data-fil"] or true
-resolvers.curl.install = install
+-- original size: 3801, stripped down to: 3231
-install('http')
-install('https')
-install('ftp')
+if not modules then modules={} end modules ['data-fil']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end)
+local report_files=logs.reporter("resolvers","files")
+local resolvers=resolvers
+local finders,openers,loaders,savers=resolvers.finders,resolvers.openers,resolvers.loaders,resolvers.savers
+local locators,hashers,generators,concatinators=resolvers.locators,resolvers.hashers,resolvers.generators,resolvers.concatinators
+local checkgarbage=utilities.garbagecollector and utilities.garbagecollector.check
+function locators.file(specification)
+ local name=specification.filename
+ local realname=resolvers.resolve(name)
+ if realname and realname~='' and lfs.isdir(realname) then
+ if trace_locating then
+ report_files("file locator %a found as %a",name,realname)
+ end
+ resolvers.appendhash('file',name,true)
+ elseif trace_locating then
+ report_files("file locator %a not found",name)
+ end
+end
+function hashers.file(specification)
+ local name=specification.filename
+ local content=caches.loadcontent(name,'files')
+ resolvers.registerfilehash(name,content,content==nil)
+end
+function generators.file(specification)
+ local path=specification.filename
+ local content=resolvers.scanfiles(path,false,true)
+ resolvers.registerfilehash(path,content,true)
+end
+concatinators.file=file.join
+function finders.file(specification,filetype)
+ local filename=specification.filename
+ local foundname=resolvers.findfile(filename,filetype)
+ if foundname and foundname~="" then
+ if trace_locating then
+ report_files("file finder: %a found",filename)
+ end
+ return foundname
+ else
+ if trace_locating then
+ report_files("file finder: %a not found",filename)
+ end
+ return finders.notfound()
+ end
+end
+function openers.helpers.textopener(tag,filename,f)
+ return {
+ reader=function() return f:read () end,
+ close=function() logs.show_close(filename) return f:close() end,
+ }
+end
+function openers.file(specification,filetype)
+ local filename=specification.filename
+ if filename and filename~="" then
+ local f=io.open(filename,"r")
+ if f then
+ if trace_locating then
+ report_files("file opener: %a opened",filename)
+ end
+ return openers.helpers.textopener("file",filename,f)
+ end
+ end
+ if trace_locating then
+ report_files("file opener: %a not found",filename)
+ end
+ return openers.notfound()
+end
+function loaders.file(specification,filetype)
+ local filename=specification.filename
+ if filename and filename~="" then
+ local f=io.open(filename,"rb")
+ if f then
+ logs.show_load(filename)
+ if trace_locating then
+ report_files("file loader: %a loaded",filename)
+ end
+ local s=f:read("*a")
+ if checkgarbage then
+ checkgarbage(#s)
+ end
+ f:close()
+ if s then
+ return true,s,#s
+ end
+ end
+ end
+ if trace_locating then
+ report_files("file loader: %a not found",filename)
+ end
+ return loaders.notfound()
+end
end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['data-lua'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
+package.loaded["data-con"] = package.loaded["data-con"] or true
--- some loading stuff ... we might move this one to slot 2 depending
--- on the developments (the loaders must not trigger kpse); we could
--- of course use a more extensive lib path spec
+-- original size: 4940, stripped down to: 3580
-local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
+if not modules then modules={} end modules ['data-con']={
+ version=1.100,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local format,lower,gsub=string.format,string.lower,string.gsub
+local trace_cache=false trackers.register("resolvers.cache",function(v) trace_cache=v end)
+local trace_containers=false trackers.register("resolvers.containers",function(v) trace_containers=v end)
+local trace_storage=false trackers.register("resolvers.storage",function(v) trace_storage=v end)
+containers=containers or {}
+local containers=containers
+containers.usecache=true
+local report_containers=logs.reporter("resolvers","containers")
+local allocated={}
+local mt={
+ __index=function(t,k)
+ if k=="writable" then
+ local writable=caches.getwritablepath(t.category,t.subcategory) or { "." }
+ t.writable=writable
+ return writable
+ elseif k=="readables" then
+ local readables=caches.getreadablepaths(t.category,t.subcategory) or { "." }
+ t.readables=readables
+ return readables
+ end
+ end,
+ __storage__=true
+}
+function containers.define(category,subcategory,version,enabled)
+ if category and subcategory then
+ local c=allocated[category]
+ if not c then
+ c={}
+ allocated[category]=c
+ end
+ local s=c[subcategory]
+ if not s then
+ s={
+ category=category,
+ subcategory=subcategory,
+ storage={},
+ enabled=enabled,
+ version=version or math.pi,
+ trace=false,
+ }
+ setmetatable(s,mt)
+ c[subcategory]=s
+ end
+ return s
+ end
+end
+function containers.is_usable(container,name)
+ return container.enabled and caches and caches.is_writable(container.writable,name)
+end
+function containers.is_valid(container,name)
+ if name and name~="" then
+ local storage=container.storage[name]
+ return storage and storage.cache_version==container.version
+ else
+ return false
+ end
+end
+function containers.read(container,name)
+ local storage=container.storage
+ local stored=storage[name]
+ if not stored and container.enabled and caches and containers.usecache then
+ stored=caches.loaddata(container.readables,name)
+ if stored and stored.cache_version==container.version then
+ if trace_cache or trace_containers then
+ report_containers("action %a, category %a, name %a","load",container.subcategory,name)
+ end
+ else
+ stored=nil
+ end
+ storage[name]=stored
+ elseif stored then
+ if trace_cache or trace_containers then
+ report_containers("action %a, category %a, name %a","reuse",container.subcategory,name)
+ end
+ end
+ return stored
+end
+function containers.write(container,name,data)
+ if data then
+ data.cache_version=container.version
+ if container.enabled and caches then
+ local unique,shared=data.unique,data.shared
+ data.unique,data.shared=nil,nil
+ caches.savedata(container.writable,name,data)
+ if trace_cache or trace_containers then
+ report_containers("action %a, category %a, name %a","save",container.subcategory,name)
+ end
+ data.unique,data.shared=unique,shared
+ end
+ if trace_cache or trace_containers then
+ report_containers("action %a, category %a, name %a","store",container.subcategory,name)
+ end
+ container.storage[name]=data
+ end
+ return data
+end
+function containers.content(container,name)
+ return container.storage[name]
+end
+function containers.cleanname(name)
+ return (gsub(lower(name),"[^%w%d]+","-"))
+end
-local report_libraries = logs.reporter("resolvers","libraries")
-local gsub, insert = string.gsub, table.insert
-local unpack = unpack or table.unpack
+end -- of closure
-local resolvers, package = resolvers, package
+do -- create closure to overcome 200 locals limit
-local libformats = { 'luatexlibs', 'tex', 'texmfscripts', 'othertextfiles' } -- 'luainputs'
-local clibformats = { 'lib' }
+package.loaded["data-use"] = package.loaded["data-use"] or true
-local _path_, libpaths, _cpath_, clibpaths
+-- original size: 3913, stripped down to: 2998
-function package.libpaths()
- if not _path_ or package.path ~= _path_ then
- _path_ = package.path
- libpaths = file.splitpath(_path_,";")
- end
- return libpaths
+if not modules then modules={} end modules ['data-use']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local format,lower,gsub,find=string.format,string.lower,string.gsub,string.find
+local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end)
+local report_mounts=logs.reporter("resolvers","mounts")
+local resolvers=resolvers
+resolvers.automounted=resolvers.automounted or {}
+function resolvers.automount(usecache)
+ local mountpaths=resolvers.cleanpathlist(resolvers.expansion('TEXMFMOUNT'))
+ if (not mountpaths or #mountpaths==0) and usecache then
+ mountpaths=caches.getreadablepaths("mount")
+ end
+ if mountpaths and #mountpaths>0 then
+ statistics.starttiming(resolvers.instance)
+ for k=1,#mountpaths do
+ local root=mountpaths[k]
+ local f=io.open(root.."/url.tmi")
+ if f then
+ for line in f:lines() do
+ if line then
+ if find(line,"^[%%#%-]") then
+ elseif find(line,"^zip://") then
+ if trace_locating then
+ report_mounts("mounting %a",line)
+ end
+ table.insert(resolvers.automounted,line)
+ resolvers.usezipfile(line)
+ end
+ end
+ end
+ f:close()
+ end
+ end
+ statistics.stoptiming(resolvers.instance)
+ end
+end
+statistics.register("used config file",function() return caches.configfiles() end)
+statistics.register("used cache path",function() return caches.usedpaths() end)
+function statistics.savefmtstatus(texname,formatbanner,sourcefile)
+ local enginebanner=status.list().banner
+ if formatbanner and enginebanner and sourcefile then
+ local luvname=file.replacesuffix(texname,"luv")
+ local luvdata={
+ enginebanner=enginebanner,
+ formatbanner=formatbanner,
+ sourcehash=md5.hex(io.loaddata(resolvers.findfile(sourcefile)) or "unknown"),
+ sourcefile=sourcefile,
+ }
+ io.savedata(luvname,table.serialize(luvdata,true))
+ end
end
-
-function package.clibpaths()
- if not _cpath_ or package.cpath ~= _cpath_ then
- _cpath_ = package.cpath
- clibpaths = file.splitpath(_cpath_,";")
+function statistics.checkfmtstatus(texname)
+ local enginebanner=status.list().banner
+ if enginebanner and texname then
+ local luvname=file.replacesuffix(texname,"luv")
+ if lfs.isfile(luvname) then
+ local luv=dofile(luvname)
+ if luv and luv.sourcefile then
+ local sourcehash=md5.hex(io.loaddata(resolvers.findfile(luv.sourcefile)) or "unknown")
+ local luvbanner=luv.enginebanner or "?"
+ if luvbanner~=enginebanner then
+ return format("engine mismatch (luv: %s <> bin: %s)",luvbanner,enginebanner)
+ end
+ local luvhash=luv.sourcehash or "?"
+ if luvhash~=sourcehash then
+ return format("source mismatch (luv: %s <> bin: %s)",luvhash,sourcehash)
+ end
+ else
+ return "invalid status file"
+ end
+ else
+ return "missing status file"
end
- return clibpaths
+ end
+ return true
end
-local function thepath(...)
- local t = { ... } t[#t+1] = "?.lua"
- local path = file.join(unpack(t))
- if trace_locating then
- report_libraries("! appending '%s' to 'package.path'",path)
- end
- return path
-end
-local p_libpaths, a_libpaths = { }, { }
+end -- of closure
-function package.appendtolibpath(...)
- insert(a_libpath,thepath(...))
-end
+do -- create closure to overcome 200 locals limit
-function package.prependtolibpath(...)
- insert(p_libpaths,1,thepath(...))
-end
+package.loaded["data-zip"] = package.loaded["data-zip"] or true
--- beware, we need to return a loadfile result !
+-- original size: 8489, stripped down to: 6757
-local function loaded(libpaths,name,simple)
- for i=1,#libpaths do -- package.path, might become option
- local libpath = libpaths[i]
- local resolved = gsub(libpath,"%?",simple)
- if trace_locating then -- more detail
- report_libraries("! checking for '%s' on 'package.path': '%s' => '%s'",simple,libpath,resolved)
- end
- if file.is_readable(resolved) then
- if trace_locating then
- report_libraries("! lib '%s' located via 'package.path': '%s'",name,resolved)
- end
- return loadfile(resolved)
- end
+if not modules then modules={} end modules ['data-zip']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local format,find,match=string.format,string.find,string.match
+local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end)
+local report_zip=logs.reporter("resolvers","zip")
+local resolvers=resolvers
+zip=zip or {}
+local zip=zip
+zip.archives=zip.archives or {}
+local archives=zip.archives
+zip.registeredfiles=zip.registeredfiles or {}
+local registeredfiles=zip.registeredfiles
+local limited=false
+directives.register("system.inputmode",function(v)
+ if not limited then
+ local i_limiter=io.i_limiter(v)
+ if i_limiter then
+ zip.open=i_limiter.protect(zip.open)
+ limited=true
+ end
+ end
+end)
+local function validzip(str)
+ if not find(str,"^zip://") then
+ return "zip:///"..str
+ else
+ return str
+ end
+end
+function zip.openarchive(name)
+ if not name or name=="" then
+ return nil
+ else
+ local arch=archives[name]
+ if not arch then
+ local full=resolvers.findfile(name) or ""
+ arch=(full~="" and zip.open(full)) or false
+ archives[name]=arch
end
+ return arch
+ end
end
-
-package.loaders[2] = function(name) -- was [#package.loaders+1]
- if file.suffix(name) == "" then
- name = file.addsuffix(name,"lua") -- maybe a list
- if trace_locating then -- mode detail
- report_libraries("! locating '%s' with forced suffix",name)
- end
+function zip.closearchive(name)
+ if not name or (name=="" and archives[name]) then
+ zip.close(archives[name])
+ archives[name]=nil
+ end
+end
+function resolvers.locators.zip(specification)
+ local archive=specification.filename
+ local zipfile=archive and archive~="" and zip.openarchive(archive)
+ if trace_locating then
+ if zipfile then
+ report_zip("locator: archive %a found",archive)
else
- if trace_locating then -- mode detail
- report_libraries("! locating '%s'",name)
- end
+ report_zip("locator: archive %a not found",archive)
end
- for i=1,#libformats do
- local format = libformats[i]
- local resolved = resolvers.findfile(name,format) or ""
- if trace_locating then -- mode detail
- report_libraries("! checking for '%s' using 'libformat path': '%s'",name,format)
- end
- if resolved ~= "" then
- if trace_locating then
- report_libraries("! lib '%s' located via environment: '%s'",name,resolved)
- end
- return loadfile(resolved)
- end
- end
- -- libpaths
- local libpaths, clibpaths = package.libpaths(), package.clibpaths()
- local simple = gsub(name,"%.lua$","")
- local simple = gsub(simple,"%.","/")
- local resolved = loaded(p_libpaths,name,simple) or loaded(libpaths,name,simple) or loaded(a_libpaths,name,simple)
- if resolved then
- return resolved
- end
- --
- local libname = file.addsuffix(simple,os.libsuffix)
- for i=1,#clibformats do
- -- better have a dedicated loop
- local format = clibformats[i]
- local paths = resolvers.expandedpathlistfromvariable(format)
- for p=1,#paths do
- local path = paths[p]
- local resolved = file.join(path,libname)
- if trace_locating then -- mode detail
- report_libraries("! checking for '%s' using 'clibformat path': '%s'",libname,path)
- end
- if file.is_readable(resolved) then
- if trace_locating then
- report_libraries("! lib '%s' located via 'clibformat': '%s'",libname,resolved)
- end
- return package.loadlib(resolved,name)
- end
+ end
+end
+function resolvers.hashers.zip(specification)
+ local archive=specification.filename
+ if trace_locating then
+ report_zip("loading file %a",archive)
+ end
+ resolvers.usezipfile(specification.original)
+end
+function resolvers.concatinators.zip(zipfile,path,name)
+ if not path or path=="" then
+ return format('%s?name=%s',zipfile,name)
+ else
+ return format('%s?name=%s/%s',zipfile,path,name)
+ end
+end
+function resolvers.finders.zip(specification)
+ local original=specification.original
+ local archive=specification.filename
+ if archive then
+ local query=url.query(specification.query)
+ local queryname=query.name
+ if queryname then
+ local zfile=zip.openarchive(archive)
+ if zfile then
+ if trace_locating then
+ report_zip("finder: archive %a found",archive)
+ end
+ local dfile=zfile:open(queryname)
+ if dfile then
+ dfile=zfile:close()
+ if trace_locating then
+ report_zip("finder: file %a found",queryname)
+ end
+ return specification.original
+ elseif trace_locating then
+ report_zip("finder: file %a not found",queryname)
end
+ elseif trace_locating then
+ report_zip("finder: unknown archive %a",archive)
+ end
end
- for i=1,#clibpaths do -- package.path, might become option
- local libpath = clibpaths[i]
- local resolved = gsub(libpath,"?",simple)
- if trace_locating then -- more detail
- report_libraries("! checking for '%s' on 'package.cpath': '%s'",simple,libpath)
- end
- if file.is_readable(resolved) then
- if trace_locating then
- report_libraries("! lib '%s' located via 'package.cpath': '%s'",name,resolved)
- end
- return package.loadlib(resolved,name)
+ end
+ if trace_locating then
+ report_zip("finder: %a not found",original)
+ end
+ return resolvers.finders.notfound()
+end
+function resolvers.openers.zip(specification)
+ local original=specification.original
+ local archive=specification.filename
+ if archive then
+ local query=url.query(specification.query)
+ local queryname=query.name
+ if queryname then
+ local zfile=zip.openarchive(archive)
+ if zfile then
+ if trace_locating then
+ report_zip("opener; archive %a opened",archive)
+ end
+ local dfile=zfile:open(queryname)
+ if dfile then
+ if trace_locating then
+ report_zip("opener: file %a found",queryname)
+ end
+ return resolvers.openers.helpers.textopener('zip',original,dfile)
+ elseif trace_locating then
+ report_zip("opener: file %a not found",queryname)
end
+ elseif trace_locating then
+ report_zip("opener: unknown archive %a",archive)
+ end
end
- -- just in case the distribution is messed up
- if trace_loading then -- more detail
- report_libraries("! checking for '%s' using 'luatexlibs': '%s'",name)
- end
- local resolved = resolvers.findfile(file.basename(name),'luatexlibs') or ""
- if resolved ~= "" then
+ end
+ if trace_locating then
+ report_zip("opener: %a not found",original)
+ end
+ return resolvers.openers.notfound()
+end
+function resolvers.loaders.zip(specification)
+ local original=specification.original
+ local archive=specification.filename
+ if archive then
+ local query=url.query(specification.query)
+ local queryname=query.name
+ if queryname then
+ local zfile=zip.openarchive(archive)
+ if zfile then
if trace_locating then
- report_libraries("! lib '%s' located by basename via environment: '%s'",name,resolved)
+ report_zip("loader: archive %a opened",archive)
+ end
+ local dfile=zfile:open(queryname)
+ if dfile then
+ logs.show_load(original)
+ if trace_locating then
+ report_zip("loader; file %a loaded",original)
+ end
+ local s=dfile:read("*all")
+ dfile:close()
+ return true,s,#s
+ elseif trace_locating then
+ report_zip("loader: file %a not found",queryname)
end
- return loadfile(resolved)
+ elseif trace_locating then
+ report_zip("loader; unknown archive %a",archive)
+ end
end
- if trace_locating then
- report_libraries('? unable to locate lib: %s',name)
+ end
+ if trace_locating then
+ report_zip("loader: %a not found",original)
+ end
+ return resolvers.openers.notfound()
+end
+function resolvers.usezipfile(archive)
+ local specification=resolvers.splitmethod(archive)
+ local archive=specification.filename
+ if archive and not registeredfiles[archive] then
+ local z=zip.openarchive(archive)
+ if z then
+ local instance=resolvers.instance
+ local tree=url.query(specification.query).tree or ""
+ if trace_locating then
+ report_zip("registering: archive %a",archive)
+ end
+ statistics.starttiming(instance)
+ resolvers.prependhash('zip',archive)
+ resolvers.extendtexmfvariable(archive)
+ registeredfiles[archive]=z
+ instance.files[archive]=resolvers.registerzipfile(z,tree)
+ statistics.stoptiming(instance)
+ elseif trace_locating then
+ report_zip("registering: unknown archive %a",archive)
+ end
+ elseif trace_locating then
+ report_zip("registering: archive %a not found",archive)
+ end
+end
+function resolvers.registerzipfile(z,tree)
+ local files,filter={},""
+ if tree=="" then
+ filter="^(.+)/(.-)$"
+ else
+ filter=format("^%s/(.+)/(.-)$",tree)
+ end
+ if trace_locating then
+ report_zip("registering: using filter %a",filter)
+ end
+ local register,n=resolvers.registerfile,0
+ for i in z:files() do
+ local path,name=match(i.filename,filter)
+ if path then
+ if name and name~='' then
+ register(files,name,path)
+ n=n+1
+ else
+ end
+ else
+ register(files,i.filename,'')
+ n=n+1
end
--- return "unable to locate " .. name
+ end
+ report_zip("registering: %s files registered",n)
+ return files
end
-resolvers.loadlualib = require
--- -- -- --
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
-package.obsolete = package.obsolete or { }
+package.loaded["data-tre"] = package.loaded["data-tre"] or true
-package.append_libpath = appendtolibpath -- will become obsolete
-package.prepend_libpath = prependtolibpath -- will become obsolete
+-- original size: 2508, stripped down to: 2074
-package.obsolete.append_libpath = appendtolibpath -- will become obsolete
-package.obsolete.prepend_libpath = prependtolibpath -- will become obsolete
+if not modules then modules={} end modules ['data-tre']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local find,gsub,format=string.find,string.gsub,string.format
+local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end)
+local report_trees=logs.reporter("resolvers","trees")
+local resolvers=resolvers
+local done,found,notfound={},{},resolvers.finders.notfound
+function resolvers.finders.tree(specification)
+ local spec=specification.filename
+ local fnd=found[spec]
+ if fnd==nil then
+ if spec~="" then
+ local path,name=file.dirname(spec),file.basename(spec)
+ if path=="" then path="." end
+ local hash=done[path]
+ if not hash then
+ local pattern=path.."/*"
+ hash=dir.glob(pattern)
+ done[path]=hash
+ end
+ local pattern="/"..gsub(name,"([%.%-%+])","%%%1").."$"
+ for k=1,#hash do
+ local v=hash[k]
+ if find(v,pattern) then
+ found[spec]=v
+ return v
+ end
+ end
+ end
+ fnd=notfound()
+ found[spec]=fnd
+ end
+ return fnd
+end
+function resolvers.locators.tree(specification)
+ local name=specification.filename
+ local realname=resolvers.resolve(name)
+ if realname and realname~='' and lfs.isdir(realname) then
+ if trace_locating then
+ report_trees("locator %a found",realname)
+ end
+ resolvers.appendhash('tree',name,false)
+ elseif trace_locating then
+ report_trees("locator %a not found",name)
+ end
+end
+function resolvers.hashers.tree(specification)
+ local name=specification.filename
+ if trace_locating then
+ report_trees("analysing %a",name)
+ end
+ resolvers.methodhandler("hashers",name)
+ resolvers.generators.file(specification)
+end
+resolvers.concatinators.tree=resolvers.concatinators.file
+resolvers.generators.tree=resolvers.generators.file
+resolvers.openers.tree=resolvers.openers.file
+resolvers.loaders.tree=resolvers.loaders.file
end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['data-aux'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local find = string.find
-local type, next = type, next
-
-local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
+package.loaded["data-sch"] = package.loaded["data-sch"] or true
-local resolvers = resolvers
+-- original size: 6202, stripped down to: 5149
-local report_scripts = logs.reporter("resolvers","scripts")
-
-function resolvers.updatescript(oldname,newname) -- oldname -> own.name, not per se a suffix
- local scriptpath = "scripts/context/lua"
- newname = file.addsuffix(newname,"lua")
- local oldscript = resolvers.cleanpath(oldname)
- if trace_locating then
- report_scripts("to be replaced old script %s", oldscript)
- end
- local newscripts = resolvers.findfiles(newname) or { }
- if #newscripts == 0 then
- if trace_locating then
- report_scripts("unable to locate new script")
- end
+if not modules then modules={} end modules ['data-sch']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local load=load
+local gsub,concat,format=string.gsub,table.concat,string.format
+local finders,openers,loaders=resolvers.finders,resolvers.openers,resolvers.loaders
+local trace_schemes=false trackers.register("resolvers.schemes",function(v) trace_schemes=v end)
+local report_schemes=logs.reporter("resolvers","schemes")
+local http=require("socket.http")
+local ltn12=require("ltn12")
+local resolvers=resolvers
+local schemes=resolvers.schemes or {}
+resolvers.schemes=schemes
+local cleaners={}
+schemes.cleaners=cleaners
+local threshold=24*60*60
+directives.register("schemes.threshold",function(v) threshold=tonumber(v) or threshold end)
+function cleaners.none(specification)
+ return specification.original
+end
+function cleaners.strip(specification)
+ return (gsub(specification.original,"[^%a%d%.]+","-"))
+end
+function cleaners.md5(specification)
+ return file.addsuffix(md5.hex(specification.original),file.suffix(specification.path))
+end
+local cleaner=cleaners.strip
+directives.register("schemes.cleanmethod",function(v) cleaner=cleaners[v] or cleaners.strip end)
+function resolvers.schemes.cleanname(specification)
+ local hash=cleaner(specification)
+ if trace_schemes then
+ report_schemes("hashing %a to %a",specification.original,hash)
+ end
+ return hash
+end
+local cached,loaded,reused,thresholds,handlers={},{},{},{},{}
+local function runcurl(name,cachename)
+ local command="curl --silent --create-dirs --output "..cachename.." "..name
+ os.spawn(command)
+end
+local function fetch(specification)
+ local original=specification.original
+ local scheme=specification.scheme
+ local cleanname=schemes.cleanname(specification)
+ local cachename=caches.setfirstwritablefile(cleanname,"schemes")
+ if not cached[original] then
+ statistics.starttiming(schemes)
+ if not io.exists(cachename) or (os.difftime(os.time(),lfs.attributes(cachename).modification)>(thresholds[protocol] or threshold)) then
+ cached[original]=cachename
+ local handler=handlers[scheme]
+ if handler then
+ if trace_schemes then
+ report_schemes("fetching %a, protocol %a, method %a",original,scheme,"built-in")
+ end
+ logs.flush()
+ handler(specification,cachename)
+ else
+ if trace_schemes then
+ report_schemes("fetching %a, protocol %a, method %a",original,scheme,"curl")
+ end
+ logs.flush()
+ runcurl(original,cachename)
+ end
+ end
+ if io.exists(cachename) then
+ cached[original]=cachename
+ if trace_schemes then
+ report_schemes("using cached %a, protocol %a, cachename %a",original,scheme,cachename)
+ end
else
- for i=1,#newscripts do
- local newscript = resolvers.cleanpath(newscripts[i])
- if trace_locating then
- report_scripts("checking new script %s", newscript)
- end
- if oldscript == newscript then
- if trace_locating then
- report_scripts("old and new script are the same")
- end
- elseif not find(newscript,scriptpath) then
- if trace_locating then
- report_scripts("new script should come from %s",scriptpath)
- end
- elseif not (find(oldscript,file.removesuffix(newname).."$") or find(oldscript,newname.."$")) then
- if trace_locating then
- report_scripts("invalid new script name")
- end
- else
- local newdata = io.loaddata(newscript)
- if newdata then
- if trace_locating then
- report_scripts("old script content replaced by new content")
- end
- io.savedata(oldscript,newdata)
- break
- elseif trace_locating then
- report_scripts("unable to load new script")
- end
- end
- end
+ cached[original]=""
+ if trace_schemes then
+ report_schemes("using missing %a, protocol %a",original,scheme)
+ end
+ end
+ loaded[scheme]=loaded[scheme]+1
+ statistics.stoptiming(schemes)
+ else
+ if trace_schemes then
+ report_schemes("reusing %a, protocol %a",original,scheme)
+ end
+ reused[scheme]=reused[scheme]+1
+ end
+ return cached[original]
+end
+local function finder(specification,filetype)
+ return resolvers.methodhandler("finders",fetch(specification),filetype)
+end
+local opener=openers.file
+local loader=loaders.file
+local function install(scheme,handler,newthreshold)
+ handlers [scheme]=handler
+ loaded [scheme]=0
+ reused [scheme]=0
+ finders [scheme]=finder
+ openers [scheme]=opener
+ loaders [scheme]=loader
+ thresholds[scheme]=newthreshold or threshold
+end
+schemes.install=install
+local function http_handler(specification,cachename)
+ local tempname=cachename..".tmp"
+ local f=io.open(tempname,"wb")
+ local status,message=http.request {
+ url=specification.original,
+ sink=ltn12.sink.file(f)
+ }
+ if not status then
+ os.remove(tempname)
+ else
+ os.remove(cachename)
+ os.rename(tempname,cachename)
+ end
+ return cachename
+end
+install('http',http_handler)
+install('https')
+install('ftp')
+statistics.register("scheme handling time",function()
+ local l,r,nl,nr={},{},0,0
+ for k,v in table.sortedhash(loaded) do
+ if v>0 then
+ nl=nl+1
+ l[nl]=k..":"..v
+ end
+ end
+ for k,v in table.sortedhash(reused) do
+ if v>0 then
+ nr=nr+1
+ r[nr]=k..":"..v
+ end
+ end
+ local n=nl+nr
+ if n>0 then
+ l=nl>0 and concat(l) or "none"
+ r=nr>0 and concat(r) or "none"
+ return format("%s seconds, %s processed, threshold %s seconds, loaded: %s, reused: %s",
+ statistics.elapsedtime(schemes),n,threshold,l,r)
+ else
+ return nil
+ end
+end)
+local httprequest=http.request
+local toquery=url.toquery
+local function fetchstring(url,data)
+ local q=data and toquery(data)
+ if q then
+ url=url.."?"..q
+ end
+ local reply=httprequest(url)
+ return reply
+end
+schemes.fetchstring=fetchstring
+function schemes.fetchtable(url,data)
+ local reply=fetchstring(url,data)
+ if reply then
+ local s=load("return "..reply)
+ if s then
+ return s()
end
+ end
end
@@ -15312,78 +15069,198 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['data-tmf'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local resolvers = resolvers
+package.loaded["data-lua"] = package.loaded["data-lua"] or true
-local report_tds = logs.reporter("resolvers","tds")
+-- original size: 4861, stripped down to: 3693
--- = <<
--- ? ??
--- < +=
--- > =+
+if not modules then modules={} end modules ['data-lua']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local resolvers,package=resolvers,package
+local gsub=string.gsub
+local concat=table.concat
+local addsuffix=file.addsuffix
+local P,S,Cs,lpegmatch=lpeg.P,lpeg.S,lpeg.Cs,lpeg.match
+local libsuffixes={ 'tex','lua' }
+local clibsuffixes={ 'lib' }
+local libformats={ 'TEXINPUTS','LUAINPUTS' }
+local clibformats={ 'CLUAINPUTS' }
+local helpers=package.helpers
+trackers.register("resolvers.libraries",function(v) helpers.trace=v end)
+trackers.register("resolvers.locating",function(v) helpers.trace=v end)
+helpers.report=logs.reporter("resolvers","libraries")
+local pattern=Cs(P("!")^0/""*(P("/")*P(-1)/"/"+P("/")^1/"/"+1)^0)
+local function cleanpath(path)
+ return resolvers.resolve(lpegmatch(pattern,path))
+end
+helpers.cleanpath=cleanpath
+local loadedaslib=helpers.loadedaslib
+local loadedbylua=helpers.loadedbylua
+local loadedbypath=helpers.loadedbypath
+local notloaded=helpers.notloaded
+local getlibpaths=package.libpaths
+local getclibpaths=package.clibpaths
+function helpers.libpaths(libhash)
+ local libpaths={}
+ for i=1,#libformats do
+ local paths=resolvers.expandedpathlistfromvariable(libformats[i])
+ for i=1,#paths do
+ local path=cleanpath(paths[i])
+ if not libhash[path] then
+ libpaths[#libpaths+1]=path
+ libhash[path]=true
+ end
+ end
+ end
+ return libpaths
+end
+function helpers.clibpaths(clibhash)
+ local clibpaths={}
+ for i=1,#clibformats do
+ local paths=resolvers.expandedpathlistfromvariable(clibformats[i])
+ for i=1,#paths do
+ local path=cleanpath(paths[i])
+ if not clibhash[path] then
+ clibpaths[#clibpaths+1]=path
+ clibhash[path]=true
+ end
+ end
+ end
+ return clibpaths
+end
+local function loadedbyformat(name,rawname,suffixes,islib)
+ local trace=helpers.trace
+ local report=helpers.report
+ if trace then
+ report("locating %a as %a using formats %a",rawname,name,suffixes)
+ end
+ for i=1,#suffixes do
+ local format=suffixes[i]
+ local resolved=resolvers.findfile(name,format) or ""
+ if trace then
+ report("checking %a using format %a",name,format)
+ end
+ if resolved~="" then
+ if trace then
+ report("lib %a located on %a",name,resolved)
+ end
+ if islib then
+ return true,loadedaslib(resolved,rawname)
+ else
+ return true,loadfile(resolved)
+ end
+ end
+ end
+end
+helpers.loadedbyformat=loadedbyformat
+local pattern=Cs((((1-S("\\/"))^0*(S("\\/")^1/"/"))^0*(P(".")^1/"/"+P(1))^1)*-1)
+local function lualibfile(name)
+ return lpegmatch(pattern,name) or name
+end
+helpers.lualibfile=lualibfile
+function helpers.loaded(name)
+ local thename=lualibfile(name)
+ local luaname=addsuffix(thename,"lua")
+ local libname=addsuffix(thename,os.libsuffix)
+ local libpaths=getlibpaths()
+ local clibpaths=getclibpaths()
+ local done,result=loadedbyformat(luaname,name,libsuffixes,false)
+ if done then
+ return result
+ end
+ local done,result=loadedbyformat(libname,name,clibsuffixes,true)
+ if done then
+ return result
+ end
+ local done,result=loadedbypath(luaname,name,libpaths,false,"lua")
+ if done then
+ return result
+ end
+ local done,result=loadedbypath(luaname,name,clibpaths,false,"lua")
+ if done then
+ return result
+ end
+ local done,result=loadedbypath(libname,name,clibpaths,true,"lib")
+ if done then
+ return result
+ end
+ local done,result=loadedbylua(name)
+ if done then
+ return result
+ end
+ return notloaded(name)
+end
+resolvers.loadlualib=require
-function resolvers.load_tree(tree,resolve)
- if type(tree) == "string" and tree ~= "" then
- local getenv, setenv = resolvers.getenv, resolvers.setenv
+end -- of closure
- -- later might listen to the raw osenv var as well
- local texos = "texmf-" .. os.platform
+do -- create closure to overcome 200 locals limit
- local oldroot = environment.texroot
- local newroot = file.collapsepath(tree)
+package.loaded["data-aux"] = package.loaded["data-aux"] or true
- local newtree = file.join(newroot,texos)
- local newpath = file.join(newtree,"bin")
+-- original size: 2394, stripped down to: 2005
- if not lfs.isdir(newtree) then
- report_tds("no '%s' under tree %s",texos,tree)
- os.exit()
+if not modules then modules={} end modules ['data-aux']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local find=string.find
+local type,next=type,next
+local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end)
+local resolvers=resolvers
+local report_scripts=logs.reporter("resolvers","scripts")
+function resolvers.updatescript(oldname,newname)
+ local scriptpath="scripts/context/lua"
+ newname=file.addsuffix(newname,"lua")
+ local oldscript=resolvers.cleanpath(oldname)
+ if trace_locating then
+ report_scripts("to be replaced old script %a",oldscript)
+ end
+ local newscripts=resolvers.findfiles(newname) or {}
+ if #newscripts==0 then
+ if trace_locating then
+ report_scripts("unable to locate new script")
+ end
+ else
+ for i=1,#newscripts do
+ local newscript=resolvers.cleanpath(newscripts[i])
+ if trace_locating then
+ report_scripts("checking new script %a",newscript)
+ end
+ if oldscript==newscript then
+ if trace_locating then
+ report_scripts("old and new script are the same")
end
- if not lfs.isdir(newpath) then
- report_tds("no '%s/bin' under tree %s",texos,tree)
- os.exit()
+ elseif not find(newscript,scriptpath) then
+ if trace_locating then
+ report_scripts("new script should come from %a",scriptpath)
end
-
- local texmfos = newtree
-
- environment.texroot = newroot
- environment.texos = texos
- environment.texmfos = texmfos
-
- -- Beware, we need to obey the relocatable autoparent so we
- -- set TEXMFCNF to its raw value. This is somewhat tricky when
- -- we run a mkii job from within. Therefore, in mtxrun, there
- -- is a resolve applied when we're in mkii/kpse mode or when
- -- --resolve is passed to mtxrun. Maybe we should also set the
- -- local AUTOPARENT etc. although these are alwasy set new.
-
- if resolve then
- -- resolvers.luacnfspec = resolvers.joinpath(resolvers.resolve(resolvers.expandedpathfromlist(resolvers.splitpath(resolvers.luacnfspec))))
- resolvers.luacnfspec = resolvers.resolve(resolvers.luacnfspec)
+ elseif not (find(oldscript,file.removesuffix(newname).."$") or find(oldscript,newname.."$")) then
+ if trace_locating then
+ report_scripts("invalid new script name")
+ end
+ else
+ local newdata=io.loaddata(newscript)
+ if newdata then
+ if trace_locating then
+ report_scripts("old script content replaced by new content")
+ end
+ io.savedata(oldscript,newdata)
+ break
+ elseif trace_locating then
+ report_scripts("unable to load new script")
end
-
- setenv('SELFAUTOPARENT', newroot)
- setenv('SELFAUTODIR', newtree)
- setenv('SELFAUTOLOC', newpath)
- setenv('TEXROOT', newroot)
- setenv('TEXOS', texos)
- setenv('TEXMFOS', texmfos)
- setenv('TEXMFCNF', resolvers.luacnfspec,true) -- already resolved
- setenv('PATH', newpath .. io.pathseparator .. getenv('PATH'))
-
- report_tds("changing from root '%s' to '%s'",oldroot,newroot)
- report_tds("prepending '%s' to PATH",newpath)
- report_tds("setting TEXMFCNF to '%s'",resolvers.luacnfspec)
- report_tds()
+ end
end
+ end
end
@@ -15391,81 +15268,132 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['data-lst'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
+package.loaded["data-tmf"] = package.loaded["data-tmf"] or true
+
+-- original size: 2600, stripped down to: 1627
+
+if not modules then modules={} end modules ['data-tmf']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
}
+local resolvers=resolvers
+local report_tds=logs.reporter("resolvers","tds")
+function resolvers.load_tree(tree,resolve)
+ if type(tree)=="string" and tree~="" then
+ local getenv,setenv=resolvers.getenv,resolvers.setenv
+ local texos="texmf-"..os.platform
+ local oldroot=environment.texroot
+ local newroot=file.collapsepath(tree)
+ local newtree=file.join(newroot,texos)
+ local newpath=file.join(newtree,"bin")
+ if not lfs.isdir(newtree) then
+ report_tds("no %a under tree %a",texos,tree)
+ os.exit()
+ end
+ if not lfs.isdir(newpath) then
+ report_tds("no '%s/bin' under tree %a",texos,tree)
+ os.exit()
+ end
+ local texmfos=newtree
+ environment.texroot=newroot
+ environment.texos=texos
+ environment.texmfos=texmfos
+ if resolve then
+ resolvers.luacnfspec=resolvers.resolve(resolvers.luacnfspec)
+ end
+ setenv('SELFAUTOPARENT',newroot)
+ setenv('SELFAUTODIR',newtree)
+ setenv('SELFAUTOLOC',newpath)
+ setenv('TEXROOT',newroot)
+ setenv('TEXOS',texos)
+ setenv('TEXMFOS',texmfos)
+ setenv('TEXMFCNF',resolvers.luacnfspec,true)
+ setenv('PATH',newpath..io.pathseparator..getenv('PATH'))
+ report_tds("changing from root %a to %a",oldroot,newroot)
+ report_tds("prepending %a to PATH",newpath)
+ report_tds("setting TEXMFCNF to %a",resolvers.luacnfspec)
+ report_tds()
+ end
+end
--- used in mtxrun, can be loaded later .. todo
-local find, concat, upper, format = string.find, table.concat, string.upper, string.format
-local fastcopy, sortedpairs = table.fastcopy, table.sortedpairs
+end -- of closure
-resolvers.listers = resolvers.listers or { }
+do -- create closure to overcome 200 locals limit
-local resolvers = resolvers
+package.loaded["data-lst"] = package.loaded["data-lst"] or true
-local report_lists = logs.reporter("resolvers","lists")
+-- original size: 2654, stripped down to: 2301
+if not modules then modules={} end modules ['data-lst']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local find,concat,upper,format=string.find,table.concat,string.upper,string.format
+local fastcopy,sortedpairs=table.fastcopy,table.sortedpairs
+resolvers.listers=resolvers.listers or {}
+local resolvers=resolvers
+local report_lists=logs.reporter("resolvers","lists")
local function tabstr(str)
- if type(str) == 'table' then
- return concat(str," | ")
- else
- return str
- end
+ if type(str)=='table' then
+ return concat(str," | ")
+ else
+ return str
+ end
end
-
function resolvers.listers.variables(pattern)
- local instance = resolvers.instance
- local environment = instance.environment
- local variables = instance.variables
- local expansions = instance.expansions
- local pattern = upper(pattern or "")
- local configured = { }
- local order = instance.order
- for i=1,#order do
- for k, v in next, order[i] do
- if v ~= nil and configured[k] == nil then
- configured[k] = v
- end
- end
- end
- local env = fastcopy(environment)
- local var = fastcopy(variables)
- local exp = fastcopy(expansions)
- for key, value in sortedpairs(configured) do
- if key ~= "" and (pattern == "" or find(upper(key),pattern)) then
- report_lists(key)
- report_lists(" env: %s",tabstr(rawget(environment,key)) or "unset")
- report_lists(" var: %s",tabstr(configured[key]) or "unset")
- report_lists(" exp: %s",tabstr(expansions[key]) or "unset")
- report_lists(" res: %s",tabstr(resolvers.resolve(expansions[key])) or "unset")
- end
- end
- instance.environment = fastcopy(env)
- instance.variables = fastcopy(var)
- instance.expansions = fastcopy(exp)
-end
-
-function resolvers.listers.configurations(report)
- local configurations = resolvers.instance.specification
- local report = report or texio.write_nl
- for i=1,#configurations do
- report(format("file : %s",resolvers.resolve(configurations[i])))
- end
- report("")
- local list = resolvers.expandedpathfromlist(resolvers.splitpath(resolvers.luacnfspec))
- for i=1,#list do
- local li = resolvers.resolve(list[i])
- if lfs.isdir(li) then
- report(format("path - %s",li))
- else
- report(format("path + %s",li))
- end
+ local instance=resolvers.instance
+ local environment=instance.environment
+ local variables=instance.variables
+ local expansions=instance.expansions
+ local pattern=upper(pattern or "")
+ local configured={}
+ local order=instance.order
+ for i=1,#order do
+ for k,v in next,order[i] do
+ if v~=nil and configured[k]==nil then
+ configured[k]=v
+ end
+ end
+ end
+ local env=fastcopy(environment)
+ local var=fastcopy(variables)
+ local exp=fastcopy(expansions)
+ for key,value in sortedpairs(configured) do
+ if key~="" and (pattern=="" or find(upper(key),pattern)) then
+ report_lists(key)
+ report_lists(" env: %s",tabstr(rawget(environment,key)) or "unset")
+ report_lists(" var: %s",tabstr(configured[key]) or "unset")
+ report_lists(" exp: %s",tabstr(expansions[key]) or "unset")
+ report_lists(" res: %s",tabstr(resolvers.resolve(expansions[key])) or "unset")
+ end
+ end
+ instance.environment=fastcopy(env)
+ instance.variables=fastcopy(var)
+ instance.expansions=fastcopy(exp)
+end
+local report_resolved=logs.reporter("system","resolved")
+function resolvers.listers.configurations()
+ local configurations=resolvers.instance.specification
+ for i=1,#configurations do
+ report_resolved("file : %s",resolvers.resolve(configurations[i]))
+ end
+ report_resolved("")
+ local list=resolvers.expandedpathfromlist(resolvers.splitpath(resolvers.luacnfspec))
+ for i=1,#list do
+ local li=resolvers.resolve(list[i])
+ if lfs.isdir(li) then
+ report_resolved("path - %s",li)
+ else
+ report_resolved("path + %s",li)
end
+ end
end
@@ -15473,279 +15401,407 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['luat-sta'] = {
- version = 1.001,
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
+package.loaded["util-lib"] = package.loaded["util-lib"] or true
--- this code is used in the updater
+-- original size: 8911, stripped down to: 4216
-local gmatch, match = string.gmatch, string.match
-local type = type
+if not modules then modules={} end modules ['util-lib']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files",
+}
+local gsub,find=string.gsub,string.find
+local pathpart,nameonly,joinfile=file.pathpart,file.nameonly,file.join
+local findfile,findfiles=resolvers and resolvers.findfile,resolvers and resolvers.findfiles
+local loaded=package.loaded
+local report_swiglib=logs.reporter("swiglib")
+local trace_swiglib=false trackers.register("resolvers.swiglib",function(v) trace_swiglib=v end)
+local function requireswiglib(required,version)
+ local library=loaded[required]
+ if library==nil then
+ local required_full=gsub(required,"%.","/")
+ local required_path=pathpart(required_full)
+ local required_base=nameonly(required_full)
+ local required_name=required_base.."."..os.libsuffix
+ local version=type(version)=="string" and version~="" and version or false
+ local function check(locate,...)
+ local found_library=nil
+ if version then
+ local asked_library=joinfile(required_path,version,required_name)
+ if trace_swiglib then
+ report_swiglib("checking %s: %a","with version",asked_library)
+ end
+ found_library=locate(asked_library,...)
+ if not found_library or found_library==""then
+ asked_library=joinfile(required_path,required_name)
+ if trace_swiglib then
+ report_swiglib("checking %s: %a","without version",asked_library)
+ end
+ found_library=locate(asked_library,...)
+ end
+ else
+ local asked_library=joinfile(required_path,required_name)
+ if trace_swiglib then
+ report_swiglib("checking %s: %a","without version",asked_library)
+ end
+ found_library=locate(asked_library,...)
+ end
+ return found_library and found_library~="" and found_library or false
+ end
+ local found_library=findfile and check(findfile,"lib")
+ if findfiles and not found_library then
+ local asked_library=joinfile(required_path,".*",required_name)
+ if trace_swiglib then
+ report_swiglib("checking %s: %a","latest version",asked_library)
+ end
+ local list=findfiles(asked_library,"lib",true)
+ if list and #list>0 then
+ table.sort(list)
+ found_library=list[#list]
+ end
+ end
+ if not found_library then
+ package.extraclibpath(environment.ownpath)
+ local paths=package.clibpaths()
+ for i=1,#paths do
+ local found_library=check(lfs.isfile)
+ if found_library then
+ break
+ end
+ end
+ end
+ if not found_library then
+ if trace_swiglib then
+ report_swiglib("not found: %a",asked_library)
+ end
+ library=false
+ else
+ local path=pathpart(found_library)
+ local base=nameonly(found_library)
+ dir.push(path)
+ if trace_swiglib then
+ report_swiglib("found: %a",found_library)
+ end
+ library=package.loadlib(found_library,"luaopen_"..required_base)
+ if type(library)=="function" then
+ library=library()
+ else
+ library=false
+ end
+ dir.pop()
+ end
+ if not library then
+ report_swiglib("unknown: %a",required)
+ elseif trace_swiglib then
+ report_swiglib("stored: %a",required)
+ end
+ loaded[required]=library
+ else
+ report_swiglib("reused: %a",required)
+ end
+ return library
+end
+local savedrequire=require
+function require(name,version)
+ if find(name,"^swiglib%.") then
+ return requireswiglib(name,version)
+ else
+ return savedrequire(name)
+ end
+end
+local swiglibs={}
+function swiglib(name,version)
+ local library=swiglibs[name]
+ if not library then
+ statistics.starttiming(swiglibs)
+ report_swiglib("loading %a",name)
+ library=requireswiglib("swiglib."..name,version)
+ swiglibs[name]=library
+ statistics.stoptiming(swiglibs)
+ end
+ return library
+end
+statistics.register("used swiglibs",function()
+ if next(swiglibs) then
+ return string.format("%s, initial load time %s seconds",table.concat(table.sortedkeys(swiglibs)," "),statistics.elapsedtime(swiglibs))
+ end
+end)
-states = states or { }
-local states = states
-states.data = states.data or { }
-local data = states.data
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
-states.hash = states.hash or { }
-local hash = states.hash
+package.loaded["luat-sta"] = package.loaded["luat-sta"] or true
-states.tag = states.tag or ""
-states.filename = states.filename or ""
+-- original size: 5703, stripped down to: 2507
+if not modules then modules={} end modules ['luat-sta']={
+ version=1.001,
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local gmatch,match=string.gmatch,string.match
+local type=type
+states=states or {}
+local states=states
+states.data=states.data or {}
+local data=states.data
+states.hash=states.hash or {}
+local hash=states.hash
+states.tag=states.tag or ""
+states.filename=states.filename or ""
function states.save(filename,tag)
- tag = tag or states.tag
- filename = file.addsuffix(filename or states.filename,'lus')
- io.savedata(filename,
- "-- generator : luat-sta.lua\n" ..
- "-- state tag : " .. tag .. "\n\n" ..
- table.serialize(data[tag or states.tag] or {},true)
- )
+ tag=tag or states.tag
+ filename=file.addsuffix(filename or states.filename,'lus')
+ io.savedata(filename,
+ "-- generator : luat-sta.lua\n".."-- state tag : "..tag.."\n\n"..table.serialize(data[tag or states.tag] or {},true)
+ )
end
-
function states.load(filename,tag)
- states.filename = filename
- states.tag = tag or "whatever"
- states.filename = file.addsuffix(states.filename,'lus')
- data[states.tag], hash[states.tag] = (io.exists(filename) and dofile(filename)) or { }, { }
+ states.filename=filename
+ states.tag=tag or "whatever"
+ states.filename=file.addsuffix(states.filename,'lus')
+ data[states.tag],hash[states.tag]=(io.exists(filename) and dofile(filename)) or {},{}
end
-
local function set_by_tag(tag,key,value,default,persistent)
- local d, h = data[tag], hash[tag]
- if d then
- if type(d) == "table" then
- local dkey, hkey = key, key
- local pre, post = match(key,"(.+)%.([^%.]+)$")
- if pre and post then
- for k in gmatch(pre,"[^%.]+") do
- local dk = d[k]
- if not dk then
- dk = { }
- d[k] = dk
- elseif type(dk) == "string" then
- -- invalid table, unable to upgrade structure
- -- hope for the best or delete the state file
- break
- end
- d = dk
- end
- dkey, hkey = post, key
- end
- if value == nil then
- value = default
- elseif value == false then
- -- special case
- elseif persistent then
- value = value or d[dkey] or default
- else
- value = value or default
- end
- d[dkey], h[hkey] = value, value
- elseif type(d) == "string" then
- -- weird
- data[tag], hash[tag] = value, value
- end
- end
+ local d,h=data[tag],hash[tag]
+ if d then
+ if type(d)=="table" then
+ local dkey,hkey=key,key
+ local pre,post=match(key,"(.+)%.([^%.]+)$")
+ if pre and post then
+ for k in gmatch(pre,"[^%.]+") do
+ local dk=d[k]
+ if not dk then
+ dk={}
+ d[k]=dk
+ elseif type(dk)=="string" then
+ break
+ end
+ d=dk
+ end
+ dkey,hkey=post,key
+ end
+ if value==nil then
+ value=default
+ elseif value==false then
+ elseif persistent then
+ value=value or d[dkey] or default
+ else
+ value=value or default
+ end
+ d[dkey],h[hkey]=value,value
+ elseif type(d)=="string" then
+ data[tag],hash[tag]=value,value
+ end
+ end
end
-
local function get_by_tag(tag,key,default)
- local h = hash[tag]
- if h and h[key] then
- return h[key]
- else
- local d = data[tag]
- if d then
- for k in gmatch(key,"[^%.]+") do
- local dk = d[k]
- if dk ~= nil then
- d = dk
- else
- return default
- end
- end
- if d == false then
- return false
- else
- return d or default
- end
+ local h=hash[tag]
+ if h and h[key] then
+ return h[key]
+ else
+ local d=data[tag]
+ if d then
+ for k in gmatch(key,"[^%.]+") do
+ local dk=d[k]
+ if dk~=nil then
+ d=dk
+ else
+ return default
end
+ end
+ if d==false then
+ return false
+ else
+ return d or default
+ end
end
+ end
end
-
-states.set_by_tag = set_by_tag
-states.get_by_tag = get_by_tag
-
+states.set_by_tag=set_by_tag
+states.get_by_tag=get_by_tag
function states.set(key,value,default,persistent)
- set_by_tag(states.tag,key,value,default,persistent)
+ set_by_tag(states.tag,key,value,default,persistent)
end
-
function states.get(key,default)
- return get_by_tag(states.tag,key,default)
+ return get_by_tag(states.tag,key,default)
end
-
-
-
end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['luat-fmt'] = {
- version = 1.001,
- comment = "companion to mtxrun",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-
-local format = string.format
-
-local report_format = logs.reporter("resolvers","formats")
-
--- helper for mtxrun
+package.loaded["luat-fmt"] = package.loaded["luat-fmt"] or true
-local quoted = string.quoted
+-- original size: 5951, stripped down to: 4922
-local function primaryflags() -- not yet ok
- local trackers = environment.argument("trackers")
- local directives = environment.argument("directives")
- local flags = ""
- if trackers and trackers ~= "" then
- flags = flags .. "--trackers=" .. quoted(trackers)
- end
- if directives and directives ~= "" then
- flags = flags .. "--directives=" .. quoted(directives)
- end
- return flags
+if not modules then modules={} end modules ['luat-fmt']={
+ version=1.001,
+ comment="companion to mtxrun",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local format=string.format
+local concat=table.concat
+local quoted=string.quoted
+local luasuffixes=utilities.lua.suffixes
+local report_format=logs.reporter("resolvers","formats")
+local function primaryflags()
+ local trackers=environment.argument("trackers")
+ local directives=environment.argument("directives")
+ local flags={}
+ if trackers and trackers~="" then
+ flags={ "--trackers="..quoted(trackers) }
+ end
+ if directives and directives~="" then
+ flags={ "--directives="..quoted(directives) }
+ end
+ if environment.argument("jit") then
+ flags={ "--jiton" }
+ end
+ return concat(flags," ")
end
-
function environment.make_format(name)
- -- change to format path (early as we need expanded paths)
- local olddir = lfs.currentdir()
- local path = caches.getwritablepath("formats") or "" -- maybe platform
- if path ~= "" then
- lfs.chdir(path)
- end
- report_format("format path: %s",lfs.currentdir())
- -- check source file
- local texsourcename = file.addsuffix(name,"mkiv")
- local fulltexsourcename = resolvers.findfile(texsourcename,"tex") or ""
- if fulltexsourcename == "" then
- texsourcename = file.addsuffix(name,"tex")
- fulltexsourcename = resolvers.findfile(texsourcename,"tex") or ""
- end
- if fulltexsourcename == "" then
- report_format("no tex source file with name: %s (mkiv or tex)",name)
- lfs.chdir(olddir)
- return
- else
- report_format("using tex source file: %s",fulltexsourcename)
- end
- local texsourcepath = dir.expandname(file.dirname(fulltexsourcename)) -- really needed
- -- check specification
- local specificationname = file.replacesuffix(fulltexsourcename,"lus")
- local fullspecificationname = resolvers.findfile(specificationname,"tex") or ""
- if fullspecificationname == "" then
- specificationname = file.join(texsourcepath,"context.lus")
- fullspecificationname = resolvers.findfile(specificationname,"tex") or ""
- end
- if fullspecificationname == "" then
- report_format("unknown stub specification: %s",specificationname)
- lfs.chdir(olddir)
- return
- end
- local specificationpath = file.dirname(fullspecificationname)
- -- load specification
- local usedluastub = nil
- local usedlualibs = dofile(fullspecificationname)
- if type(usedlualibs) == "string" then
- usedluastub = file.join(file.dirname(fullspecificationname),usedlualibs)
- elseif type(usedlualibs) == "table" then
- report_format("using stub specification: %s",fullspecificationname)
- local texbasename = file.basename(name)
- local luastubname = file.addsuffix(texbasename,"lua")
- local lucstubname = file.addsuffix(texbasename,"luc")
- -- pack libraries in stub
- report_format("creating initialization file: %s",luastubname)
- utilities.merger.selfcreate(usedlualibs,specificationpath,luastubname)
- -- compile stub file (does not save that much as we don't use this stub at startup any more)
- local strip = resolvers.booleanvariable("LUACSTRIP", true)
- if utilities.lua.compile(luastubname,lucstubname) and lfs.isfile(lucstubname) then
- report_format("using compiled initialization file: %s",lucstubname)
- usedluastub = lucstubname
- else
- report_format("using uncompiled initialization file: %s",luastubname)
- usedluastub = luastubname
- end
+ local engine=environment.ownmain or "luatex"
+ local olddir=dir.current()
+ local path=caches.getwritablepath("formats",engine) or ""
+ if path~="" then
+ lfs.chdir(path)
+ end
+ report_format("using format path %a",dir.current())
+ local texsourcename=file.addsuffix(name,"mkiv")
+ local fulltexsourcename=resolvers.findfile(texsourcename,"tex") or ""
+ if fulltexsourcename=="" then
+ texsourcename=file.addsuffix(name,"tex")
+ fulltexsourcename=resolvers.findfile(texsourcename,"tex") or ""
+ end
+ if fulltexsourcename=="" then
+ report_format("no tex source file with name %a (mkiv or tex)",name)
+ lfs.chdir(olddir)
+ return
+ else
+ report_format("using tex source file %a",fulltexsourcename)
+ end
+ local texsourcepath=dir.expandname(file.dirname(fulltexsourcename))
+ local specificationname=file.replacesuffix(fulltexsourcename,"lus")
+ local fullspecificationname=resolvers.findfile(specificationname,"tex") or ""
+ if fullspecificationname=="" then
+ specificationname=file.join(texsourcepath,"context.lus")
+ fullspecificationname=resolvers.findfile(specificationname,"tex") or ""
+ end
+ if fullspecificationname=="" then
+ report_format("unknown stub specification %a",specificationname)
+ lfs.chdir(olddir)
+ return
+ end
+ local specificationpath=file.dirname(fullspecificationname)
+ local usedluastub=nil
+ local usedlualibs=dofile(fullspecificationname)
+ if type(usedlualibs)=="string" then
+ usedluastub=file.join(file.dirname(fullspecificationname),usedlualibs)
+ elseif type(usedlualibs)=="table" then
+ report_format("using stub specification %a",fullspecificationname)
+ local texbasename=file.basename(name)
+ local luastubname=file.addsuffix(texbasename,luasuffixes.lua)
+ local lucstubname=file.addsuffix(texbasename,luasuffixes.luc)
+ report_format("creating initialization file %a",luastubname)
+ utilities.merger.selfcreate(usedlualibs,specificationpath,luastubname)
+ if utilities.lua.compile(luastubname,lucstubname) and lfs.isfile(lucstubname) then
+ report_format("using compiled initialization file %a",lucstubname)
+ usedluastub=lucstubname
else
- report_format("invalid stub specification: %s",fullspecificationname)
- lfs.chdir(olddir)
- return
- end
- -- generate format
- local command = format("luatex --ini %s --lua=%s %s %sdump",primaryflags(),quoted(usedluastub),quoted(fulltexsourcename),os.platform == "unix" and "\\\\" or "\\")
- report_format("running command: %s\n",command)
- os.spawn(command)
- -- remove related mem files
- local pattern = file.removesuffix(file.basename(usedluastub)).."-*.mem"
- -- report_format("removing related mplib format with pattern '%s'", pattern)
- local mp = dir.glob(pattern)
- if mp then
- for i=1,#mp do
- local name = mp[i]
- report_format("removing related mplib format %s", file.basename(name))
- os.remove(name)
- end
+ report_format("using uncompiled initialization file %a",luastubname)
+ usedluastub=luastubname
end
+ else
+ report_format("invalid stub specification %a",fullspecificationname)
lfs.chdir(olddir)
+ return
+ end
+ local command=format("%s --ini %s --lua=%s %s %sdump",engine,primaryflags(),quoted(usedluastub),quoted(fulltexsourcename),os.platform=="unix" and "\\\\" or "\\")
+ report_format("running command: %s\n",command)
+ os.spawn(command)
+ local pattern=file.removesuffix(file.basename(usedluastub)).."-*.mem"
+ local mp=dir.glob(pattern)
+ if mp then
+ for i=1,#mp do
+ local name=mp[i]
+ report_format("removing related mplib format %a",file.basename(name))
+ os.remove(name)
+ end
+ end
+ lfs.chdir(olddir)
end
-
function environment.run_format(name,data,more)
- -- hm, rather old code here; we can now use the file.whatever functions
- if name and name ~= "" then
- local barename = file.removesuffix(name)
- local fmtname = caches.getfirstreadablefile(file.addsuffix(barename,"fmt"),"formats")
- if fmtname == "" then
- fmtname = resolvers.findfile(file.addsuffix(barename,"fmt")) or ""
- end
- fmtname = resolvers.cleanpath(fmtname)
- if fmtname == "" then
- report_format("no format with name: %s",name)
- else
- local barename = file.removesuffix(name) -- expanded name
- local luaname = file.addsuffix(barename,"luc")
- if not lfs.isfile(luaname) then
- luaname = file.addsuffix(barename,"lua")
- end
- if not lfs.isfile(luaname) then
- report_format("using format name: %s",fmtname)
- report_format("no luc/lua with name: %s",barename)
- else
- local command = format("luatex %s --fmt=%s --lua=%s %s %s",primaryflags(),quoted(barename),quoted(luaname),quoted(data),more ~= "" and quoted(more) or "")
- report_format("running command: %s",command)
- os.spawn(command)
- end
- end
+ if name and name~="" then
+ local engine=environment.ownmain or "luatex"
+ local barename=file.removesuffix(name)
+ local fmtname=caches.getfirstreadablefile(file.addsuffix(barename,"fmt"),"formats",engine)
+ if fmtname=="" then
+ fmtname=resolvers.findfile(file.addsuffix(barename,"fmt")) or ""
+ end
+ fmtname=resolvers.cleanpath(fmtname)
+ if fmtname=="" then
+ report_format("no format with name %a",name)
+ else
+ local barename=file.removesuffix(name)
+ local luaname=file.addsuffix(barename,"luc")
+ if not lfs.isfile(luaname) then
+ luaname=file.addsuffix(barename,"lua")
+ end
+ if not lfs.isfile(luaname) then
+ report_format("using format name %a",fmtname)
+ report_format("no luc/lua file with name %a",barename)
+ else
+ local command=format("%s %s --fmt=%s --lua=%s %s %s",engine,primaryflags(),quoted(barename),quoted(luaname),quoted(data),more~="" and quoted(more) or "")
+ report_format("running command: %s",command)
+ os.spawn(command)
+ end
end
+ end
end
end -- of closure
+
+-- used libraries : l-lua.lua l-lpeg.lua l-function.lua l-string.lua l-table.lua l-io.lua l-number.lua l-set.lua l-os.lua l-file.lua l-md5.lua l-url.lua l-dir.lua l-boolean.lua l-unicode.lua l-math.lua util-str.lua util-tab.lua util-sto.lua util-prs.lua util-fmt.lua trac-set.lua trac-log.lua trac-inf.lua trac-pro.lua util-lua.lua util-deb.lua util-mrg.lua util-tpl.lua util-env.lua luat-env.lua lxml-tab.lua lxml-lpt.lua lxml-mis.lua lxml-aux.lua lxml-xml.lua trac-xml.lua data-ini.lua data-exp.lua data-env.lua data-tmp.lua data-met.lua data-res.lua data-pre.lua data-inp.lua data-out.lua data-fil.lua data-con.lua data-use.lua data-zip.lua data-tre.lua data-sch.lua data-lua.lua data-aux.lua data-tmf.lua data-lst.lua util-lib.lua luat-sta.lua luat-fmt.lua
+-- skipped libraries : -
+-- original bytes : 658276
+-- stripped bytes : 241564
+
-- end library merge
-own = { } -- not local, might change
+-- We need this hack till luatex is fixed.
+--
+-- for k,v in pairs(arg) do print(k,v) end
+
+if arg and (arg[0] == 'luatex' or arg[0] == 'luatex.exe') and arg[1] == "--luaonly" then
+ arg[-1]=arg[0] arg[0]=arg[2] for k=3,#arg do arg[k-2]=arg[k] end arg[#arg]=nil arg[#arg]=nil
+end
+
+-- End of hack.
+
+local format, gsub, gmatch, match, find = string.format, string.gsub, string.gmatch, string.match, string.find
+local concat = table.concat
+
+local ownname = environment and environment.ownname or arg[0] or 'mtxrun.lua'
+local ownpath = gsub(match(ownname,"^(.+)[\\/].-$") or ".","\\","/")
+local owntree = environment and environment.ownpath or ownpath
-own.libs = { -- order can be made better
+local ownlibs = { -- order can be made better
+ 'l-lua.lua',
+ 'l-lpeg.lua',
+ 'l-function.lua',
'l-string.lua',
'l-table.lua',
- 'l-lpeg.lua',
'l-io.lua',
'l-number.lua',
'l-set.lua',
@@ -15758,19 +15814,23 @@ own.libs = { -- order can be made better
'l-unicode.lua',
'l-math.lua',
+ 'util-str.lua', -- code might move to l-string
'util-tab.lua',
'util-sto.lua',
- 'util-mrg.lua',
- 'util-lua.lua',
'util-prs.lua',
'util-fmt.lua',
- 'util-deb.lua',
- 'trac-inf.lua',
'trac-set.lua',
'trac-log.lua',
- 'trac-pro.lua',
+ 'trac-inf.lua', -- was before trac-set
+ 'trac-pro.lua', -- not really needed
+ 'util-lua.lua', -- indeed here?
+ 'util-deb.lua',
+
+ 'util-mrg.lua',
+ 'util-tpl.lua',
+ 'util-env.lua',
'luat-env.lua', -- can come before inf (as in mkiv)
'lxml-tab.lua',
@@ -15780,6 +15840,8 @@ own.libs = { -- order can be made better
'lxml-aux.lua',
'lxml-xml.lua',
+ 'trac-xml.lua',
+
'data-ini.lua',
'data-exp.lua',
'data-env.lua',
@@ -15796,35 +15858,20 @@ own.libs = { -- order can be made better
-- 'data-bin.lua',
'data-zip.lua',
'data-tre.lua',
- 'data-crl.lua',
+ 'data-sch.lua',
'data-lua.lua',
'data-aux.lua', -- updater
'data-tmf.lua',
'data-lst.lua',
+ 'util-lib.lua', -- swiglib
+
'luat-sta.lua',
'luat-fmt.lua',
-}
-
--- We need this hack till luatex is fixed.
---
--- for k,v in pairs(arg) do print(k,v) end
-
-if arg and (arg[0] == 'luatex' or arg[0] == 'luatex.exe') and arg[1] == "--luaonly" then
- arg[-1]=arg[0] arg[0]=arg[2] for k=3,#arg do arg[k-2]=arg[k] end arg[#arg]=nil arg[#arg]=nil
-end
--- End of hack.
-
-local format, gsub, gmatch, match, find = string.format, string.gsub, string.gmatch, string.match, string.find
-local concat = table.concat
-
-own.name = (environment and environment.ownname) or arg[0] or 'mtxrun.lua'
-own.path = gsub(match(own.name,"^(.+)[\\/].-$") or ".","\\","/")
-
-local ownpath, owntree = own.path, environment and environment.ownpath or own.path
+}
-own.list = {
+local ownlist = {
'.',
ownpath ,
ownpath .. "/../sources", -- HH's development path
@@ -15838,13 +15885,21 @@ own.list = {
owntree .. "/../../../texmf/tex/context/base",
}
-if own.path == "." then table.remove(own.list,1) end
+if ownpath == "." then table.remove(ownlist,1) end
+
+own = {
+ name = ownname,
+ path = ownpath,
+ tree = owntree,
+ list = ownlist,
+ libs = ownlibs,
+}
local function locate_libs()
- for l=1,#own.libs do
- local lib = own.libs[l]
- for p =1,#own.list do
- local pth = own.list[p]
+ for l=1,#ownlibs do
+ local lib = ownlibs[l]
+ for p =1,#ownlist do
+ local pth = ownlist[p]
local filename = pth .. "/" .. lib
local found = lfs.isfile(filename)
if found then
@@ -15858,8 +15913,8 @@ end
local function load_libs()
local found = locate_libs()
if found then
- for l=1,#own.libs do
- local filename = found .. "/" .. own.libs[l]
+ for l=1,#ownlibs do
+ local filename = found .. "/" .. ownlibs[l]
local codeblob = loadfile(filename)
if codeblob then
codeblob()
@@ -15933,55 +15988,85 @@ if not environment.experiments then environment.experiments = e_experiments end
local instance = resolvers.reset()
local helpinfo = [[
---script run an mtx script (lua prefered method) (--noquotes), no script gives list
---execute run a script or program (texmfstart method) (--noquotes)
---resolve resolve prefixed arguments
---ctxlua run internally (using preloaded libs)
---internal run script using built in libraries (same as --ctxlua)
---locate locate given filename in database (default) or system (--first --all --detail)
-
---autotree use texmf tree cf. env 'texmfstart_tree' or 'texmfstarttree'
---tree=pathtotree use given texmf tree (default file: 'setuptex.tmf')
---environment=name use given (tmf) environment file
---path=runpath go to given path before execution
---ifchanged=filename only execute when given file has changed (md checksum)
---iftouched=old,new only execute when given file has changed (time stamp)
-
---makestubs create stubs for (context related) scripts
---removestubs remove stubs (context related) scripts
---stubpath=binpath paths where stubs wil be written
---windows create windows (mswin) stubs
---unix create unix (linux) stubs
-
---verbose give a bit more info
---trackers=list enable given trackers
---progname=str format or backend
-
---edit launch editor with found file
---launch (--all) launch files like manuals, assumes os support
-
---timedrun run a script an time its run
---autogenerate regenerate databases if needed (handy when used to run context in an editor)
-
---usekpse use kpse as fallback (when no mkiv and cache installed, often slower)
---forcekpse force using kpse (handy when no mkiv and cache installed but less functionality)
-
---prefixes show supported prefixes
-
---generate generate file database
-
---variables show configuration variables
---configurations show configuration order
-
---expand-braces expand complex variable
---expand-path expand variable (resolve paths)
---expand-var expand variable (resolve references)
---show-path show path expansion of ...
---var-value report value of variable
---find-file report file location
---find-path report path of file
-
---pattern=str filter variables
+
+
+
+ mtxrun
+ ConTeXt TDS Runner Tool
+ 1.31
+
+
+
+
+ run an mtx script (lua prefered method) (), no script gives list
+ run a script or program (texmfstart method) ()
+ resolve prefixed arguments
+ run internally (using preloaded libs)
+ run script using built in libraries (same as )
+ locate given filename in database (default) or system ( )
+
+
+ use texmf tree cf. env texmfstart_tree or texmfstarttree
+ use given texmf tree (default file: setuptex.tmf)
+ use given (tmf) environment file
+ go to given path before execution
+ only execute when given file has changed (md checksum)
+ only execute when given file has changed (time stamp)
+
+
+ create stubs for (context related) scripts
+ remove stubs (context related) scripts
+ paths where stubs wil be written
+ create windows (mswin) stubs
+ create unix (linux) stubs
+
+
+ give a bit more info
+ enable given trackers
+ format or backend
+
+
+ launch editor with found file
+ launch files like manuals, assumes os support ()
+
+
+ run a script and time its run
+ regenerate databases if needed (handy when used to run context in an editor)
+
+
+ use kpse as fallback (when no mkiv and cache installed, often slower)
+ force using kpse (handy when no mkiv and cache installed but less functionality)
+
+
+ show supported prefixes
+
+
+ generate file database
+
+
+ show configuration variables
+ show configuration order
+
+
+ show (known) directives
+ show (known) trackers
+ show (known) experiments
+
+
+ expand complex variable
+ expand variable (resolve paths)
+ expand variable (resolve references)
+ show path expansion of ...
+ report value of variable
+ report file location
+ report path of file
+
+
+ filter variables
+
+
+
+
]]
local application = logs.application {
@@ -16093,7 +16178,8 @@ function runners.execute_script(fullname,internal,nosplit)
elseif state == 'skip' then
return true
elseif state == "run" then
- local path, name, suffix, result = file.dirname(fullname), file.basename(fullname), file.extname(fullname), ""
+ local path, name, suffix = file.splitname(fullname)
+ local result = ""
if path ~= "" then
result = fullname
elseif name then
@@ -16104,7 +16190,7 @@ function runners.execute_script(fullname,internal,nosplit)
name = gsub(name,"^script:","")
if suffix == "" and runners.registered[name] and runners.registered[name][1] then
name = runners.registered[name][1]
- suffix = file.extname(name)
+ suffix = file.suffix(name)
end
if suffix == "" then
-- loop over known suffixes
@@ -16131,7 +16217,7 @@ function runners.execute_script(fullname,internal,nosplit)
environment.ownscript = result
dofile(result)
else
- local binary = runners.applications[file.extname(result)]
+ local binary = runners.applications[file.suffix(result)]
result = string.quoted(string.unquoted(result))
-- if string.match(result,' ') and not string.match(result,"^\".*\"$") then
-- result = '"' .. result .. '"'
@@ -16324,7 +16410,7 @@ function resolvers.launch(str)
-- maybe we also need to test on mtxrun.launcher.suffix environment
-- variable or on windows consult the assoc and ftype vars and such
local launchers = runners.launchers[os.platform] if launchers then
- local suffix = file.extname(str) if suffix then
+ local suffix = file.suffix(str) if suffix then
local runner = launchers[suffix] if runner then
str = runner .. " " .. str
end
@@ -16383,7 +16469,7 @@ function runners.find_mtx_script(filename)
end
filename = file.addsuffix(filename,"lua")
local basename = file.removesuffix(file.basename(filename))
- local suffix = file.extname(filename)
+ local suffix = file.suffix(filename)
-- qualified path, raw name
local fullname = file.is_qualified_path(filename) and io.exists(filename) and filename
if fullname and fullname ~= "" then
@@ -16438,7 +16524,7 @@ function runners.execute_ctx_script(filename,...)
runners.register_arguments(...)
local arguments = environment.arguments_after
local fullname = runners.find_mtx_script(filename) or ""
- if file.extname(fullname) == "cld" then
+ if file.suffix(fullname) == "cld" then
-- handy in editors where we force --autopdf
report("running cld script: %s",filename)
table.insert(arguments,1,fullname)
@@ -16546,6 +16632,21 @@ function runners.timed(action)
statistics.timed(action)
end
+function runners.associate(filename)
+ os.launch(filename)
+end
+
+function runners.gethelp(filename)
+ local url = environment.argument("url")
+ if url and url ~= "" then
+ local command = string.gsub(environment.argument("command") or "unknown","^%s*\\*(.-)%s*$","%1")
+ url = utilities.templates.replace(url,{ command = command })
+ os.launch(url)
+ else
+ report("no --url given")
+ end
+end
+
-- this is a bit dirty ... first we store the first filename and next we
-- split the arguments so that we only see the ones meant for this script
-- ... later we will use the second half
@@ -16647,8 +16748,18 @@ else
end
+if e_argument("script") or e_argument("scripts") then
+
+ -- run a script by loading it (using libs), pass args
+
+ runners.loadbase()
+ if is_mkii_stub then
+ ok = runners.execute_script(filename,false,true)
+ else
+ ok = runners.execute_ctx_script(filename)
+ end
-if e_argument("selfmerge") then
+elseif e_argument("selfmerge") then
-- embed used libraries
@@ -16678,17 +16789,6 @@ elseif e_argument("ctxlua") or e_argument("internal") then
runners.loadbase()
ok = runners.execute_script(filename,true)
-elseif e_argument("script") or e_argument("scripts") then
-
- -- run a script by loading it (using libs), pass args
-
- runners.loadbase()
- if is_mkii_stub then
- ok = runners.execute_script(filename,false,true)
- else
- ok = runners.execute_ctx_script(filename)
- end
-
elseif e_argument("execute") then
-- execute script
@@ -16715,6 +16815,14 @@ elseif e_argument("launch") then
runners.loadbase()
runners.launch_file(filename)
+elseif e_argument("associate") then
+
+ runners.associate(filename)
+
+elseif e_argument("gethelp") then
+
+ runners.gethelp()
+
elseif e_argument("makestubs") then
-- make stubs (depricated)
@@ -16806,7 +16914,7 @@ elseif e_argument("find-path") then
elseif e_argument("expand-braces") then
- -- luatools: runners.execute_ctx_script("mtx-base","--expand-braces",filename
+ -- luatools: runners.execute_ctx_script("mtx-base","--expand-braces",filename)
resolvers.load("nofiles")
runners.register_arguments(filename)
@@ -16908,6 +17016,23 @@ elseif e_argument("version") then
application.version()
+elseif e_argument("directives") then
+
+ directives.show()
+
+elseif e_argument("trackers") then
+
+ trackers.show()
+
+elseif e_argument("experiments") then
+
+ experiments.show()
+
+elseif e_argument("exporthelp") then
+
+ runners.loadbase()
+ application.export(e_argument("exporthelp"),filename)
+
elseif e_argument("help") or filename=='help' or filename == "" then
application.help()
@@ -16938,7 +17063,6 @@ elseif environment.files[1] == 'texmfcnf.lua' then -- so that we don't need to l
resolvers.listers.configurations()
else
-
runners.loadbase()
runners.execute_ctx_script("mtx-base",filename)
@@ -16955,4 +17079,4 @@ end
if ok == false then ok = 1 elseif ok == true then ok = 0 end
-os.exit(ok)
+os.exit(ok,true) -- true forces a cleanup in 5.2+
diff --git a/Master/texmf-dist/scripts/context/stubs/mswin/pstopdf.exe b/Master/texmf-dist/scripts/context/stubs/mswin/pstopdf.exe
new file mode 100755
index 00000000000..2d45f27494d
Binary files /dev/null and b/Master/texmf-dist/scripts/context/stubs/mswin/pstopdf.exe differ
diff --git a/Master/texmf-dist/scripts/context/stubs/mswin/setuptex.bat b/Master/texmf-dist/scripts/context/stubs/mswin/setuptex.bat
new file mode 100755
index 00000000000..52c60f155c7
--- /dev/null
+++ b/Master/texmf-dist/scripts/context/stubs/mswin/setuptex.bat
@@ -0,0 +1,34 @@
+@ECHO OFF
+
+REM author: Hans Hagen - PRAGMA ADE - Hasselt NL - www.pragma-ade.com
+
+:userpath
+
+if "%SETUPTEX%"=="done" goto done
+
+if "%~s1"=="" goto selftest
+
+set TEXMFOS=%~s1texmf-mswin
+if exist %TEXMFOS%\bin\mtxrun.exe goto start
+
+set TEXMFOS=%~s1\texmf-mswin
+if exist %TEXMFOS%\bin\mtxrun.exe goto start
+
+:selftest
+
+set TEXMFOS=%~d0%~p0texmf-mswin
+if exist %TEXMFOS%\bin\mtxrun.exe goto start
+
+set TEXMFOS=%~d0%~p0\texmf-mswin
+if exist %TEXMFOS%\bin\mtxrun.exe goto start
+
+:start
+
+set PATH=%TEXMFOS%\bin;%PATH%
+
+:register
+
+set SETUPTEX=done
+set CTXMINIMAL=yes
+
+:done
diff --git a/Master/texmf-dist/scripts/context/stubs/unix/ctxtools b/Master/texmf-dist/scripts/context/stubs/unix/ctxtools
new file mode 100644
index 00000000000..2e6bd4afaa0
--- /dev/null
+++ b/Master/texmf-dist/scripts/context/stubs/unix/ctxtools
@@ -0,0 +1,2 @@
+#!/bin/sh
+mtxrun --script ctxtools "$@"
diff --git a/Master/texmf-dist/scripts/context/stubs/unix/mtxrun b/Master/texmf-dist/scripts/context/stubs/unix/mtxrun
index 108f2a8a112..00f63a5791d 100755
--- a/Master/texmf-dist/scripts/context/stubs/unix/mtxrun
+++ b/Master/texmf-dist/scripts/context/stubs/unix/mtxrun
@@ -1,5 +1,16 @@
#!/usr/bin/env texlua
+-- for k, v in next, _G.string do
+-- local tv = type(v)
+-- if tv == "table" then
+-- for kk, vv in next, v do
+-- print(k,kk,vv)
+-- end
+-- else
+-- print(tv,k,v)
+-- end
+-- end
+
if not modules then modules = { } end modules ['mtxrun'] = {
version = 1.001,
comment = "runner, lua replacement for texmfstart.rb",
@@ -43,3016 +54,7333 @@ if not modules then modules = { } end modules ['mtxrun'] = {
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-string'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
+package.loaded["l-lua"] = package.loaded["l-lua"] or true
+
+-- original size: 10048, stripped down to: 5684
+
+if not modules then modules={} end modules ['l-lua']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local major,minor=string.match(_VERSION,"^[^%d]+(%d+)%.(%d+).*$")
+_MAJORVERSION=tonumber(major) or 5
+_MINORVERSION=tonumber(minor) or 1
+_LUAVERSION=_MAJORVERSION+_MINORVERSION/10
+if not lpeg then
+ lpeg=require("lpeg")
+end
+if loadstring then
+ local loadnormal=load
+ function load(first,...)
+ if type(first)=="string" then
+ return loadstring(first,...)
+ else
+ return loadnormal(first,...)
+ end
+ end
+else
+ loadstring=load
+end
+if not ipairs then
+ local function iterate(a,i)
+ i=i+1
+ local v=a[i]
+ if v~=nil then
+ return i,v
+ end
+ end
+ function ipairs(a)
+ return iterate,a,0
+ end
+end
+if not pairs then
+ function pairs(t)
+ return next,t
+ end
+end
+if not table.unpack then
+ table.unpack=_G.unpack
+elseif not unpack then
+ _G.unpack=table.unpack
+end
+if not package.loaders then
+ package.loaders=package.searchers
+end
+local print,select,tostring=print,select,tostring
+local inspectors={}
+function setinspector(inspector)
+ inspectors[#inspectors+1]=inspector
+end
+function inspect(...)
+ for s=1,select("#",...) do
+ local value=select(s,...)
+ local done=false
+ for i=1,#inspectors do
+ done=inspectors[i](value)
+ if done then
+ break
+ end
+ end
+ if not done then
+ print(tostring(value))
+ end
+ end
+end
+local dummy=function() end
+function optionalrequire(...)
+ local ok,result=xpcall(require,dummy,...)
+ if ok then
+ return result
+ end
+end
+local type=type
+local gsub,format=string.gsub,string.format
+local package=package
+local searchers=package.searchers or package.loaders
+local libpaths=nil
+local clibpaths=nil
+local libhash={}
+local clibhash={}
+local libextras={}
+local clibextras={}
+local filejoin=file and file.join or function(path,name) return path.."/"..name end
+local isreadable=file and file.is_readable or function(name) local f=io.open(name) if f then f:close() return true end end
+local addsuffix=file and file.addsuffix or function(name,suffix) return name.."."..suffix end
+local function cleanpath(path)
+ return path
+end
+local helpers=package.helpers or {
+ libpaths=function() return {} end,
+ clibpaths=function() return {} end,
+ cleanpath=cleanpath,
+ trace=false,
+ report=function(...) print(format(...)) end,
}
+package.helpers=helpers
+local function getlibpaths()
+ return libpaths or helpers.libpaths(libhash)
+end
+local function getclibpaths()
+ return clibpaths or helpers.clibpaths(clibhash)
+end
+package.libpaths=getlibpaths
+package.clibpaths=getclibpaths
+local function addpath(what,paths,extras,hash,...)
+ local pathlist={... }
+ local cleanpath=helpers.cleanpath
+ local trace=helpers.trace
+ local report=helpers.report
+ local function add(path)
+ local path=cleanpath(path)
+ if not hash[path] then
+ if trace then
+ report("extra %s path: %s",what,path)
+ end
+ paths [#paths+1]=path
+ extras[#extras+1]=path
+ end
+ end
+ for p=1,#pathlist do
+ local path=pathlist[p]
+ if type(path)=="table" then
+ for i=1,#path do
+ add(path[i])
+ end
+ else
+ add(path)
+ end
+ end
+ return paths,extras
+end
+function package.extralibpath(...)
+ libpaths,libextras=addpath("lua",getlibpaths(),libextras,libhash,...)
+end
+function package.extraclibpath(...)
+ clibpaths,clibextras=addpath("lib",getclibpaths(),clibextras,clibhash,...)
+end
+if not searchers[-2] then
+ searchers[-2]=searchers[2]
+end
+searchers[2]=function(name)
+ return helpers.loaded(name)
+end
+searchers[3]=nil
+local function loadedaslib(resolved,rawname)
+ local init="luaopen_"..gsub(rawname,"%.","_")
+ if helpers.trace then
+ helpers.report("calling loadlib with '%s' with init '%s'",resolved,init)
+ end
+ return package.loadlib(resolved,init)
+end
+local function loadedbylua(name)
+ if helpers.trace then
+ helpers.report("locating '%s' using normal loader",name)
+ end
+ return true,searchers[-2](name)
+end
+local function loadedbypath(name,rawname,paths,islib,what)
+ local trace=helpers.trace
+ local report=helpers.report
+ if trace then
+ report("locating '%s' as '%s' on '%s' paths",rawname,name,what)
+ end
+ for p=1,#paths do
+ local path=paths[p]
+ local resolved=filejoin(path,name)
+ if trace then
+ report("checking for '%s' using '%s' path '%s'",name,what,path)
+ end
+ if isreadable(resolved) then
+ if trace then
+ report("lib '%s' located on '%s'",name,resolved)
+ end
+ if islib then
+ return true,loadedaslib(resolved,rawname)
+ else
+ return true,loadfile(resolved)
+ end
+ end
+ end
+end
+local function notloaded(name)
+ if helpers.trace then
+ helpers.report("? unable to locate library '%s'",name)
+ end
+end
+helpers.loadedaslib=loadedaslib
+helpers.loadedbylua=loadedbylua
+helpers.loadedbypath=loadedbypath
+helpers.notloaded=notloaded
+function helpers.loaded(name)
+ local thename=gsub(name,"%.","/")
+ local luaname=addsuffix(thename,"lua")
+ local libname=addsuffix(thename,os.libsuffix or "so")
+ local libpaths=getlibpaths()
+ local clibpaths=getclibpaths()
+ local done,result=loadedbypath(luaname,name,libpaths,false,"lua")
+ if done then
+ return result
+ end
+ local done,result=loadedbypath(luaname,name,clibpaths,false,"lua")
+ if done then
+ return result
+ end
+ local done,result=loadedbypath(libname,name,clibpaths,true,"lib")
+ if done then
+ return result
+ end
+ local done,result=loadedbylua(name)
+ if done then
+ return result
+ end
+ return notloaded(name)
+end
-local string = string
-local sub, gsub, find, match, gmatch, format, char, byte, rep, lower = string.sub, string.gsub, string.find, string.match, string.gmatch, string.format, string.char, string.byte, string.rep, string.lower
-local lpegmatch, S, C, Ct = lpeg.match, lpeg.S, lpeg.C, lpeg.Ct
--- some functions may disappear as they are not used anywhere
+end -- of closure
-if not string.split then
+do -- create closure to overcome 200 locals limit
- -- this will be overloaded by a faster lpeg variant
+package.loaded["l-lpeg"] = package.loaded["l-lpeg"] or true
- function string.split(str,pattern)
- local t = { }
- if #str > 0 then
- local n = 1
- for s in gmatch(str..pattern,"(.-)"..pattern) do
- t[n] = s
- n = n + 1
- end
- end
- return t
- end
+-- original size: 26252, stripped down to: 14371
+if not modules then modules={} end modules ['l-lpeg']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+lpeg=require("lpeg")
+local type,next,tostring=type,next,tostring
+local byte,char,gmatch,format=string.byte,string.char,string.gmatch,string.format
+local floor=math.floor
+local P,R,S,V,Ct,C,Cs,Cc,Cp,Cmt=lpeg.P,lpeg.R,lpeg.S,lpeg.V,lpeg.Ct,lpeg.C,lpeg.Cs,lpeg.Cc,lpeg.Cp,lpeg.Cmt
+local lpegtype,lpegmatch,lpegprint=lpeg.type,lpeg.match,lpeg.print
+setinspector(function(v) if lpegtype(v) then lpegprint(v) return true end end)
+lpeg.patterns=lpeg.patterns or {}
+local patterns=lpeg.patterns
+local anything=P(1)
+local endofstring=P(-1)
+local alwaysmatched=P(true)
+patterns.anything=anything
+patterns.endofstring=endofstring
+patterns.beginofstring=alwaysmatched
+patterns.alwaysmatched=alwaysmatched
+local digit,sign=R('09'),S('+-')
+local cr,lf,crlf=P("\r"),P("\n"),P("\r\n")
+local newline=crlf+S("\r\n")
+local escaped=P("\\")*anything
+local squote=P("'")
+local dquote=P('"')
+local space=P(" ")
+local utfbom_32_be=P('\000\000\254\255')
+local utfbom_32_le=P('\255\254\000\000')
+local utfbom_16_be=P('\255\254')
+local utfbom_16_le=P('\254\255')
+local utfbom_8=P('\239\187\191')
+local utfbom=utfbom_32_be+utfbom_32_le+utfbom_16_be+utfbom_16_le+utfbom_8
+local utftype=utfbom_32_be*Cc("utf-32-be")+utfbom_32_le*Cc("utf-32-le")+utfbom_16_be*Cc("utf-16-be")+utfbom_16_le*Cc("utf-16-le")+utfbom_8*Cc("utf-8")+alwaysmatched*Cc("utf-8")
+local utfoffset=utfbom_32_be*Cc(4)+utfbom_32_le*Cc(4)+utfbom_16_be*Cc(2)+utfbom_16_le*Cc(2)+utfbom_8*Cc(3)+Cc(0)
+local utf8next=R("\128\191")
+patterns.utf8one=R("\000\127")
+patterns.utf8two=R("\194\223")*utf8next
+patterns.utf8three=R("\224\239")*utf8next*utf8next
+patterns.utf8four=R("\240\244")*utf8next*utf8next*utf8next
+patterns.utfbom=utfbom
+patterns.utftype=utftype
+patterns.utfoffset=utfoffset
+local utf8char=patterns.utf8one+patterns.utf8two+patterns.utf8three+patterns.utf8four
+local validutf8char=utf8char^0*endofstring*Cc(true)+Cc(false)
+local utf8character=P(1)*R("\128\191")^0
+patterns.utf8=utf8char
+patterns.utf8char=utf8char
+patterns.utf8character=utf8character
+patterns.validutf8=validutf8char
+patterns.validutf8char=validutf8char
+local eol=S("\n\r")
+local spacer=S(" \t\f\v")
+local whitespace=eol+spacer
+local nonspacer=1-spacer
+local nonwhitespace=1-whitespace
+patterns.eol=eol
+patterns.spacer=spacer
+patterns.whitespace=whitespace
+patterns.nonspacer=nonspacer
+patterns.nonwhitespace=nonwhitespace
+local stripper=spacer^0*C((spacer^0*nonspacer^1)^0)
+local collapser=Cs(spacer^0/""*nonspacer^0*((spacer^0/" "*nonspacer^1)^0))
+patterns.stripper=stripper
+patterns.collapser=collapser
+patterns.digit=digit
+patterns.sign=sign
+patterns.cardinal=sign^0*digit^1
+patterns.integer=sign^0*digit^1
+patterns.unsigned=digit^0*P('.')*digit^1
+patterns.float=sign^0*patterns.unsigned
+patterns.cunsigned=digit^0*P(',')*digit^1
+patterns.cfloat=sign^0*patterns.cunsigned
+patterns.number=patterns.float+patterns.integer
+patterns.cnumber=patterns.cfloat+patterns.integer
+patterns.oct=P("0")*R("07")^1
+patterns.octal=patterns.oct
+patterns.HEX=P("0x")*R("09","AF")^1
+patterns.hex=P("0x")*R("09","af")^1
+patterns.hexadecimal=P("0x")*R("09","AF","af")^1
+patterns.lowercase=R("az")
+patterns.uppercase=R("AZ")
+patterns.letter=patterns.lowercase+patterns.uppercase
+patterns.space=space
+patterns.tab=P("\t")
+patterns.spaceortab=patterns.space+patterns.tab
+patterns.newline=newline
+patterns.emptyline=newline^1
+patterns.equal=P("=")
+patterns.comma=P(",")
+patterns.commaspacer=P(",")*spacer^0
+patterns.period=P(".")
+patterns.colon=P(":")
+patterns.semicolon=P(";")
+patterns.underscore=P("_")
+patterns.escaped=escaped
+patterns.squote=squote
+patterns.dquote=dquote
+patterns.nosquote=(escaped+(1-squote))^0
+patterns.nodquote=(escaped+(1-dquote))^0
+patterns.unsingle=(squote/"")*patterns.nosquote*(squote/"")
+patterns.undouble=(dquote/"")*patterns.nodquote*(dquote/"")
+patterns.unquoted=patterns.undouble+patterns.unsingle
+patterns.unspacer=((patterns.spacer^1)/"")^0
+patterns.singlequoted=squote*patterns.nosquote*squote
+patterns.doublequoted=dquote*patterns.nodquote*dquote
+patterns.quoted=patterns.doublequoted+patterns.singlequoted
+patterns.propername=R("AZ","az","__")*R("09","AZ","az","__")^0*P(-1)
+patterns.somecontent=(anything-newline-space)^1
+patterns.beginline=#(1-newline)
+patterns.longtostring=Cs(whitespace^0/""*nonwhitespace^0*((whitespace^0/" "*(patterns.quoted+nonwhitespace)^1)^0))
+local function anywhere(pattern)
+ return P { P(pattern)+1*V(1) }
+end
+lpeg.anywhere=anywhere
+function lpeg.instringchecker(p)
+ p=anywhere(p)
+ return function(str)
+ return lpegmatch(p,str) and true or false
+ end
+end
+function lpeg.splitter(pattern,action)
+ return (((1-P(pattern))^1)/action+1)^0
+end
+function lpeg.tsplitter(pattern,action)
+ return Ct((((1-P(pattern))^1)/action+1)^0)
+end
+local splitters_s,splitters_m,splitters_t={},{},{}
+local function splitat(separator,single)
+ local splitter=(single and splitters_s[separator]) or splitters_m[separator]
+ if not splitter then
+ separator=P(separator)
+ local other=C((1-separator)^0)
+ if single then
+ local any=anything
+ splitter=other*(separator*C(any^0)+"")
+ splitters_s[separator]=splitter
+ else
+ splitter=other*(separator*other)^0
+ splitters_m[separator]=splitter
+ end
+ end
+ return splitter
end
-
-function string.unquoted(str)
- return (gsub(str,"^([\"\'])(.*)%1$","%2"))
+local function tsplitat(separator)
+ local splitter=splitters_t[separator]
+ if not splitter then
+ splitter=Ct(splitat(separator))
+ splitters_t[separator]=splitter
+ end
+ return splitter
+end
+lpeg.splitat=splitat
+lpeg.tsplitat=tsplitat
+function string.splitup(str,separator)
+ if not separator then
+ separator=","
+ end
+ return lpegmatch(splitters_m[separator] or splitat(separator),str)
end
-
-
-function string.quoted(str)
- return format("%q",str) -- always "
+local cache={}
+function lpeg.split(separator,str)
+ local c=cache[separator]
+ if not c then
+ c=tsplitat(separator)
+ cache[separator]=c
+ end
+ return lpegmatch(c,str)
end
-
-function string.count(str,pattern) -- variant 3
- local n = 0
- for _ in gmatch(str,pattern) do -- not for utf
- n = n + 1
+function string.split(str,separator)
+ if separator then
+ local c=cache[separator]
+ if not c then
+ c=tsplitat(separator)
+ cache[separator]=c
+ end
+ return lpegmatch(c,str)
+ else
+ return { str }
+ end
+end
+local spacing=patterns.spacer^0*newline
+local empty=spacing*Cc("")
+local nonempty=Cs((1-spacing)^1)*spacing^-1
+local content=(empty+nonempty)^1
+patterns.textline=content
+local linesplitter=tsplitat(newline)
+patterns.linesplitter=linesplitter
+function string.splitlines(str)
+ return lpegmatch(linesplitter,str)
+end
+local cache={}
+function lpeg.checkedsplit(separator,str)
+ local c=cache[separator]
+ if not c then
+ separator=P(separator)
+ local other=C((1-separator)^1)
+ c=Ct(separator^0*other*(separator^1*other)^0)
+ cache[separator]=c
+ end
+ return lpegmatch(c,str)
+end
+function string.checkedsplit(str,separator)
+ local c=cache[separator]
+ if not c then
+ separator=P(separator)
+ local other=C((1-separator)^1)
+ c=Ct(separator^0*other*(separator^1*other)^0)
+ cache[separator]=c
+ end
+ return lpegmatch(c,str)
+end
+local function f2(s) local c1,c2=byte(s,1,2) return c1*64+c2-12416 end
+local function f3(s) local c1,c2,c3=byte(s,1,3) return (c1*64+c2)*64+c3-925824 end
+local function f4(s) local c1,c2,c3,c4=byte(s,1,4) return ((c1*64+c2)*64+c3)*64+c4-63447168 end
+local utf8byte=patterns.utf8one/byte+patterns.utf8two/f2+patterns.utf8three/f3+patterns.utf8four/f4
+patterns.utf8byte=utf8byte
+local cache={}
+function lpeg.stripper(str)
+ if type(str)=="string" then
+ local s=cache[str]
+ if not s then
+ s=Cs(((S(str)^1)/""+1)^0)
+ cache[str]=s
end
- return n
+ return s
+ else
+ return Cs(((str^1)/""+1)^0)
+ end
end
-
-function string.limit(str,n,sentinel) -- not utf proof
- if #str > n then
- sentinel = sentinel or "..."
- return sub(str,1,(n-#sentinel)) .. sentinel
+local cache={}
+function lpeg.keeper(str)
+ if type(str)=="string" then
+ local s=cache[str]
+ if not s then
+ s=Cs((((1-S(str))^1)/""+1)^0)
+ cache[str]=s
+ end
+ return s
+ else
+ return Cs((((1-str)^1)/""+1)^0)
+ end
+end
+function lpeg.frontstripper(str)
+ return (P(str)+P(true))*Cs(anything^0)
+end
+function lpeg.endstripper(str)
+ return Cs((1-P(str)*endofstring)^0)
+end
+function lpeg.replacer(one,two,makefunction,isutf)
+ local pattern
+ local u=isutf and utf8char or 1
+ if type(one)=="table" then
+ local no=#one
+ local p=P(false)
+ if no==0 then
+ for k,v in next,one do
+ p=p+P(k)/v
+ end
+ pattern=Cs((p+u)^0)
+ elseif no==1 then
+ local o=one[1]
+ one,two=P(o[1]),o[2]
+ pattern=Cs((one/two+u)^0)
+ else
+ for i=1,no do
+ local o=one[i]
+ p=p+P(o[1])/o[2]
+ end
+ pattern=Cs((p+u)^0)
+ end
+ else
+ pattern=Cs((P(one)/(two or "")+u)^0)
+ end
+ if makefunction then
+ return function(str)
+ return lpegmatch(pattern,str)
+ end
+ else
+ return pattern
+ end
+end
+function lpeg.finder(lst,makefunction)
+ local pattern
+ if type(lst)=="table" then
+ pattern=P(false)
+ if #lst==0 then
+ for k,v in next,lst do
+ pattern=pattern+P(k)
+ end
else
- return str
+ for i=1,#lst do
+ pattern=pattern+P(lst[i])
+ end
+ end
+ else
+ pattern=P(lst)
+ end
+ pattern=(1-pattern)^0*pattern
+ if makefunction then
+ return function(str)
+ return lpegmatch(pattern,str)
+ end
+ else
+ return pattern
+ end
+end
+local splitters_f,splitters_s={},{}
+function lpeg.firstofsplit(separator)
+ local splitter=splitters_f[separator]
+ if not splitter then
+ separator=P(separator)
+ splitter=C((1-separator)^0)
+ splitters_f[separator]=splitter
+ end
+ return splitter
+end
+function lpeg.secondofsplit(separator)
+ local splitter=splitters_s[separator]
+ if not splitter then
+ separator=P(separator)
+ splitter=(1-separator)^0*separator*C(anything^0)
+ splitters_s[separator]=splitter
+ end
+ return splitter
+end
+function lpeg.balancer(left,right)
+ left,right=P(left),P(right)
+ return P { left*((1-left-right)+V(1))^0*right }
+end
+local nany=utf8char/""
+function lpeg.counter(pattern)
+ pattern=Cs((P(pattern)/" "+nany)^0)
+ return function(str)
+ return #lpegmatch(pattern,str)
+ end
+end
+utf=utf or (unicode and unicode.utf8) or {}
+local utfcharacters=utf and utf.characters or string.utfcharacters
+local utfgmatch=utf and utf.gmatch
+local utfchar=utf and utf.char
+lpeg.UP=lpeg.P
+if utfcharacters then
+ function lpeg.US(str)
+ local p=P(false)
+ for uc in utfcharacters(str) do
+ p=p+P(uc)
+ end
+ return p
+ end
+elseif utfgmatch then
+ function lpeg.US(str)
+ local p=P(false)
+ for uc in utfgmatch(str,".") do
+ p=p+P(uc)
+ end
+ return p
+ end
+else
+ function lpeg.US(str)
+ local p=P(false)
+ local f=function(uc)
+ p=p+P(uc)
end
+ lpegmatch((utf8char/f)^0,str)
+ return p
+ end
end
-
-local space = S(" \t\v\n")
-local nospace = 1 - space
-local stripper = space^0 * C((space^0 * nospace^1)^0) -- roberto's code
-
-function string.strip(str)
- return lpegmatch(stripper,str) or ""
+local range=utf8byte*utf8byte+Cc(false)
+function lpeg.UR(str,more)
+ local first,last
+ if type(str)=="number" then
+ first=str
+ last=more or first
+ else
+ first,last=lpegmatch(range,str)
+ if not last then
+ return P(str)
+ end
+ end
+ if first==last then
+ return P(str)
+ elseif utfchar and (last-first<8) then
+ local p=P(false)
+ for i=first,last do
+ p=p+P(utfchar(i))
+ end
+ return p
+ else
+ local f=function(b)
+ return b>=first and b<=last
+ end
+ return utf8byte/f
+ end
end
-
-function string.is_empty(str)
- return not find(str,"%S")
+function lpeg.is_lpeg(p)
+ return p and lpegtype(p)=="pattern"
+end
+function lpeg.oneof(list,...)
+ if type(list)~="table" then
+ list={ list,... }
+ end
+ local p=P(list[1])
+ for l=2,#list do
+ p=p+P(list[l])
+ end
+ return p
+end
+local sort=table.sort
+local function copyindexed(old)
+ local new={}
+ for i=1,#old do
+ new[i]=old
+ end
+ return new
end
-
-local patterns_escapes = {
- ["%"] = "%%",
- ["."] = "%.",
- ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
- ["["] = "%[", ["]"] = "%]",
- ["("] = "%(", [")"] = "%)",
- -- ["{"] = "%{", ["}"] = "%}"
- -- ["^"] = "%^", ["$"] = "%$",
-}
-
-local simple_escapes = {
- ["-"] = "%-",
- ["."] = "%.",
- ["?"] = ".",
- ["*"] = ".*",
-}
-
-function string.escapedpattern(str,simple)
- return (gsub(str,".",simple and simple_escapes or patterns_escapes))
+local function sortedkeys(tab)
+ local keys,s={},0
+ for key,_ in next,tab do
+ s=s+1
+ keys[s]=key
+ end
+ sort(keys)
+ return keys
end
-
-function string.topattern(str,lowercase,strict)
- if str == "" then
- return ".*"
+function lpeg.append(list,pp,delayed,checked)
+ local p=pp
+ if #list>0 then
+ local keys=copyindexed(list)
+ sort(keys)
+ for i=#keys,1,-1 do
+ local k=keys[i]
+ if p then
+ p=P(k)+p
+ else
+ p=P(k)
+ end
+ end
+ elseif delayed then
+ local keys=sortedkeys(list)
+ if p then
+ for i=1,#keys,1 do
+ local k=keys[i]
+ local v=list[k]
+ p=P(k)/list+p
+ end
else
- str = gsub(str,".",simple_escapes)
- if lowercase then
- str = lower(str)
+ for i=1,#keys do
+ local k=keys[i]
+ local v=list[k]
+ if p then
+ p=P(k)+p
+ else
+ p=P(k)
+ end
+ end
+ if p then
+ p=p/list
+ end
+ end
+ elseif checked then
+ local keys=sortedkeys(list)
+ for i=1,#keys do
+ local k=keys[i]
+ local v=list[k]
+ if p then
+ if k==v then
+ p=P(k)+p
+ else
+ p=P(k)/v+p
end
- if strict then
- return "^" .. str .. "$"
+ else
+ if k==v then
+ p=P(k)
else
- return str
+ p=P(k)/v
end
+ end
+ end
+ else
+ local keys=sortedkeys(list)
+ for i=1,#keys do
+ local k=keys[i]
+ local v=list[k]
+ if p then
+ p=P(k)/v+p
+ else
+ p=P(k)/v
+ end
end
+ end
+ return p
end
-
--- obsolete names:
-
-string.quote = string.quoted
-string.unquote = string.unquoted
+local function make(t)
+ local p
+ local keys=sortedkeys(t)
+ for i=1,#keys do
+ local k=keys[i]
+ local v=t[k]
+ if not p then
+ if next(v) then
+ p=P(k)*make(v)
+ else
+ p=P(k)
+ end
+ else
+ if next(v) then
+ p=p+P(k)*make(v)
+ else
+ p=p+P(k)
+ end
+ end
+ end
+ return p
+end
+function lpeg.utfchartabletopattern(list)
+ local tree={}
+ for i=1,#list do
+ local t=tree
+ for c in gmatch(list[i],".") do
+ if not t[c] then
+ t[c]={}
+ end
+ t=t[c]
+ end
+ end
+ return make(tree)
+end
+patterns.containseol=lpeg.finder(eol)
+local function nextstep(n,step,result)
+ local m=n%step
+ local d=floor(n/step)
+ if d>0 then
+ local v=V(tostring(step))
+ local s=result.start
+ for i=1,d do
+ if s then
+ s=v*s
+ else
+ s=v
+ end
+ end
+ result.start=s
+ end
+ if step>1 and result.start then
+ local v=V(tostring(step/2))
+ result[tostring(step)]=v*v
+ end
+ if step>0 then
+ return nextstep(m,step/2,result)
+ else
+ return result
+ end
+end
+function lpeg.times(pattern,n)
+ return P(nextstep(n,2^16,{ "start",["1"]=pattern }))
+end
+local digit=R("09")
+local period=P(".")
+local zero=P("0")
+local trailingzeros=zero^0*-digit
+local case_1=period*trailingzeros/""
+local case_2=period*(digit-trailingzeros)^1*(trailingzeros/"")
+local number=digit^1*(case_1+case_2)
+local stripper=Cs((number+1)^0)
+lpeg.patterns.stripzeros=stripper
end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-table'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local type, next, tostring, tonumber, ipairs, table, string = type, next, tostring, tonumber, ipairs, table, string
-local concat, sort, insert, remove = table.concat, table.sort, table.insert, table.remove
-local format, find, gsub, lower, dump, match = string.format, string.find, string.gsub, string.lower, string.dump, string.match
-local getmetatable, setmetatable = getmetatable, setmetatable
-local getinfo = debug.getinfo
+package.loaded["l-function"] = package.loaded["l-function"] or true
--- Starting with version 5.2 Lua no longer provide ipairs, which makes
--- sense. As we already used the for loop and # in most places the
--- impact on ConTeXt was not that large; the remaining ipairs already
--- have been replaced. In a similar fashion we also hardly used pairs.
---
--- Just in case, we provide the fallbacks as discussed in Programming
--- in Lua (http://www.lua.org/pil/7.3.html):
+-- original size: 361, stripped down to: 322
-if not ipairs then
+if not modules then modules={} end modules ['l-functions']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+functions=functions or {}
+function functions.dummy() end
- -- for k, v in ipairs(t) do ... end
- -- for k=1,#t do local v = t[k] ... end
- local function iterate(a,i)
- i = i + 1
- local v = a[i]
- if v ~= nil then
- return i, v --, nil
- end
- end
+end -- of closure
- function ipairs(a)
- return iterate, a, 0
- end
+do -- create closure to overcome 200 locals limit
-end
+package.loaded["l-string"] = package.loaded["l-string"] or true
-if not pairs then
+-- original size: 5513, stripped down to: 2708
- -- for k, v in pairs(t) do ... end
- -- for k, v in next, t do ... end
+if not modules then modules={} end modules ['l-string']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local string=string
+local sub,gmatch,format,char,byte,rep,lower=string.sub,string.gmatch,string.format,string.char,string.byte,string.rep,string.lower
+local lpegmatch,patterns=lpeg.match,lpeg.patterns
+local P,S,C,Ct,Cc,Cs=lpeg.P,lpeg.S,lpeg.C,lpeg.Ct,lpeg.Cc,lpeg.Cs
+local unquoted=patterns.squote*C(patterns.nosquote)*patterns.squote+patterns.dquote*C(patterns.nodquote)*patterns.dquote
+function string.unquoted(str)
+ return lpegmatch(unquoted,str) or str
+end
+function string.quoted(str)
+ return format("%q",str)
+end
+function string.count(str,pattern)
+ local n=0
+ for _ in gmatch(str,pattern) do
+ n=n+1
+ end
+ return n
+end
+function string.limit(str,n,sentinel)
+ if #str>n then
+ sentinel=sentinel or "..."
+ return sub(str,1,(n-#sentinel))..sentinel
+ else
+ return str
+ end
+end
+local stripper=patterns.stripper
+local collapser=patterns.collapser
+local longtostring=patterns.longtostring
+function string.strip(str)
+ return lpegmatch(stripper,str) or ""
+end
+function string.collapsespaces(str)
+ return lpegmatch(collapser,str) or ""
+end
+function string.longtostring(str)
+ return lpegmatch(longtostring,str) or ""
+end
+local pattern=P(" ")^0*P(-1)
+function string.is_empty(str)
+ if str=="" then
+ return true
+ else
+ return lpegmatch(pattern,str) and true or false
+ end
+end
+local anything=patterns.anything
+local allescapes=Cc("%")*S(".-+%?()[]*")
+local someescapes=Cc("%")*S(".-+%()[]")
+local matchescapes=Cc(".")*S("*?")
+local pattern_a=Cs ((allescapes+anything )^0 )
+local pattern_b=Cs ((someescapes+matchescapes+anything )^0 )
+local pattern_c=Cs (Cc("^")*(someescapes+matchescapes+anything )^0*Cc("$") )
+function string.escapedpattern(str,simple)
+ return lpegmatch(simple and pattern_b or pattern_a,str)
+end
+function string.topattern(str,lowercase,strict)
+ if str=="" or type(str)~="string" then
+ return ".*"
+ elseif strict then
+ str=lpegmatch(pattern_c,str)
+ else
+ str=lpegmatch(pattern_b,str)
+ end
+ if lowercase then
+ return lower(str)
+ else
+ return str
+ end
+end
+function string.valid(str,default)
+ return (type(str)=="string" and str~="" and str) or default or nil
+end
+string.itself=function(s) return s end
+local pattern=Ct(C(1)^0)
+function string.totable(str)
+ return lpegmatch(pattern,str)
+end
+local replacer=lpeg.replacer("@","%%")
+function string.tformat(fmt,...)
+ return format(lpegmatch(replacer,fmt),...)
+end
+string.quote=string.quoted
+string.unquote=string.unquoted
- function pairs(t)
- return next, t -- , nil
- end
-end
+end -- of closure
--- Also, unpack has been moved to the table table, and for compatiility
--- reasons we provide both now.
+do -- create closure to overcome 200 locals limit
-if not table.unpack then
- table.unpack = _G.unpack
-elseif not unpack then
- _G.unpack = table.unpack
-end
+package.loaded["l-table"] = package.loaded["l-table"] or true
--- extra functions, some might go (when not used)
+-- original size: 44643, stripped down to: 19717
+if not modules then modules={} end modules ['l-table']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local type,next,tostring,tonumber,ipairs,select=type,next,tostring,tonumber,ipairs,select
+local table,string=table,string
+local concat,sort,insert,remove=table.concat,table.sort,table.insert,table.remove
+local format,lower,dump=string.format,string.lower,string.dump
+local getmetatable,setmetatable=getmetatable,setmetatable
+local getinfo=debug.getinfo
+local lpegmatch,patterns=lpeg.match,lpeg.patterns
+local floor=math.floor
+local stripper=patterns.stripper
function table.strip(tab)
- local lst, l = { }, 0
- for i=1,#tab do
- local s = gsub(tab[i],"^%s*(.-)%s*$","%1")
- if s == "" then
- -- skip this one
- else
- l = l + 1
- lst[l] = s
- end
+ local lst,l={},0
+ for i=1,#tab do
+ local s=lpegmatch(stripper,tab[i]) or ""
+ if s=="" then
+ else
+ l=l+1
+ lst[l]=s
end
- return lst
+ end
+ return lst
end
-
function table.keys(t)
- local keys, k = { }, 0
- for key, _ in next, t do
- k = k + 1
- keys[k] = key
+ if t then
+ local keys,k={},0
+ for key,_ in next,t do
+ k=k+1
+ keys[k]=key
end
return keys
+ else
+ return {}
+ end
end
-
local function compare(a,b)
- local ta, tb = type(a), type(b) -- needed, else 11 < 2
- if ta == tb then
- return a < b
- else
- return tostring(a) < tostring(b)
- end
+ local ta,tb=type(a),type(b)
+ if ta==tb then
+ return a0 then
+ local n=0
+ for _,v in next,t do
+ n=n+1
+ end
+ if n==#t then
+ local tt,nt={},0
+ for i=1,#t do
+ local v=t[i]
+ local tv=type(v)
+ if tv=="number" then
+ nt=nt+1
+ if hexify then
+ tt[nt]=format("0x%04X",v)
+ else
+ tt[nt]=tostring(v)
+ end
+ elseif tv=="boolean" then
+ nt=nt+1
+ tt[nt]=tostring(v)
+ elseif tv=="string" then
+ nt=nt+1
+ tt[nt]=format("%q",v)
+ else
+ tt=nil
+ break
end
+ end
+ return tt
end
- return tmp
+ end
+ return nil
end
-
-local function fastcopy(old,metatabletoo) -- fast one
- if old then
- local new = { }
- for k,v in next, old do
- if type(v) == "table" then
- new[k] = fastcopy(v,metatabletoo) -- was just table.copy
- else
- new[k] = v
- end
+local propername=patterns.propername
+local function dummy() end
+local function do_serialize(root,name,depth,level,indexed)
+ if level>0 then
+ depth=depth.." "
+ if indexed then
+ handle(format("%s{",depth))
+ else
+ local tn=type(name)
+ if tn=="number" then
+ if hexify then
+ handle(format("%s[0x%04X]={",depth,name))
+ else
+ handle(format("%s[%s]={",depth,name))
end
- if metatabletoo then
- -- optional second arg
- local mt = getmetatable(old)
- if mt then
- setmetatable(new,mt)
+ elseif tn=="string" then
+ if noquotes and not reserved[name] and lpegmatch(propername,name) then
+ handle(format("%s%s={",depth,name))
+ else
+ handle(format("%s[%q]={",depth,name))
+ end
+ elseif tn=="boolean" then
+ handle(format("%s[%s]={",depth,tostring(name)))
+ else
+ handle(format("%s{",depth))
+ end
+ end
+ end
+ if root and next(root) then
+ local first,last=nil,0
+ if compact then
+ last=#root
+ for k=1,last do
+ if root[k]==nil then
+ last=k-1
+ break
+ end
+ end
+ if last>0 then
+ first=1
+ end
+ end
+ local sk=sortedkeys(root)
+ for i=1,#sk do
+ local k=sk[i]
+ local v=root[k]
+ local t,tk=type(v),type(k)
+ if compact and first and tk=="number" and k>=first and k<=last then
+ if t=="number" then
+ if hexify then
+ handle(format("%s 0x%04X,",depth,v))
+ else
+ handle(format("%s %s,",depth,v))
+ end
+ elseif t=="string" then
+ if reduce and tonumber(v) then
+ handle(format("%s %s,",depth,v))
+ else
+ handle(format("%s %q,",depth,v))
+ end
+ elseif t=="table" then
+ if not next(v) then
+ handle(format("%s {},",depth))
+ elseif inline then
+ local st=simple_table(v)
+ if st then
+ handle(format("%s { %s },",depth,concat(st,", ")))
+ else
+ do_serialize(v,k,depth,level+1,true)
+ end
+ else
+ do_serialize(v,k,depth,level+1,true)
+ end
+ elseif t=="boolean" then
+ handle(format("%s %s,",depth,tostring(v)))
+ elseif t=="function" then
+ if functions then
+ handle(format('%s load(%q),',depth,dump(v)))
+ else
+ handle(format('%s "function",',depth))
+ end
+ else
+ handle(format("%s %q,",depth,tostring(v)))
+ end
+ elseif k=="__p__" then
+ if false then
+ handle(format("%s __p__=nil,",depth))
+ end
+ elseif t=="number" then
+ if tk=="number" then
+ if hexify then
+ handle(format("%s [0x%04X]=0x%04X,",depth,k,v))
+ else
+ handle(format("%s [%s]=%s,",depth,k,v))
+ end
+ elseif tk=="boolean" then
+ if hexify then
+ handle(format("%s [%s]=0x%04X,",depth,tostring(k),v))
+ else
+ handle(format("%s [%s]=%s,",depth,tostring(k),v))
+ end
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
+ if hexify then
+ handle(format("%s %s=0x%04X,",depth,k,v))
+ else
+ handle(format("%s %s=%s,",depth,k,v))
+ end
+ else
+ if hexify then
+ handle(format("%s [%q]=0x%04X,",depth,k,v))
+ else
+ handle(format("%s [%q]=%s,",depth,k,v))
+ end
+ end
+ elseif t=="string" then
+ if reduce and tonumber(v) then
+ if tk=="number" then
+ if hexify then
+ handle(format("%s [0x%04X]=%s,",depth,k,v))
+ else
+ handle(format("%s [%s]=%s,",depth,k,v))
+ end
+ elseif tk=="boolean" then
+ handle(format("%s [%s]=%s,",depth,tostring(k),v))
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
+ handle(format("%s %s=%s,",depth,k,v))
+ else
+ handle(format("%s [%q]=%s,",depth,k,v))
+ end
+ else
+ if tk=="number" then
+ if hexify then
+ handle(format("%s [0x%04X]=%q,",depth,k,v))
+ else
+ handle(format("%s [%s]=%q,",depth,k,v))
+ end
+ elseif tk=="boolean" then
+ handle(format("%s [%s]=%q,",depth,tostring(k),v))
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
+ handle(format("%s %s=%q,",depth,k,v))
+ else
+ handle(format("%s [%q]=%q,",depth,k,v))
+ end
+ end
+ elseif t=="table" then
+ if not next(v) then
+ if tk=="number" then
+ if hexify then
+ handle(format("%s [0x%04X]={},",depth,k))
+ else
+ handle(format("%s [%s]={},",depth,k))
+ end
+ elseif tk=="boolean" then
+ handle(format("%s [%s]={},",depth,tostring(k)))
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
+ handle(format("%s %s={},",depth,k))
+ else
+ handle(format("%s [%q]={},",depth,k))
+ end
+ elseif inline then
+ local st=simple_table(v)
+ if st then
+ if tk=="number" then
+ if hexify then
+ handle(format("%s [0x%04X]={ %s },",depth,k,concat(st,", ")))
+ else
+ handle(format("%s [%s]={ %s },",depth,k,concat(st,", ")))
+ end
+ elseif tk=="boolean" then
+ handle(format("%s [%s]={ %s },",depth,tostring(k),concat(st,", ")))
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
+ handle(format("%s %s={ %s },",depth,k,concat(st,", ")))
+ else
+ handle(format("%s [%q]={ %s },",depth,k,concat(st,", ")))
end
+ else
+ do_serialize(v,k,depth,level+1)
+ end
+ else
+ do_serialize(v,k,depth,level+1)
+ end
+ elseif t=="boolean" then
+ if tk=="number" then
+ if hexify then
+ handle(format("%s [0x%04X]=%s,",depth,k,tostring(v)))
+ else
+ handle(format("%s [%s]=%s,",depth,k,tostring(v)))
+ end
+ elseif tk=="boolean" then
+ handle(format("%s [%s]=%s,",depth,tostring(k),tostring(v)))
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
+ handle(format("%s %s=%s,",depth,k,tostring(v)))
+ else
+ handle(format("%s [%q]=%s,",depth,k,tostring(v)))
end
- return new
+ elseif t=="function" then
+ if functions then
+ local f=getinfo(v).what=="C" and dump(dummy) or dump(v)
+ if tk=="number" then
+ if hexify then
+ handle(format("%s [0x%04X]=load(%q),",depth,k,f))
+ else
+ handle(format("%s [%s]=load(%q),",depth,k,f))
+ end
+ elseif tk=="boolean" then
+ handle(format("%s [%s]=load(%q),",depth,tostring(k),f))
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
+ handle(format("%s %s=load(%q),",depth,k,f))
+ else
+ handle(format("%s [%q]=load(%q),",depth,k,f))
+ end
+ end
+ else
+ if tk=="number" then
+ if hexify then
+ handle(format("%s [0x%04X]=%q,",depth,k,tostring(v)))
+ else
+ handle(format("%s [%s]=%q,",depth,k,tostring(v)))
+ end
+ elseif tk=="boolean" then
+ handle(format("%s [%s]=%q,",depth,tostring(k),tostring(v)))
+ elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
+ handle(format("%s %s=%q,",depth,k,tostring(v)))
+ else
+ handle(format("%s [%q]=%q,",depth,k,tostring(v)))
+ end
+ end
+ end
+ end
+ if level>0 then
+ handle(format("%s},",depth))
+ end
+end
+local function serialize(_handle,root,name,specification)
+ local tname=type(name)
+ if type(specification)=="table" then
+ noquotes=specification.noquotes
+ hexify=specification.hexify
+ handle=_handle or specification.handle or print
+ reduce=specification.reduce or false
+ functions=specification.functions
+ compact=specification.compact
+ inline=specification.inline and compact
+ if functions==nil then
+ functions=true
+ end
+ if compact==nil then
+ compact=true
+ end
+ if inline==nil then
+ inline=compact
+ end
+ else
+ noquotes=false
+ hexify=false
+ handle=_handle or print
+ reduce=false
+ compact=true
+ inline=true
+ functions=true
+ end
+ if tname=="string" then
+ if name=="return" then
+ handle("return {")
else
- return { }
+ handle(name.."={")
end
-end
-
--- todo : copy without metatable
-
-local function copy(t, tables) -- taken from lua wiki, slightly adapted
- tables = tables or { }
- local tcopy = {}
- if not tables[t] then
- tables[t] = tcopy
+ elseif tname=="number" then
+ if hexify then
+ handle(format("[0x%04X]={",name))
+ else
+ handle("["..name.."]={")
end
- for i,v in next, t do -- brrr, what happens with sparse indexed
- if type(i) == "table" then
- if tables[i] then
- i = tables[i]
- else
- i = copy(i, tables)
- end
- end
- if type(v) ~= "table" then
- tcopy[i] = v
- elseif tables[v] then
- tcopy[i] = tables[v]
- else
- tcopy[i] = copy(v, tables)
- end
+ elseif tname=="boolean" then
+ if name then
+ handle("return {")
+ else
+ handle("{")
end
- local mt = getmetatable(t)
- if mt then
- setmetatable(tcopy,mt)
+ else
+ handle("t={")
+ end
+ if root then
+ if getmetatable(root) then
+ local dummy=root._w_h_a_t_e_v_e_r_
+ root._w_h_a_t_e_v_e_r_=nil
end
- return tcopy
-end
-
-table.fastcopy = fastcopy
-table.copy = copy
-
-function table.derive(parent)
- local child = { }
- if parent then
- setmetatable(child,{ __index = parent })
+ if next(root) then
+ do_serialize(root,name,"",0)
end
- return child
+ end
+ handle("}")
end
-
-function table.tohash(t,value)
- local h = { }
- if t then
- if value == nil then value = true end
- for _, v in next, t do -- no ipairs here
- h[v] = value
- end
+function table.serialize(root,name,specification)
+ local t,n={},0
+ local function flush(s)
+ n=n+1
+ t[n]=s
+ end
+ serialize(flush,root,name,specification)
+ return concat(t,"\n")
+end
+table.tohandle=serialize
+local maxtab=2*1024
+function table.tofile(filename,root,name,specification)
+ local f=io.open(filename,'w')
+ if f then
+ if maxtab>1 then
+ local t,n={},0
+ local function flush(s)
+ n=n+1
+ t[n]=s
+ if n>maxtab then
+ f:write(concat(t,"\n"),"\n")
+ t,n={},0
+ end
+ end
+ serialize(flush,root,name,specification)
+ f:write(concat(t,"\n"),"\n")
+ else
+ local function flush(s)
+ f:write(s,"\n")
+ end
+ serialize(flush,root,name,specification)
end
- return h
+ f:close()
+ io.flush()
+ end
end
-
-function table.fromhash(t)
- local hsh, h = { }, 0
- for k, v in next, t do -- no ipairs here
- if v then
- h = h + 1
- hsh[h] = k
- end
+local function flattened(t,f,depth)
+ if f==nil then
+ f={}
+ depth=0xFFFF
+ elseif tonumber(f) then
+ depth=f
+ f={}
+ elseif not depth then
+ depth=0xFFFF
+ end
+ for k,v in next,t do
+ if type(k)~="number" then
+ if depth>0 and type(v)=="table" then
+ flattened(v,f,depth-1)
+ else
+ f[k]=v
+ end
+ end
+ end
+ local n=#f
+ for k=1,#t do
+ local v=t[k]
+ if depth>0 and type(v)=="table" then
+ flattened(v,f,depth-1)
+ n=#f
+ else
+ n=n+1
+ f[n]=v
+ end
+ end
+ return f
+end
+table.flattened=flattened
+local function unnest(t,f)
+ if not f then
+ f={}
+ end
+ for i=1,#t do
+ local v=t[i]
+ if type(v)=="table" then
+ if type(v[1])=="table" then
+ unnest(v,f)
+ else
+ f[#f+1]=v
+ end
+ else
+ f[#f+1]=v
+ end
+ end
+ return f
+end
+function table.unnest(t)
+ return unnest(t)
+end
+local function are_equal(a,b,n,m)
+ if a and b and #a==#b then
+ n=n or 1
+ m=m or #a
+ for i=n,m do
+ local ai,bi=a[i],b[i]
+ if ai==bi then
+ elseif type(ai)=="table" and type(bi)=="table" then
+ if not are_equal(ai,bi) then
+ return false
+ end
+ else
+ return false
+ end
end
- return hsh
-end
-
-local noquotes, hexify, handle, reduce, compact, inline, functions
-
-local reserved = table.tohash { -- intercept a language inconvenience: no reserved words as key
- 'and', 'break', 'do', 'else', 'elseif', 'end', 'false', 'for', 'function', 'if',
- 'in', 'local', 'nil', 'not', 'or', 'repeat', 'return', 'then', 'true', 'until', 'while',
-}
-
-local function simple_table(t)
- if #t > 0 then
- local n = 0
- for _,v in next, t do
- n = n + 1
- end
- if n == #t then
- local tt, nt = { }, 0
- for i=1,#t do
- local v = t[i]
- local tv = type(v)
- if tv == "number" then
- nt = nt + 1
- if hexify then
- tt[nt] = format("0x%04X",v)
- else
- tt[nt] = tostring(v) -- tostring not needed
- end
- elseif tv == "boolean" then
- nt = nt + 1
- tt[nt] = tostring(v)
- elseif tv == "string" then
- nt = nt + 1
- tt[nt] = format("%q",v)
- else
- tt = nil
- break
- end
- end
- return tt
- end
+ return true
+ else
+ return false
+ end
+end
+local function identical(a,b)
+ for ka,va in next,a do
+ local vb=b[ka]
+ if va==vb then
+ elseif type(va)=="table" and type(vb)=="table" then
+ if not identical(va,vb) then
+ return false
+ end
+ else
+ return false
end
- return nil
+ end
+ return true
end
-
--- Because this is a core function of mkiv I moved some function calls
--- inline.
---
--- twice as fast in a test:
---
--- local propername = lpeg.P(lpeg.R("AZ","az","__") * lpeg.R("09","AZ","az", "__")^0 * lpeg.P(-1) )
-
--- problem: there no good number_to_string converter with the best resolution
-
-local function dummy() end
-
-local function do_serialize(root,name,depth,level,indexed)
- if level > 0 then
- depth = depth .. " "
- if indexed then
- handle(format("%s{",depth))
- else
- local tn = type(name)
- if tn == "number" then -- or find(k,"^%d+$") then
- if hexify then
- handle(format("%s[0x%04X]={",depth,name))
- else
- handle(format("%s[%s]={",depth,name))
- end
- elseif tn == "string" then
- if noquotes and not reserved[name] and find(name,"^%a[%w%_]*$") then
- handle(format("%s%s={",depth,name))
- else
- handle(format("%s[%q]={",depth,name))
- end
- elseif tn == "boolean" then
- handle(format("%s[%s]={",depth,tostring(name)))
- else
- handle(format("%s{",depth))
- end
- end
- end
- -- we could check for k (index) being number (cardinal)
- if root and next(root) then
- local first, last = nil, 0 -- #root cannot be trusted here (will be ok in 5.2 when ipairs is gone)
- if compact then
- -- NOT: for k=1,#root do (we need to quit at nil)
- for k,v in ipairs(root) do -- can we use next?
- if not first then first = k end
- last = last + 1
- end
- end
- local sk = sortedkeys(root)
- for i=1,#sk do
- local k = sk[i]
- local v = root[k]
- -- circular
- local t, tk = type(v), type(k)
- if compact and first and tk == "number" and k >= first and k <= last then
- if t == "number" then
- if hexify then
- handle(format("%s 0x%04X,",depth,v))
- else
- handle(format("%s %s,",depth,v)) -- %.99g
- end
- elseif t == "string" then
- if reduce and tonumber(v) then
- handle(format("%s %s,",depth,v))
- else
- handle(format("%s %q,",depth,v))
- end
- elseif t == "table" then
- if not next(v) then
- handle(format("%s {},",depth))
- elseif inline then -- and #t > 0
- local st = simple_table(v)
- if st then
- handle(format("%s { %s },",depth,concat(st,", ")))
- else
- do_serialize(v,k,depth,level+1,true)
- end
- else
- do_serialize(v,k,depth,level+1,true)
- end
- elseif t == "boolean" then
- handle(format("%s %s,",depth,tostring(v)))
- elseif t == "function" then
- if functions then
- handle(format('%s loadstring(%q),',depth,dump(v)))
- else
- handle(format('%s "function",',depth))
- end
- else
- handle(format("%s %q,",depth,tostring(v)))
- end
- elseif k == "__p__" then -- parent
- if false then
- handle(format("%s __p__=nil,",depth))
- end
- elseif t == "number" then
- if tk == "number" then -- or find(k,"^%d+$") then
- if hexify then
- handle(format("%s [0x%04X]=0x%04X,",depth,k,v))
- else
- handle(format("%s [%s]=%s,",depth,k,v)) -- %.99g
- end
- elseif tk == "boolean" then
- if hexify then
- handle(format("%s [%s]=0x%04X,",depth,tostring(k),v))
- else
- handle(format("%s [%s]=%s,",depth,tostring(k),v)) -- %.99g
- end
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
- if hexify then
- handle(format("%s %s=0x%04X,",depth,k,v))
- else
- handle(format("%s %s=%s,",depth,k,v)) -- %.99g
- end
- else
- if hexify then
- handle(format("%s [%q]=0x%04X,",depth,k,v))
- else
- handle(format("%s [%q]=%s,",depth,k,v)) -- %.99g
- end
- end
- elseif t == "string" then
- if reduce and tonumber(v) then
- if tk == "number" then -- or find(k,"^%d+$") then
- if hexify then
- handle(format("%s [0x%04X]=%s,",depth,k,v))
- else
- handle(format("%s [%s]=%s,",depth,k,v))
- end
- elseif tk == "boolean" then
- handle(format("%s [%s]=%s,",depth,tostring(k),v))
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
- handle(format("%s %s=%s,",depth,k,v))
- else
- handle(format("%s [%q]=%s,",depth,k,v))
- end
- else
- if tk == "number" then -- or find(k,"^%d+$") then
- if hexify then
- handle(format("%s [0x%04X]=%q,",depth,k,v))
- else
- handle(format("%s [%s]=%q,",depth,k,v))
- end
- elseif tk == "boolean" then
- handle(format("%s [%s]=%q,",depth,tostring(k),v))
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
- handle(format("%s %s=%q,",depth,k,v))
- else
- handle(format("%s [%q]=%q,",depth,k,v))
- end
- end
- elseif t == "table" then
- if not next(v) then
- if tk == "number" then -- or find(k,"^%d+$") then
- if hexify then
- handle(format("%s [0x%04X]={},",depth,k))
- else
- handle(format("%s [%s]={},",depth,k))
- end
- elseif tk == "boolean" then
- handle(format("%s [%s]={},",depth,tostring(k)))
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
- handle(format("%s %s={},",depth,k))
- else
- handle(format("%s [%q]={},",depth,k))
- end
- elseif inline then
- local st = simple_table(v)
- if st then
- if tk == "number" then -- or find(k,"^%d+$") then
- if hexify then
- handle(format("%s [0x%04X]={ %s },",depth,k,concat(st,", ")))
- else
- handle(format("%s [%s]={ %s },",depth,k,concat(st,", ")))
- end
- elseif tk == "boolean" then -- or find(k,"^%d+$") then
- handle(format("%s [%s]={ %s },",depth,tostring(k),concat(st,", ")))
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
- handle(format("%s %s={ %s },",depth,k,concat(st,", ")))
- else
- handle(format("%s [%q]={ %s },",depth,k,concat(st,", ")))
- end
- else
- do_serialize(v,k,depth,level+1)
- end
- else
- do_serialize(v,k,depth,level+1)
- end
- elseif t == "boolean" then
- if tk == "number" then -- or find(k,"^%d+$") then
- if hexify then
- handle(format("%s [0x%04X]=%s,",depth,k,tostring(v)))
- else
- handle(format("%s [%s]=%s,",depth,k,tostring(v)))
- end
- elseif tk == "boolean" then -- or find(k,"^%d+$") then
- handle(format("%s [%s]=%s,",depth,tostring(k),tostring(v)))
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
- handle(format("%s %s=%s,",depth,k,tostring(v)))
- else
- handle(format("%s [%q]=%s,",depth,k,tostring(v)))
- end
- elseif t == "function" then
- if functions then
- local f = getinfo(v).what == "C" and dump(dummy) or dump(v)
- -- local f = getinfo(v).what == "C" and dump(function(...) return v(...) end) or dump(v)
- if tk == "number" then -- or find(k,"^%d+$") then
- if hexify then
- handle(format("%s [0x%04X]=loadstring(%q),",depth,k,f))
- else
- handle(format("%s [%s]=loadstring(%q),",depth,k,f))
- end
- elseif tk == "boolean" then
- handle(format("%s [%s]=loadstring(%q),",depth,tostring(k),f))
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
- handle(format("%s %s=loadstring(%q),",depth,k,f))
- else
- handle(format("%s [%q]=loadstring(%q),",depth,k,f))
- end
- end
- else
- if tk == "number" then -- or find(k,"^%d+$") then
- if hexify then
- handle(format("%s [0x%04X]=%q,",depth,k,tostring(v)))
- else
- handle(format("%s [%s]=%q,",depth,k,tostring(v)))
- end
- elseif tk == "boolean" then -- or find(k,"^%d+$") then
- handle(format("%s [%s]=%q,",depth,tostring(k),tostring(v)))
- elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
- handle(format("%s %s=%q,",depth,k,tostring(v)))
- else
- handle(format("%s [%q]=%q,",depth,k,tostring(v)))
- end
- end
- end
+table.identical=identical
+table.are_equal=are_equal
+function table.compact(t)
+ if t then
+ for k,v in next,t do
+ if not next(v) then
+ t[k]=nil
+ end
end
- if level > 0 then
- handle(format("%s},",depth))
+ end
+end
+function table.contains(t,v)
+ if t then
+ for i=1,#t do
+ if t[i]==v then
+ return i
+ end
end
+ end
+ return false
end
-
--- replacing handle by a direct t[#t+1] = ... (plus test) is not much
--- faster (0.03 on 1.00 for zapfino.tma)
-
-local function serialize(_handle,root,name,specification) -- handle wins
- local tname = type(name)
- if type(specification) == "table" then
- noquotes = specification.noquotes
- hexify = specification.hexify
- handle = _handle or specification.handle or print
- reduce = specification.reduce or false
- functions = specification.functions
- compact = specification.compact
- inline = specification.inline and compact
- if functions == nil then
- functions = true
- end
- if compact == nil then
- compact = true
- end
- if inline == nil then
- inline = compact
- end
- else
- noquotes = false
- hexify = false
- handle = _handle or print
- reduce = false
- compact = true
- inline = true
- functions = true
- end
- if tname == "string" then
- if name == "return" then
- handle("return {")
- else
- handle(name .. "={")
- end
- elseif tname == "number" then
- if hexify then
- handle(format("[0x%04X]={",name))
- else
- handle("[" .. name .. "]={")
- end
- elseif tname == "boolean" then
- if name then
- handle("return {")
- else
- handle("{")
- end
- else
- handle("t={")
- end
- if root then
- -- The dummy access will initialize a table that has a delayed initialization
- -- using a metatable. (maybe explicitly test for metatable)
- if getmetatable(root) then -- todo: make this an option, maybe even per subtable
- local dummy = root._w_h_a_t_e_v_e_r_
- root._w_h_a_t_e_v_e_r_ = nil
- end
- -- Let's forget about empty tables.
- if next(root) then
- do_serialize(root,name,"",0)
- end
+function table.count(t)
+ local n=0
+ for k,v in next,t do
+ n=n+1
+ end
+ return n
+end
+function table.swapped(t,s)
+ local n={}
+ if s then
+ for k,v in next,s do
+ n[k]=v
+ end
+ end
+ for k,v in next,t do
+ n[v]=k
+ end
+ return n
+end
+function table.mirrored(t)
+ local n={}
+ for k,v in next,t do
+ n[v]=k
+ n[k]=v
+ end
+ return n
+end
+function table.reversed(t)
+ if t then
+ local tt,tn={},#t
+ if tn>0 then
+ local ttn=0
+ for i=tn,1,-1 do
+ ttn=ttn+1
+ tt[ttn]=t[i]
+ end
+ end
+ return tt
+ end
+end
+function table.reverse(t)
+ if t then
+ local n=#t
+ for i=1,floor(n/2) do
+ local j=n-i+1
+ t[i],t[j]=t[j],t[i]
end
- handle("}")
+ return t
+ end
end
-
-
-function table.serialize(root,name,specification)
- local t, n = { }, 0
- local function flush(s)
- n = n + 1
- t[n] = s
+function table.sequenced(t,sep,simple)
+ if not t then
+ return ""
+ end
+ local n=#t
+ local s={}
+ if n>0 then
+ for i=1,n do
+ s[i]=tostring(t[i])
+ end
+ else
+ n=0
+ for k,v in sortedhash(t) do
+ if simple then
+ if v==true then
+ n=n+1
+ s[n]=k
+ elseif v and v~="" then
+ n=n+1
+ s[n]=k.."="..tostring(v)
+ end
+ else
+ n=n+1
+ s[n]=k.."="..tostring(v)
+ end
+ end
+ end
+ return concat(s,sep or " | ")
+end
+function table.print(t,...)
+ if type(t)~="table" then
+ print(tostring(t))
+ else
+ serialize(print,t,...)
+ end
+end
+setinspector(function(v) if type(v)=="table" then serialize(print,v,"table") return true end end)
+function table.sub(t,i,j)
+ return { unpack(t,i,j) }
+end
+function table.is_empty(t)
+ return not t or not next(t)
+end
+function table.has_one_entry(t)
+ return t and not next(t,next(t))
+end
+function table.loweredkeys(t)
+ local l={}
+ for k,v in next,t do
+ l[lower(k)]=v
+ end
+ return l
+end
+function table.unique(old)
+ local hash={}
+ local new={}
+ local n=0
+ for i=1,#old do
+ local oi=old[i]
+ if not hash[oi] then
+ n=n+1
+ new[n]=oi
+ hash[oi]=true
end
- serialize(flush,root,name,specification)
- return concat(t,"\n")
+ end
+ return new
+end
+function table.sorted(t,...)
+ sort(t,...)
+ return t
end
-table.tohandle = serialize
-
--- sometimes tables are real use (zapfino extra pro is some 85M) in which
--- case a stepwise serialization is nice; actually, we could consider:
---
--- for line in table.serializer(root,name,reduce,noquotes) do
--- ...(line)
--- end
---
--- so this is on the todo list
-local maxtab = 2*1024
+end -- of closure
-function table.tofile(filename,root,name,specification)
- local f = io.open(filename,'w')
- if f then
- if maxtab > 1 then
- local t, n = { }, 0
- local function flush(s)
- n = n + 1
- t[n] = s
- if n > maxtab then
- f:write(concat(t,"\n"),"\n") -- hm, write(sometable) should be nice
- t, n = { }, 0 -- we could recycle t if needed
- end
- end
- serialize(flush,root,name,specification)
- f:write(concat(t,"\n"),"\n")
- else
- local function flush(s)
- f:write(s,"\n")
- end
- serialize(flush,root,name,specification)
- end
- f:close()
- io.flush()
- end
-end
+do -- create closure to overcome 200 locals limit
-local function flattened(t,f,depth)
- if f == nil then
- f = { }
- depth = 0xFFFF
- elseif tonumber(f) then
- -- assume then only two arguments are given
- depth = f
- f = { }
- elseif not depth then
- depth = 0xFFFF
- end
- for k, v in next, t do
- if type(k) ~= "number" then
- if depth > 0 and type(v) == "table" then
- flattened(v,f,depth-1)
- else
- f[k] = v
- end
- end
- end
- local n = #f
- for k=1,#t do
- local v = t[k]
- if depth > 0 and type(v) == "table" then
- flattened(v,f,depth-1)
- n = #f
- else
- n = n + 1
- f[n] = v
- end
- end
- return f
-end
+package.loaded["l-io"] = package.loaded["l-io"] or true
-table.flattened = flattened
+-- original size: 8799, stripped down to: 6325
-local function unnest(t,f) -- only used in mk, for old times sake
- if not f then -- and only relevant for token lists
- f = { }
- end
- for i=1,#t do
- local v = t[i]
- if type(v) == "table" then
- if type(v[1]) == "table" then
- unnest(v,f)
- else
- f[#f+1] = v
- end
- else
- f[#f+1] = v
- end
- end
- return f
+if not modules then modules={} end modules ['l-io']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local io=io
+local byte,find,gsub,format=string.byte,string.find,string.gsub,string.format
+local concat=table.concat
+local floor=math.floor
+local type=type
+if string.find(os.getenv("PATH"),";") then
+ io.fileseparator,io.pathseparator="\\",";"
+else
+ io.fileseparator,io.pathseparator="/",":"
end
-
-function table.unnest(t) -- bad name
- return unnest(t)
+local function readall(f)
+ return f:read("*all")
end
-
-local function are_equal(a,b,n,m) -- indexed
- if a and b and #a == #b then
- n = n or 1
- m = m or #a
- for i=n,m do
- local ai, bi = a[i], b[i]
- if ai==bi then
- -- same
- elseif type(ai)=="table" and type(bi)=="table" then
- if not are_equal(ai,bi) then
- return false
- end
- else
- return false
- end
- end
- return true
+local function readall(f)
+ local size=f:seek("end")
+ if size==0 then
+ return ""
+ elseif size<1024*1024 then
+ f:seek("set",0)
+ return f:read('*all')
+ else
+ local done=f:seek("set",0)
+ if size<1024*1024 then
+ step=1024*1024
+ elseif size>16*1024*1024 then
+ step=16*1024*1024
else
- return false
+ step=floor(size/(1024*1024))*1024*1024/8
end
+ local data={}
+ while true do
+ local r=f:read(step)
+ if not r then
+ return concat(data)
+ else
+ data[#data+1]=r
+ end
+ end
+ end
+end
+io.readall=readall
+function io.loaddata(filename,textmode)
+ local f=io.open(filename,(textmode and 'r') or 'rb')
+ if f then
+ local data=readall(f)
+ f:close()
+ if #data>0 then
+ return data
+ end
+ end
end
-
-local function identical(a,b) -- assumes same structure
- for ka, va in next, a do
- local vb = b[ka]
- if va == vb then
- -- same
- elseif type(va) == "table" and type(vb) == "table" then
- if not identical(va,vb) then
- return false
- end
- else
- return false
- end
+function io.savedata(filename,data,joiner)
+ local f=io.open(filename,"wb")
+ if f then
+ if type(data)=="table" then
+ f:write(concat(data,joiner or ""))
+ elseif type(data)=="function" then
+ data(f)
+ else
+ f:write(data or "")
end
+ f:close()
+ io.flush()
return true
+ else
+ return false
+ end
+end
+function io.loadlines(filename,n)
+ local f=io.open(filename,'r')
+ if not f then
+ elseif n then
+ local lines={}
+ for i=1,n do
+ local line=f:read("*lines")
+ if line then
+ lines[#lines+1]=line
+ else
+ break
+ end
+ end
+ f:close()
+ lines=concat(lines,"\n")
+ if #lines>0 then
+ return lines
+ end
+ else
+ local line=f:read("*line") or ""
+ f:close()
+ if #line>0 then
+ return line
+ end
+ end
+end
+function io.loadchunk(filename,n)
+ local f=io.open(filename,'rb')
+ if f then
+ local data=f:read(n or 1024)
+ f:close()
+ if #data>0 then
+ return data
+ end
+ end
end
-
-table.identical = identical
-table.are_equal = are_equal
-
--- maybe also make a combined one
-
-function table.compact(t)
- if t then
- for k,v in next, t do
- if not next(v) then
- t[k] = nil
- end
- end
- end
-end
-
-function table.contains(t, v)
- if t then
- for i=1, #t do
- if t[i] == v then
- return i
- end
- end
- end
+function io.exists(filename)
+ local f=io.open(filename)
+ if f==nil then
return false
+ else
+ f:close()
+ return true
+ end
end
-
-function table.count(t)
- local n = 0
- for k, v in next, t do
- n = n + 1
- end
- return n
+function io.size(filename)
+ local f=io.open(filename)
+ if f==nil then
+ return 0
+ else
+ local s=f:seek("end")
+ f:close()
+ return s
+ end
end
-
-function table.swapped(t,s) -- hash
- local n = { }
- if s then
- for k, v in next, s do
- n[k] = v
- end
+function io.noflines(f)
+ if type(f)=="string" then
+ local f=io.open(filename)
+ if f then
+ local n=f and io.noflines(f) or 0
+ f:close()
+ return n
+ else
+ return 0
end
- for k, v in next, t do
- n[v] = k
+ else
+ local n=0
+ for _ in f:lines() do
+ n=n+1
end
+ f:seek('set',0)
return n
+ end
+end
+local nextchar={
+ [ 4]=function(f)
+ return f:read(1,1,1,1)
+ end,
+ [ 2]=function(f)
+ return f:read(1,1)
+ end,
+ [ 1]=function(f)
+ return f:read(1)
+ end,
+ [-2]=function(f)
+ local a,b=f:read(1,1)
+ return b,a
+ end,
+ [-4]=function(f)
+ local a,b,c,d=f:read(1,1,1,1)
+ return d,c,b,a
+ end
+}
+function io.characters(f,n)
+ if f then
+ return nextchar[n or 1],f
+ end
end
-
-function table.reversed(t)
- if t then
- local tt, tn = { }, #t
- if tn > 0 then
- local ttn = 0
- for i=tn,1,-1 do
- ttn = ttn + 1
- tt[ttn] = t[i]
- end
- end
- return tt
+local nextbyte={
+ [4]=function(f)
+ local a,b,c,d=f:read(1,1,1,1)
+ if d then
+ return byte(a),byte(b),byte(c),byte(d)
+ end
+ end,
+ [3]=function(f)
+ local a,b,c=f:read(1,1,1)
+ if b then
+ return byte(a),byte(b),byte(c)
+ end
+ end,
+ [2]=function(f)
+ local a,b=f:read(1,1)
+ if b then
+ return byte(a),byte(b)
+ end
+ end,
+ [1]=function (f)
+ local a=f:read(1)
+ if a then
+ return byte(a)
+ end
+ end,
+ [-2]=function (f)
+ local a,b=f:read(1,1)
+ if b then
+ return byte(b),byte(a)
+ end
+ end,
+ [-3]=function(f)
+ local a,b,c=f:read(1,1,1)
+ if b then
+ return byte(c),byte(b),byte(a)
+ end
+ end,
+ [-4]=function(f)
+ local a,b,c,d=f:read(1,1,1,1)
+ if d then
+ return byte(d),byte(c),byte(b),byte(a)
end
+ end
+}
+function io.bytes(f,n)
+ if f then
+ return nextbyte[n or 1],f
+ else
+ return nil,nil
+ end
end
-
-function table.sequenced(t,sep,simple) -- hash only
- local s, n = { }, 0
- for k, v in sortedhash(t) do
- if simple then
- if v == true then
- n = n + 1
- s[n] = k
- elseif v and v~= "" then
- n = n + 1
- s[n] = k .. "=" .. tostring(v)
- end
- else
- n = n + 1
- s[n] = k .. "=" .. tostring(v)
+function io.ask(question,default,options)
+ while true do
+ io.write(question)
+ if options then
+ io.write(format(" [%s]",concat(options,"|")))
+ end
+ if default then
+ io.write(format(" [%s]",default))
+ end
+ io.write(format(" "))
+ io.flush()
+ local answer=io.read()
+ answer=gsub(answer,"^%s*(.*)%s*$","%1")
+ if answer=="" and default then
+ return default
+ elseif not options then
+ return answer
+ else
+ for k=1,#options do
+ if options[k]==answer then
+ return answer
+ end
+ end
+ local pattern="^"..answer
+ for k=1,#options do
+ local v=options[k]
+ if find(v,pattern) then
+ return v
end
+ end
end
- return concat(s, sep or " | ")
+ end
end
-
-function table.print(t,...)
- if type(t) ~= "table" then
- print(tostring(t))
- else
- table.tohandle(print,t,...)
- end
+local function readnumber(f,n,m)
+ if m then
+ f:seek("set",n)
+ n=m
+ end
+ if n==1 then
+ return byte(f:read(1))
+ elseif n==2 then
+ local a,b=byte(f:read(2),1,2)
+ return 256*a+b
+ elseif n==3 then
+ local a,b,c=byte(f:read(3),1,3)
+ return 256*256*a+256*b+c
+ elseif n==4 then
+ local a,b,c,d=byte(f:read(4),1,4)
+ return 256*256*256*a+256*256*b+256*c+d
+ elseif n==8 then
+ local a,b=readnumber(f,4),readnumber(f,4)
+ return 256*a+b
+ elseif n==12 then
+ local a,b,c=readnumber(f,4),readnumber(f,4),readnumber(f,4)
+ return 256*256*a+256*b+c
+ elseif n==-2 then
+ local b,a=byte(f:read(2),1,2)
+ return 256*a+b
+ elseif n==-3 then
+ local c,b,a=byte(f:read(3),1,3)
+ return 256*256*a+256*b+c
+ elseif n==-4 then
+ local d,c,b,a=byte(f:read(4),1,4)
+ return 256*256*256*a+256*256*b+256*c+d
+ elseif n==-8 then
+ local h,g,f,e,d,c,b,a=byte(f:read(8),1,8)
+ return 256*256*256*256*256*256*256*a+256*256*256*256*256*256*b+256*256*256*256*256*c+256*256*256*256*d+256*256*256*e+256*256*f+256*g+h
+ else
+ return 0
+ end
end
-
--- -- -- obsolete but we keep them for a while and might comment them later -- -- --
-
--- roughly: copy-loop : unpack : sub == 0.9 : 0.4 : 0.45 (so in critical apps, use unpack)
-
-function table.sub(t,i,j)
- return { unpack(t,i,j) }
+io.readnumber=readnumber
+function io.readstring(f,n,m)
+ if m then
+ f:seek("set",n)
+ n=m
+ end
+ local str=gsub(f:read(n),"\000","")
+ return str
end
+if not io.i_limiter then function io.i_limiter() end end
+if not io.o_limiter then function io.o_limiter() end end
--- slower than #t on indexed tables (#t only returns the size of the numerically indexed slice)
-
-function table.is_empty(t)
- return not t or not next(t)
-end
-function table.has_one_entry(t)
- return t and not next(t,next(t))
-end
+end -- of closure
--- new
+do -- create closure to overcome 200 locals limit
-function table.loweredkeys(t) -- maybe utf
- local l = { }
- for k, v in next, t do
- l[lower(k)] = v
- end
- return l
-end
+package.loaded["l-number"] = package.loaded["l-number"] or true
--- new, might move (maybe duplicate)
+-- original size: 4939, stripped down to: 2830
-function table.unique(old)
- local hash = { }
- local new = { }
- local n = 0
- for i=1,#old do
- local oi = old[i]
- if not hash[oi] then
- n = n + 1
- new[n] = oi
- hash[oi] = true
- end
+if not modules then modules={} end modules ['l-number']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local tostring,tonumber=tostring,tonumber
+local format,floor,match,rep=string.format,math.floor,string.match,string.rep
+local concat,insert=table.concat,table.insert
+local lpegmatch=lpeg.match
+number=number or {}
+local number=number
+if bit32 then
+ local btest,bor=bit32.btest,bit32.bor
+ function number.bit(p)
+ return 2^(p-1)
+ end
+ number.hasbit=btest
+ number.setbit=bor
+ function number.setbit(x,p)
+ return btest(x,p) and x or x+p
+ end
+ function number.clearbit(x,p)
+ return btest(x,p) and x-p or x
+ end
+else
+ function number.bit(p)
+ return 2^(p-1)
+ end
+ function number.hasbit(x,p)
+ return x%(p+p)>=p
+ end
+ function number.setbit(x,p)
+ return (x%(p+p)>=p) and x or x+p
+ end
+ function number.clearbit(x,p)
+ return (x%(p+p)>=p) and x-p or x
+ end
+end
+if bit32 then
+ local bextract=bit32.extract
+ local t={
+ "0","0","0","0","0","0","0","0",
+ "0","0","0","0","0","0","0","0",
+ "0","0","0","0","0","0","0","0",
+ "0","0","0","0","0","0","0","0",
+ }
+ function number.tobitstring(b,m)
+ local n=32
+ for i=0,31 do
+ local v=bextract(b,i)
+ local k=32-i
+ if v==1 then
+ n=k
+ t[k]="1"
+ else
+ t[k]="0"
+ end
end
- return new
-end
-
--- function table.sorted(t,...)
--- table.sort(t,...)
--- return t -- still sorts in-place
--- end
+ if m then
+ m=33-m*8
+ if m<1 then
+ m=1
+ end
+ return concat(t,"",m)
+ elseif n<8 then
+ return concat(t)
+ elseif n<16 then
+ return concat(t,"",9)
+ elseif n<24 then
+ return concat(t,"",17)
+ else
+ return concat(t,"",25)
+ end
+ end
+else
+ function number.tobitstring(n,m)
+ if n>0 then
+ local t={}
+ while n>0 do
+ insert(t,1,n%2>0 and 1 or 0)
+ n=floor(n/2)
+ end
+ local nn=8-#t%8
+ if nn>0 and nn<8 then
+ for i=1,nn do
+ insert(t,1,0)
+ end
+ end
+ if m then
+ m=m*8-#t
+ if m>0 then
+ insert(t,1,rep("0",m))
+ end
+ end
+ return concat(t)
+ elseif m then
+ rep("00000000",m)
+ else
+ return "00000000"
+ end
+ end
+end
+function number.valid(str,default)
+ return tonumber(str) or default or nil
+end
+function number.toevenhex(n)
+ local s=format("%X",n)
+ if #s%2==0 then
+ return s
+ else
+ return "0"..s
+ end
+end
+local one=lpeg.C(1-lpeg.S('')/tonumber)^1
+function number.toset(n)
+ return lpegmatch(one,tostring(n))
+end
+local function bits(n,i,...)
+ if n>0 then
+ local m=n%2
+ local n=floor(n/2)
+ if m>0 then
+ return bits(n,i+1,i,...)
+ else
+ return bits(n,i+1,...)
+ end
+ else
+ return...
+ end
+end
+function number.bits(n)
+ return { bits(n,1) }
+end
end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-lpeg'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
+package.loaded["l-set"] = package.loaded["l-set"] or true
--- a new lpeg fails on a #(1-P(":")) test and really needs a + P(-1)
-
-local lpeg = require("lpeg")
-
--- tracing (only used when we encounter a problem in integration of lpeg in luatex)
-
-local report = texio and texio.write_nl or print
-
--- local lpmatch = lpeg.match
--- local lpprint = lpeg.print
--- local lpp = lpeg.P
--- local lpr = lpeg.R
--- local lps = lpeg.S
--- local lpc = lpeg.C
--- local lpb = lpeg.B
--- local lpv = lpeg.V
--- local lpcf = lpeg.Cf
--- local lpcb = lpeg.Cb
--- local lpcg = lpeg.Cg
--- local lpct = lpeg.Ct
--- local lpcs = lpeg.Cs
--- local lpcc = lpeg.Cc
--- local lpcmt = lpeg.Cmt
--- local lpcarg = lpeg.Carg
-
--- function lpeg.match(l,...) report("LPEG MATCH") lpprint(l) return lpmatch(l,...) end
-
--- function lpeg.P (l) local p = lpp (l) report("LPEG P =") lpprint(l) return p end
--- function lpeg.R (l) local p = lpr (l) report("LPEG R =") lpprint(l) return p end
--- function lpeg.S (l) local p = lps (l) report("LPEG S =") lpprint(l) return p end
--- function lpeg.C (l) local p = lpc (l) report("LPEG C =") lpprint(l) return p end
--- function lpeg.B (l) local p = lpb (l) report("LPEG B =") lpprint(l) return p end
--- function lpeg.V (l) local p = lpv (l) report("LPEG V =") lpprint(l) return p end
--- function lpeg.Cf (l) local p = lpcf (l) report("LPEG Cf =") lpprint(l) return p end
--- function lpeg.Cb (l) local p = lpcb (l) report("LPEG Cb =") lpprint(l) return p end
--- function lpeg.Cg (l) local p = lpcg (l) report("LPEG Cg =") lpprint(l) return p end
--- function lpeg.Ct (l) local p = lpct (l) report("LPEG Ct =") lpprint(l) return p end
--- function lpeg.Cs (l) local p = lpcs (l) report("LPEG Cs =") lpprint(l) return p end
--- function lpeg.Cc (l) local p = lpcc (l) report("LPEG Cc =") lpprint(l) return p end
--- function lpeg.Cmt (l) local p = lpcmt (l) report("LPEG Cmt =") lpprint(l) return p end
--- function lpeg.Carg (l) local p = lpcarg(l) report("LPEG Carg =") lpprint(l) return p end
-
-local type = type
-local byte, char, gmatch = string.byte, string.char, string.gmatch
-
--- Beware, we predefine a bunch of patterns here and one reason for doing so
--- is that we get consistent behaviour in some of the visualizers.
-
-lpeg.patterns = lpeg.patterns or { } -- so that we can share
-local patterns = lpeg.patterns
-
-local P, R, S, V, match = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.match
-local Ct, C, Cs, Cc = lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc
-local lpegtype = lpeg.type
-
-local utfcharacters = string.utfcharacters
-local utfgmatch = unicode and unicode.utf8.gmatch
-
-local anything = P(1)
-local endofstring = P(-1)
-local alwaysmatched = P(true)
-
-patterns.anything = anything
-patterns.endofstring = endofstring
-patterns.beginofstring = alwaysmatched
-patterns.alwaysmatched = alwaysmatched
-
-local digit, sign = R('09'), S('+-')
-local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
-local newline = crlf + S("\r\n") -- cr + lf
-local escaped = P("\\") * anything
-local squote = P("'")
-local dquote = P('"')
-local space = P(" ")
-
-local utfbom_32_be = P('\000\000\254\255')
-local utfbom_32_le = P('\255\254\000\000')
-local utfbom_16_be = P('\255\254')
-local utfbom_16_le = P('\254\255')
-local utfbom_8 = P('\239\187\191')
-local utfbom = utfbom_32_be + utfbom_32_le
- + utfbom_16_be + utfbom_16_le
- + utfbom_8
-local utftype = utfbom_32_be / "utf-32-be" + utfbom_32_le / "utf-32-le"
- + utfbom_16_be / "utf-16-be" + utfbom_16_le / "utf-16-le"
- + utfbom_8 / "utf-8" + alwaysmatched / "unknown"
-
-local utf8next = R("\128\191")
-
-patterns.utf8one = R("\000\127")
-patterns.utf8two = R("\194\223") * utf8next
-patterns.utf8three = R("\224\239") * utf8next * utf8next
-patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
-patterns.utfbom = utfbom
-patterns.utftype = utftype
-
-local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
-local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
-
-patterns.utf8 = utf8char
-patterns.utf8char = utf8char
-patterns.validutf8 = validutf8char
-patterns.validutf8char = validutf8char
-
-patterns.digit = digit
-patterns.sign = sign
-patterns.cardinal = sign^0 * digit^1
-patterns.integer = sign^0 * digit^1
-patterns.float = sign^0 * digit^0 * P('.') * digit^1
-patterns.cfloat = sign^0 * digit^0 * P(',') * digit^1
-patterns.number = patterns.float + patterns.integer
-patterns.cnumber = patterns.cfloat + patterns.integer
-patterns.oct = P("0") * R("07")^1
-patterns.octal = patterns.oct
-patterns.HEX = P("0x") * R("09","AF")^1
-patterns.hex = P("0x") * R("09","af")^1
-patterns.hexadecimal = P("0x") * R("09","AF","af")^1
-patterns.lowercase = R("az")
-patterns.uppercase = R("AZ")
-patterns.letter = patterns.lowercase + patterns.uppercase
-patterns.space = space
-patterns.tab = P("\t")
-patterns.spaceortab = patterns.space + patterns.tab
-patterns.eol = S("\n\r")
-patterns.spacer = S(" \t\f\v") -- + char(0xc2, 0xa0) if we want utf (cf mail roberto)
-patterns.newline = newline
-patterns.emptyline = newline^1
-patterns.nonspacer = 1 - patterns.spacer
-patterns.whitespace = patterns.eol + patterns.spacer
-patterns.nonwhitespace = 1 - patterns.whitespace
-patterns.equal = P("=")
-patterns.comma = P(",")
-patterns.commaspacer = P(",") * patterns.spacer^0
-patterns.period = P(".")
-patterns.colon = P(":")
-patterns.semicolon = P(";")
-patterns.underscore = P("_")
-patterns.escaped = escaped
-patterns.squote = squote
-patterns.dquote = dquote
-patterns.nosquote = (escaped + (1-squote))^0
-patterns.nodquote = (escaped + (1-dquote))^0
-patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"")
-patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
-patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
-patterns.unspacer = ((patterns.spacer^1)/"")^0
-
-patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
-patterns.beginline = #(1-newline)
-
--- print(string.unquoted("test"))
--- print(string.unquoted([["t\"est"]]))
--- print(string.unquoted([["t\"est"x]]))
--- print(string.unquoted("\'test\'"))
--- print(string.unquoted('"test"'))
--- print(string.unquoted('"test"'))
-
-function lpeg.anywhere(pattern) --slightly adapted from website
- return P { P(pattern) + 1 * V(1) } -- why so complex?
-end
-
-function lpeg.splitter(pattern, action)
- return (((1-P(pattern))^1)/action+1)^0
-end
-
-function lpeg.tsplitter(pattern, action)
- return Ct((((1-P(pattern))^1)/action+1)^0)
-end
-
--- probleem: separator can be lpeg and that does not hash too well, but
--- it's quite okay as the key is then not garbage collected
-
-local splitters_s, splitters_m, splitters_t = { }, { }, { }
-
-local function splitat(separator,single)
- local splitter = (single and splitters_s[separator]) or splitters_m[separator]
- if not splitter then
- separator = P(separator)
- local other = C((1 - separator)^0)
- if single then
- local any = anything
- splitter = other * (separator * C(any^0) + "") -- ?
- splitters_s[separator] = splitter
- else
- splitter = other * (separator * other)^0
- splitters_m[separator] = splitter
- end
- end
- return splitter
-end
+-- original size: 1923, stripped down to: 1133
-local function tsplitat(separator)
- local splitter = splitters_t[separator]
- if not splitter then
- splitter = Ct(splitat(separator))
- splitters_t[separator] = splitter
+if not modules then modules={} end modules ['l-set']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+set=set or {}
+local nums={}
+local tabs={}
+local concat=table.concat
+local next,type=next,type
+set.create=table.tohash
+function set.tonumber(t)
+ if next(t) then
+ local s=""
+ for k,v in next,t do
+ if v then
+ s=s.." "..k
+ end
+ end
+ local n=nums[s]
+ if not n then
+ n=#tabs+1
+ tabs[n]=t
+ nums[s]=n
end
- return splitter
+ return n
+ else
+ return 0
+ end
end
-
-lpeg.splitat = splitat
-lpeg.tsplitat = tsplitat
-
-function string.splitup(str,separator)
- if not separator then
- separator = ","
- end
- return match(splitters_m[separator] or splitat(separator),str)
+function set.totable(n)
+ if n==0 then
+ return {}
+ else
+ return tabs[n] or {}
+ end
end
-
-
-local cache = { }
-
-function lpeg.split(separator,str)
- local c = cache[separator]
- if not c then
- c = tsplitat(separator)
- cache[separator] = c
+function set.tolist(n)
+ if n==0 or not tabs[n] then
+ return ""
+ else
+ local t,n={},0
+ for k,v in next,tabs[n] do
+ if v then
+ n=n+1
+ t[n]=k
+ end
end
- return match(c,str)
+ return concat(t," ")
+ end
end
-
-function string.split(str,separator)
- local c = cache[separator]
- if not c then
- c = tsplitat(separator)
- cache[separator] = c
- end
- return match(c,str)
+function set.contains(n,s)
+ if type(n)=="table" then
+ return n[s]
+ elseif n==0 then
+ return false
+ else
+ local t=tabs[n]
+ return t and t[s]
+ end
end
-local spacing = patterns.spacer^0 * newline -- sort of strip
-local empty = spacing * Cc("")
-local nonempty = Cs((1-spacing)^1) * spacing^-1
-local content = (empty + nonempty)^1
-patterns.textline = content
+end -- of closure
+do -- create closure to overcome 200 locals limit
-local linesplitter = tsplitat(newline)
+package.loaded["l-os"] = package.loaded["l-os"] or true
-patterns.linesplitter = linesplitter
+-- original size: 13692, stripped down to: 8406
-function string.splitlines(str)
- return match(linesplitter,str)
+if not modules then modules={} end modules ['l-os']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local os=os
+local date,time=os.date,os.time
+local find,format,gsub,upper,gmatch=string.find,string.format,string.gsub,string.upper,string.gmatch
+local concat=table.concat
+local random,ceil,randomseed=math.random,math.ceil,math.randomseed
+local rawget,rawset,type,getmetatable,setmetatable,tonumber,tostring=rawget,rawset,type,getmetatable,setmetatable,tonumber,tostring
+math.initialseed=tonumber(string.sub(string.reverse(tostring(ceil(socket and socket.gettime()*10000 or time()))),1,6))
+randomseed(math.initialseed)
+if not os.__getenv__ then
+ os.__getenv__=os.getenv
+ os.__setenv__=os.setenv
+ if os.env then
+ local osgetenv=os.getenv
+ local ossetenv=os.setenv
+ local osenv=os.env local _=osenv.PATH
+ function os.setenv(k,v)
+ if v==nil then
+ v=""
+ end
+ local K=upper(k)
+ osenv[K]=v
+ if type(v)=="table" then
+ v=concat(v,";")
+ end
+ ossetenv(K,v)
+ end
+ function os.getenv(k)
+ local K=upper(k)
+ local v=osenv[K] or osenv[k] or osgetenv(K) or osgetenv(k)
+ if v=="" then
+ return nil
+ else
+ return v
+ end
+ end
+ else
+ local ossetenv=os.setenv
+ local osgetenv=os.getenv
+ local osenv={}
+ function os.setenv(k,v)
+ if v==nil then
+ v=""
+ end
+ local K=upper(k)
+ osenv[K]=v
+ end
+ function os.getenv(k)
+ local K=upper(k)
+ local v=osenv[K] or osgetenv(K) or osgetenv(k)
+ if v=="" then
+ return nil
+ else
+ return v
+ end
+ end
+ local function __index(t,k)
+ return os.getenv(k)
+ end
+ local function __newindex(t,k,v)
+ os.setenv(k,v)
+ end
+ os.env={}
+ setmetatable(os.env,{ __index=__index,__newindex=__newindex } )
+ end
end
-
-local utflinesplitter = utfbom^-1 * tsplitat(newline)
-
-patterns.utflinesplitter = utflinesplitter
-
-function string.utfsplitlines(str)
- return match(utflinesplitter,str or "")
+local execute,spawn,exec,iopopen,ioflush=os.execute,os.spawn or os.execute,os.exec or os.execute,io.popen,io.flush
+function os.execute(...) ioflush() return execute(...) end
+function os.spawn (...) ioflush() return spawn (...) end
+function os.exec (...) ioflush() return exec (...) end
+function io.popen (...) ioflush() return iopopen(...) end
+function os.resultof(command)
+ local handle=io.popen(command,"r")
+ return handle and handle:read("*all") or ""
end
-
-
-local cache = { }
-
-function lpeg.checkedsplit(separator,str)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
+if not io.fileseparator then
+ if find(os.getenv("PATH"),";") then
+ io.fileseparator,io.pathseparator,os.type="\\",";",os.type or "mswin"
+ else
+ io.fileseparator,io.pathseparator,os.type="/",":",os.type or "unix"
+ end
+end
+os.type=os.type or (io.pathseparator==";" and "windows") or "unix"
+os.name=os.name or (os.type=="windows" and "mswin" ) or "linux"
+if os.type=="windows" then
+ os.libsuffix,os.binsuffix,os.binsuffixes='dll','exe',{ 'exe','cmd','bat' }
+else
+ os.libsuffix,os.binsuffix,os.binsuffixes='so','',{ '' }
+end
+local launchers={
+ windows="start %s",
+ macosx="open %s",
+ unix="$BROWSER %s &> /dev/null &",
+}
+function os.launch(str)
+ os.execute(format(launchers[os.name] or launchers.unix,str))
+end
+if not os.times then
+ function os.times()
+ return {
+ utime=os.gettimeofday(),
+ stime=0,
+ cutime=0,
+ cstime=0,
+ }
+ end
+end
+os.gettimeofday=os.gettimeofday or os.clock
+local startuptime=os.gettimeofday()
+function os.runtime()
+ return os.gettimeofday()-startuptime
+end
+os.resolvers=os.resolvers or {}
+local resolvers=os.resolvers
+setmetatable(os,{ __index=function(t,k)
+ local r=resolvers[k]
+ return r and r(t,k) or nil
+end })
+local name,platform=os.name or "linux",os.getenv("MTX_PLATFORM") or ""
+local function guess()
+ local architecture=os.resultof("uname -m") or ""
+ if architecture~="" then
+ return architecture
+ end
+ architecture=os.getenv("HOSTTYPE") or ""
+ if architecture~="" then
+ return architecture
+ end
+ return os.resultof("echo $HOSTTYPE") or ""
+end
+if platform~="" then
+ os.platform=platform
+elseif os.type=="windows" then
+ function os.resolvers.platform(t,k)
+ local platform,architecture="",os.getenv("PROCESSOR_ARCHITECTURE") or ""
+ if find(architecture,"AMD64") then
+ platform="mswin-64"
+ else
+ platform="mswin"
+ end
+ os.setenv("MTX_PLATFORM",platform)
+ os.platform=platform
+ return platform
+ end
+elseif name=="linux" then
+ function os.resolvers.platform(t,k)
+ local platform,architecture="",os.getenv("HOSTTYPE") or os.resultof("uname -m") or ""
+ if find(architecture,"x86_64") then
+ platform="linux-64"
+ elseif find(architecture,"ppc") then
+ platform="linux-ppc"
+ else
+ platform="linux"
+ end
+ os.setenv("MTX_PLATFORM",platform)
+ os.platform=platform
+ return platform
+ end
+elseif name=="macosx" then
+ function os.resolvers.platform(t,k)
+ local platform,architecture="",os.resultof("echo $HOSTTYPE") or ""
+ if architecture=="" then
+ platform="osx-intel"
+ elseif find(architecture,"i386") then
+ platform="osx-intel"
+ elseif find(architecture,"x86_64") then
+ platform="osx-64"
+ else
+ platform="osx-ppc"
+ end
+ os.setenv("MTX_PLATFORM",platform)
+ os.platform=platform
+ return platform
+ end
+elseif name=="sunos" then
+ function os.resolvers.platform(t,k)
+ local platform,architecture="",os.resultof("uname -m") or ""
+ if find(architecture,"sparc") then
+ platform="solaris-sparc"
+ else
+ platform="solaris-intel"
+ end
+ os.setenv("MTX_PLATFORM",platform)
+ os.platform=platform
+ return platform
+ end
+elseif name=="freebsd" then
+ function os.resolvers.platform(t,k)
+ local platform,architecture="",os.resultof("uname -m") or ""
+ if find(architecture,"amd64") then
+ platform="freebsd-amd64"
+ else
+ platform="freebsd"
+ end
+ os.setenv("MTX_PLATFORM",platform)
+ os.platform=platform
+ return platform
+ end
+elseif name=="kfreebsd" then
+ function os.resolvers.platform(t,k)
+ local platform,architecture="",os.getenv("HOSTTYPE") or os.resultof("uname -m") or ""
+ if find(architecture,"x86_64") then
+ platform="kfreebsd-amd64"
+ else
+ platform="kfreebsd-i386"
end
- return match(c,str)
+ os.setenv("MTX_PLATFORM",platform)
+ os.platform=platform
+ return platform
+ end
+else
+ function os.resolvers.platform(t,k)
+ local platform="linux"
+ os.setenv("MTX_PLATFORM",platform)
+ os.platform=platform
+ return platform
+ end
+end
+local t={ 8,9,"a","b" }
+function os.uuid()
+ return format("%04x%04x-4%03x-%s%03x-%04x-%04x%04x%04x",
+ random(0xFFFF),random(0xFFFF),
+ random(0x0FFF),
+ t[ceil(random(4))] or 8,random(0x0FFF),
+ random(0xFFFF),
+ random(0xFFFF),random(0xFFFF),random(0xFFFF)
+ )
end
-
-function string.checkedsplit(str,separator)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
+local d
+function os.timezone(delta)
+ d=d or tonumber(tonumber(date("%H")-date("!%H")))
+ if delta then
+ if d>0 then
+ return format("+%02i:00",d)
+ else
+ return format("-%02i:00",-d)
+ end
+ else
+ return 1
+ end
+end
+local timeformat=format("%%s%s",os.timezone(true))
+local dateformat="!%Y-%m-%d %H:%M:%S"
+function os.fulltime(t,default)
+ t=tonumber(t) or 0
+ if t>0 then
+ elseif default then
+ return default
+ else
+ t=nil
+ end
+ return format(timeformat,date(dateformat,t))
+end
+local dateformat="%Y-%m-%d %H:%M:%S"
+function os.localtime(t,default)
+ t=tonumber(t) or 0
+ if t>0 then
+ elseif default then
+ return default
+ else
+ t=nil
+ end
+ return date(dateformat,t)
+end
+function os.converttime(t,default)
+ local t=tonumber(t)
+ if t and t>0 then
+ return date(dateformat,t)
+ else
+ return default or "-"
+ end
+end
+local memory={}
+local function which(filename)
+ local fullname=memory[filename]
+ if fullname==nil then
+ local suffix=file.suffix(filename)
+ local suffixes=suffix=="" and os.binsuffixes or { suffix }
+ for directory in gmatch(os.getenv("PATH"),"[^"..io.pathseparator.."]+") do
+ local df=file.join(directory,filename)
+ for i=1,#suffixes do
+ local dfs=file.addsuffix(df,suffixes[i])
+ if io.exists(dfs) then
+ fullname=dfs
+ break
+ end
+ end
end
- return match(c,str)
+ if not fullname then
+ fullname=false
+ end
+ memory[filename]=fullname
+ end
+ return fullname
+end
+os.which=which
+os.where=which
+function os.today()
+ return date("!*t")
+end
+function os.now()
+ return date("!%Y-%m-%d %H:%M:%S")
+end
+if not os.sleep and socket then
+ os.sleep=socket.sleep
end
-local function f2(s) local c1, c2 = byte(s,1,2) return c1 * 64 + c2 - 12416 end
-local function f3(s) local c1, c2, c3 = byte(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
-local function f4(s) local c1, c2, c3, c4 = byte(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
-
-local utf8byte = patterns.utf8one/byte + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
-
-patterns.utf8byte = utf8byte
+end -- of closure
+do -- create closure to overcome 200 locals limit
+package.loaded["l-file"] = package.loaded["l-file"] or true
-local cache = { }
+-- original size: 16648, stripped down to: 9051
-function lpeg.stripper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs(((S(str)^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs(((str^1)/"" + 1)^0)
- end
+if not modules then modules={} end modules ['l-file']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+file=file or {}
+local file=file
+if not lfs then
+ lfs=optionalrequire("lfs")
+end
+if not lfs then
+ lfs={
+ getcurrentdir=function()
+ return "."
+ end,
+ attributes=function()
+ return nil
+ end,
+ isfile=function(name)
+ local f=io.open(name,'rb')
+ if f then
+ f:close()
+ return true
+ end
+ end,
+ isdir=function(name)
+ print("you need to load lfs")
+ return false
+ end
+ }
+elseif not lfs.isfile then
+ local attributes=lfs.attributes
+ function lfs.isdir(name)
+ return attributes(name,"mode")=="directory"
+ end
+ function lfs.isfile(name)
+ return attributes(name,"mode")=="file"
+ end
+end
+local insert,concat=table.insert,table.concat
+local match=string.match
+local lpegmatch=lpeg.match
+local getcurrentdir,attributes=lfs.currentdir,lfs.attributes
+local checkedsplit=string.checkedsplit
+local P,R,S,C,Cs,Cp,Cc,Ct=lpeg.P,lpeg.R,lpeg.S,lpeg.C,lpeg.Cs,lpeg.Cp,lpeg.Cc,lpeg.Ct
+local colon=P(":")
+local period=P(".")
+local periods=P("..")
+local fwslash=P("/")
+local bwslash=P("\\")
+local slashes=S("\\/")
+local noperiod=1-period
+local noslashes=1-slashes
+local name=noperiod^1
+local suffix=period/""*(1-period-slashes)^1*-1
+local pattern=C((1-(slashes^1*noslashes^1*-1))^1)*P(1)
+local function pathpart(name,default)
+ return name and lpegmatch(pattern,name) or default or ""
+end
+local pattern=(noslashes^0*slashes)^1*C(noslashes^1)*-1
+local function basename(name)
+ return name and lpegmatch(pattern,name) or name
end
-
-local cache = { }
-
-function lpeg.keeper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs((((1-S(str))^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
+local pattern=(noslashes^0*slashes^1)^0*Cs((1-suffix)^1)*suffix^0
+local function nameonly(name)
+ return name and lpegmatch(pattern,name) or name
+end
+local pattern=(noslashes^0*slashes)^0*(noperiod^1*period)^1*C(noperiod^1)*-1
+local function suffixonly(name)
+ return name and lpegmatch(pattern,name) or ""
+end
+file.pathpart=pathpart
+file.basename=basename
+file.nameonly=nameonly
+file.suffixonly=suffixonly
+file.suffix=suffixonly
+file.dirname=pathpart
+file.extname=suffixonly
+local drive=C(R("az","AZ"))*colon
+local path=C((noslashes^0*slashes)^0)
+local suffix=period*C(P(1-period)^0*P(-1))
+local base=C((1-suffix)^0)
+local rest=C(P(1)^0)
+drive=drive+Cc("")
+path=path+Cc("")
+base=base+Cc("")
+suffix=suffix+Cc("")
+local pattern_a=drive*path*base*suffix
+local pattern_b=path*base*suffix
+local pattern_c=C(drive*path)*C(base*suffix)
+local pattern_d=path*rest
+function file.splitname(str,splitdrive)
+ if not str then
+ elseif splitdrive then
+ return lpegmatch(pattern_a,str)
+ else
+ return lpegmatch(pattern_b,str)
+ end
+end
+function file.splitbase(str)
+ return str and lpegmatch(pattern_d,str)
+end
+function file.nametotable(str,splitdrive)
+ if str then
+ local path,drive,subpath,name,base,suffix=lpegmatch(pattern_c,str)
+ if splitdrive then
+ return {
+ path=path,
+ drive=drive,
+ subpath=subpath,
+ name=name,
+ base=base,
+ suffix=suffix,
+ }
else
- return Cs((((1-str)^1)/"" + 1)^0)
+ return {
+ path=path,
+ name=name,
+ base=base,
+ suffix=suffix,
+ }
+ end
+ end
+end
+local pattern=Cs(((period*(1-period-slashes)^1*-1)/""+1)^1)
+function file.removesuffix(name)
+ return name and lpegmatch(pattern,name)
+end
+local suffix=period/""*(1-period-slashes)^1*-1
+local pattern=Cs((noslashes^0*slashes^1)^0*((1-suffix)^1))*Cs(suffix)
+function file.addsuffix(filename,suffix,criterium)
+ if not filename or not suffix or suffix=="" then
+ return filename
+ elseif criterium==true then
+ return filename.."."..suffix
+ elseif not criterium then
+ local n,s=lpegmatch(pattern,filename)
+ if not s or s=="" then
+ return filename.."."..suffix
+ else
+ return filename
+ end
+ else
+ local n,s=lpegmatch(pattern,filename)
+ if s and s~="" then
+ local t=type(criterium)
+ if t=="table" then
+ for i=1,#criterium do
+ if s==criterium[i] then
+ return filename
+ end
+ end
+ elseif t=="string" then
+ if s==criterium then
+ return filename
+ end
+ end
end
+ return (n or filename).."."..suffix
+ end
end
-
-function lpeg.frontstripper(str) -- or pattern (yet undocumented)
- return (P(str) + P(true)) * Cs(P(1)^0)
+local suffix=period*(1-period-slashes)^1*-1
+local pattern=Cs((1-suffix)^0)
+function file.replacesuffix(name,suffix)
+ if name and suffix and suffix~="" then
+ return lpegmatch(pattern,name).."."..suffix
+ else
+ return name
+ end
end
-
-function lpeg.endstripper(str) -- or pattern (yet undocumented)
- return Cs((1 - P(str) * P(-1))^0)
+local reslasher=lpeg.replacer(P("\\"),"/")
+function file.reslash(str)
+ return str and lpegmatch(reslasher,str)
end
-
--- Just for fun I looked at the used bytecode and
--- p = (p and p + pp) or pp gets one more (testset).
-
-function lpeg.replacer(one,two)
- if type(one) == "table" then
- local no = #one
- if no > 0 then
- local p
- for i=1,no do
- local o = one[i]
- local pp = P(o[1]) / o[2]
- if p then
- p = p + pp
- else
- p = pp
- end
- end
- return Cs((p + 1)^0)
- end
- else
- two = two or ""
- return Cs((P(one)/two + 1)^0)
+function file.is_writable(name)
+ if not name then
+ elseif lfs.isdir(name) then
+ name=name.."/m_t_x_t_e_s_t.tmp"
+ local f=io.open(name,"wb")
+ if f then
+ f:close()
+ os.remove(name)
+ return true
end
-end
-
-local splitters_f, splitters_s = { }, { }
-
-function lpeg.firstofsplit(separator) -- always return value
- local splitter = splitters_f[separator]
- if not splitter then
- separator = P(separator)
- splitter = C((1 - separator)^0)
- splitters_f[separator] = splitter
+ elseif lfs.isfile(name) then
+ local f=io.open(name,"ab")
+ if f then
+ f:close()
+ return true
+ end
+ else
+ local f=io.open(name,"ab")
+ if f then
+ f:close()
+ os.remove(name)
+ return true
end
- return splitter
+ end
+ return false
end
-
-function lpeg.secondofsplit(separator) -- nil if not split
- local splitter = splitters_s[separator]
- if not splitter then
- separator = P(separator)
- splitter = (1 - separator)^0 * separator * C(anything^0)
- splitters_s[separator] = splitter
+local readable=P("r")*Cc(true)
+function file.is_readable(name)
+ if name then
+ local a=attributes(name)
+ return a and lpegmatch(readable,a.permissions) or false
+ else
+ return false
+ end
+end
+file.isreadable=file.is_readable
+file.iswritable=file.is_writable
+function file.size(name)
+ if name then
+ local a=attributes(name)
+ return a and a.size or 0
+ else
+ return 0
+ end
+end
+function file.splitpath(str,separator)
+ return str and checkedsplit(lpegmatch(reslasher,str),separator or io.pathseparator)
+end
+function file.joinpath(tab,separator)
+ return tab and concat(tab,separator or io.pathseparator)
+end
+local stripper=Cs(P(fwslash)^0/""*reslasher)
+local isnetwork=fwslash*fwslash*(1-fwslash)+(1-fwslash-colon)^1*colon
+local isroot=fwslash^1*-1
+local hasroot=fwslash^1
+local deslasher=lpeg.replacer(S("\\/")^1,"/")
+function file.join(...)
+ local lst={... }
+ local one=lst[1]
+ if lpegmatch(isnetwork,one) then
+ local two=lpegmatch(deslasher,concat(lst,"/",2))
+ return one.."/"..two
+ elseif lpegmatch(isroot,one) then
+ local two=lpegmatch(deslasher,concat(lst,"/",2))
+ if lpegmatch(hasroot,two) then
+ return two
+ else
+ return "/"..two
+ end
+ elseif one=="" then
+ return lpegmatch(stripper,concat(lst,"/",2))
+ else
+ return lpegmatch(deslasher,concat(lst,"/"))
+ end
+end
+local drivespec=R("az","AZ")^1*colon
+local anchors=fwslash+drivespec
+local untouched=periods+(1-period)^1*P(-1)
+local splitstarter=(Cs(drivespec*(bwslash/"/"+fwslash)^0)+Cc(false))*Ct(lpeg.splitat(S("/\\")^1))
+local absolute=fwslash
+function file.collapsepath(str,anchor)
+ if not str then
+ return
+ end
+ if anchor and not lpegmatch(anchors,str) then
+ str=getcurrentdir().."/"..str
+ end
+ if str=="" or str=="." then
+ return "."
+ elseif lpegmatch(untouched,str) then
+ return lpegmatch(reslasher,str)
+ end
+ local starter,oldelements=lpegmatch(splitstarter,str)
+ local newelements={}
+ local i=#oldelements
+ while i>0 do
+ local element=oldelements[i]
+ if element=='.' then
+ elseif element=='..' then
+ local n=i-1
+ while n>0 do
+ local element=oldelements[n]
+ if element~='..' and element~='.' then
+ oldelements[n]='.'
+ break
+ else
+ n=n-1
+ end
+ end
+ if n<1 then
+ insert(newelements,1,'..')
+ end
+ elseif element~="" then
+ insert(newelements,1,element)
+ end
+ i=i-1
+ end
+ if #newelements==0 then
+ return starter or "."
+ elseif starter then
+ return starter..concat(newelements,'/')
+ elseif lpegmatch(absolute,str) then
+ return "/"..concat(newelements,'/')
+ else
+ return concat(newelements,'/')
+ end
+end
+local validchars=R("az","09","AZ","--","..")
+local pattern_a=lpeg.replacer(1-validchars)
+local pattern_a=Cs((validchars+P(1)/"-")^1)
+local whatever=P("-")^0/""
+local pattern_b=Cs(whatever*(1-whatever*-1)^1)
+function file.robustname(str,strict)
+ if str then
+ str=lpegmatch(pattern_a,str) or str
+ if strict then
+ return lpegmatch(pattern_b,str) or str
+ else
+ return str
end
- return splitter
+ end
end
-
-function lpeg.balancer(left,right)
- left, right = P(left), P(right)
- return P { left * ((1 - left - right) + V(1))^0 * right }
+file.readdata=io.loaddata
+file.savedata=io.savedata
+function file.copy(oldname,newname)
+ if oldname and newname then
+ local data=io.loaddata(oldname)
+ if data and data~="" then
+ file.savedata(newname,data)
+ end
+ end
+end
+local letter=R("az","AZ")+S("_-+")
+local separator=P("://")
+local qualified=period^0*fwslash+letter*colon+letter^1*separator+letter^1*fwslash
+local rootbased=fwslash+letter*colon
+lpeg.patterns.qualified=qualified
+lpeg.patterns.rootbased=rootbased
+function file.is_qualified_path(filename)
+ return filename and lpegmatch(qualified,filename)~=nil
+end
+function file.is_rootbased_path(filename)
+ return filename and lpegmatch(rootbased,filename)~=nil
+end
+function file.strip(name,dir)
+ if name then
+ local b,a=match(name,"^(.-)"..dir.."(.*)$")
+ return a~="" and a or name
+ end
end
+end -- of closure
-local nany = utf8char/""
+do -- create closure to overcome 200 locals limit
-function lpeg.counter(pattern)
- pattern = Cs((P(pattern)/" " + nany)^0)
- return function(str)
- return #match(pattern,str)
- end
-end
+package.loaded["l-md5"] = package.loaded["l-md5"] or true
-if utfgmatch then
+-- original size: 3760, stripped down to: 2088
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local n = 0
- for _ in utfgmatch(str,what) do
- n = n + 1
- end
- return n
- else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
- end
+if not modules then modules={} end modules ['l-md5']={
+ version=1.001,
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+if not md5 then
+ md5=optionalrequire("md5")
+end
+if not md5 then
+ md5={
+ sum=function(str) print("error: md5 is not loaded (sum ignored)") return str end,
+ sumhexa=function(str) print("error: md5 is not loaded (sumhexa ignored)") return str end,
+ }
+end
+local md5,file=md5,file
+local gsub,format,byte=string.gsub,string.format,string.byte
+local md5sum=md5.sum
+local function convert(str,fmt)
+ return (gsub(md5sum(str),".",function(chr) return format(fmt,byte(chr)) end))
+end
+if not md5.HEX then function md5.HEX(str) return convert(str,"%02X") end end
+if not md5.hex then function md5.hex(str) return convert(str,"%02x") end end
+if not md5.dec then function md5.dec(str) return convert(str,"%03i") end end
+function file.needsupdating(oldname,newname,threshold)
+ local oldtime=lfs.attributes(oldname,"modification")
+ if oldtime then
+ local newtime=lfs.attributes(newname,"modification")
+ if not newtime then
+ return true
+ elseif newtime>=oldtime then
+ return false
+ elseif oldtime-newtime<(threshold or 1) then
+ return false
+ else
+ return true
+ end
+ else
+ return false
+ end
+end
+file.needs_updating=file.needsupdating
+function file.syncmtimes(oldname,newname)
+ local oldtime=lfs.attributes(oldname,"modification")
+ if oldtime and lfs.isfile(newname) then
+ lfs.touch(newname,oldtime,oldtime)
+ end
+end
+function file.checksum(name)
+ if md5 then
+ local data=io.loaddata(name)
+ if data then
+ return md5.HEX(data)
end
+ end
+ return nil
+end
+function file.loadchecksum(name)
+ if md5 then
+ local data=io.loaddata(name..".md5")
+ return data and (gsub(data,"%s",""))
+ end
+ return nil
+end
+function file.savechecksum(name,checksum)
+ if not checksum then checksum=file.checksum(name) end
+ if checksum then
+ io.savedata(name..".md5",checksum)
+ return checksum
+ end
+ return nil
+end
-else
- local cache = { }
+end -- of closure
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local p = cache[what]
- if not p then
- p = Cs((P(what)/" " + nany)^0)
- cache[p] = p
- end
- return #match(p,str)
- else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
- end
- end
+do -- create closure to overcome 200 locals limit
-end
+package.loaded["l-url"] = package.loaded["l-url"] or true
-local patterns_escapes = { -- also defines in l-string
- ["%"] = "%%",
- ["."] = "%.",
- ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
- ["["] = "%[", ["]"] = "%]",
- ["("] = "%)", [")"] = "%)",
- -- ["{"] = "%{", ["}"] = "%}"
- -- ["^"] = "%^", ["$"] = "%$",
-}
+-- original size: 11806, stripped down to: 5417
-local simple_escapes = { -- also defines in l-string
- ["-"] = "%-",
- ["."] = "%.",
- ["?"] = ".",
- ["*"] = ".*",
+if not modules then modules={} end modules ['l-url']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
}
-
-local p = Cs((S("-.+*%()[]") / patterns_escapes + anything)^0)
-local s = Cs((S("-.+*%()[]") / simple_escapes + anything)^0)
-
-function string.escapedpattern(str,simple)
- return match(simple and s or p,str)
+local char,format,byte=string.char,string.format,string.byte
+local concat=table.concat
+local tonumber,type=tonumber,type
+local P,C,R,S,Cs,Cc,Ct,Cf,Cg,V=lpeg.P,lpeg.C,lpeg.R,lpeg.S,lpeg.Cs,lpeg.Cc,lpeg.Ct,lpeg.Cf,lpeg.Cg,lpeg.V
+local lpegmatch,lpegpatterns,replacer=lpeg.match,lpeg.patterns,lpeg.replacer
+url=url or {}
+local url=url
+local tochar=function(s) return char(tonumber(s,16)) end
+local colon=P(":")
+local qmark=P("?")
+local hash=P("#")
+local slash=P("/")
+local percent=P("%")
+local endofstring=P(-1)
+local hexdigit=R("09","AF","af")
+local plus=P("+")
+local nothing=Cc("")
+local escapedchar=(percent*C(hexdigit*hexdigit))/tochar
+local escaped=(plus/" ")+escapedchar
+local noslash=P("/")/""
+local schemestr=Cs((escaped+(1-colon-slash-qmark-hash))^2)
+local authoritystr=Cs((escaped+(1- slash-qmark-hash))^0)
+local pathstr=Cs((escaped+(1- qmark-hash))^0)
+local querystr=Cs(((1- hash))^0)
+local fragmentstr=Cs((escaped+(1- endofstring))^0)
+local scheme=schemestr*colon+nothing
+local authority=slash*slash*authoritystr+nothing
+local path=slash*pathstr+nothing
+local query=qmark*querystr+nothing
+local fragment=hash*fragmentstr+nothing
+local validurl=scheme*authority*path*query*fragment
+local parser=Ct(validurl)
+lpegpatterns.url=validurl
+lpegpatterns.urlsplitter=parser
+local escapes={}
+setmetatable(escapes,{ __index=function(t,k)
+ local v=format("%%%02X",byte(k))
+ t[k]=v
+ return v
+end })
+local escaper=Cs((R("09","AZ","az")^1+P(" ")/"%%20"+S("-./_")^1+P(1)/escapes)^0)
+local unescaper=Cs((escapedchar+1)^0)
+lpegpatterns.urlunescaped=escapedchar
+lpegpatterns.urlescaper=escaper
+lpegpatterns.urlunescaper=unescaper
+local function split(str)
+ return (type(str)=="string" and lpegmatch(parser,str)) or str
+end
+local isscheme=schemestr*colon*slash*slash
+local function hasscheme(str)
+ if str then
+ local scheme=lpegmatch(isscheme,str)
+ return scheme~="" and scheme or false
+ else
+ return false
+ end
+end
+local rootletter=R("az","AZ")+S("_-+")
+local separator=P("://")
+local qualified=P(".")^0*P("/")+rootletter*P(":")+rootletter^1*separator+rootletter^1*P("/")
+local rootbased=P("/")+rootletter*P(":")
+local barswapper=replacer("|",":")
+local backslashswapper=replacer("\\","/")
+local equal=P("=")
+local amp=P("&")
+local key=Cs(((escapedchar+1)-equal )^0)
+local value=Cs(((escapedchar+1)-amp -endofstring)^0)
+local splitquery=Cf (Ct("")*P { "sequence",
+ sequence=V("pair")*(amp*V("pair"))^0,
+ pair=Cg(key*equal*value),
+},rawset)
+local function hashed(str)
+ if str=="" then
+ return {
+ scheme="invalid",
+ original=str,
+ }
+ end
+ local s=split(str)
+ local rawscheme=s[1]
+ local rawquery=s[4]
+ local somescheme=rawscheme~=""
+ local somequery=rawquery~=""
+ if not somescheme and not somequery then
+ s={
+ scheme="file",
+ authority="",
+ path=str,
+ query="",
+ fragment="",
+ original=str,
+ noscheme=true,
+ filename=str,
+ }
+ else
+ local authority,path,filename=s[2],s[3]
+ if authority=="" then
+ filename=path
+ elseif path=="" then
+ filename=""
+ else
+ filename=authority.."/"..path
+ end
+ s={
+ scheme=rawscheme,
+ authority=authority,
+ path=path,
+ query=lpegmatch(unescaper,rawquery),
+ queries=lpegmatch(splitquery,rawquery),
+ fragment=s[5],
+ original=str,
+ noscheme=false,
+ filename=filename,
+ }
+ end
+ return s
+end
+url.split=split
+url.hasscheme=hasscheme
+url.hashed=hashed
+function url.addscheme(str,scheme)
+ if hasscheme(str) then
+ return str
+ elseif not scheme then
+ return "file:///"..str
+ else
+ return scheme..":///"..str
+ end
+end
+function url.construct(hash)
+ local fullurl,f={},0
+ local scheme,authority,path,query,fragment=hash.scheme,hash.authority,hash.path,hash.query,hash.fragment
+ if scheme and scheme~="" then
+ f=f+1;fullurl[f]=scheme.."://"
+ end
+ if authority and authority~="" then
+ f=f+1;fullurl[f]=authority
+ end
+ if path and path~="" then
+ f=f+1;fullurl[f]="/"..path
+ end
+ if query and query~="" then
+ f=f+1;fullurl[f]="?"..query
+ end
+ if fragment and fragment~="" then
+ f=f+1;fullurl[f]="#"..fragment
+ end
+ return lpegmatch(escaper,concat(fullurl))
+end
+local pattern=Cs(noslash*R("az","AZ")*(S(":|")/":")*noslash*P(1)^0)
+function url.filename(filename)
+ local spec=hashed(filename)
+ local path=spec.path
+ return (spec.scheme=="file" and path and lpegmatch(pattern,path)) or filename
+end
+local function escapestring(str)
+ return lpegmatch(escaper,str)
+end
+url.escape=escapestring
+function url.query(str)
+ if type(str)=="string" then
+ return lpegmatch(splitquery,str) or ""
+ else
+ return str
+ end
+end
+function url.toquery(data)
+ local td=type(data)
+ if td=="string" then
+ return #str and escape(data) or nil
+ elseif td=="table" then
+ if next(data) then
+ local t={}
+ for k,v in next,data do
+ t[#t+1]=format("%s=%s",k,escapestring(v))
+ end
+ return concat(t,"&")
+ end
+ else
+ end
+end
+local pattern=Cs(noslash^0*(1-noslash*P(-1))^0)
+function url.barepath(path)
+ if not path or path=="" then
+ return ""
+ else
+ return lpegmatch(pattern,path)
+ end
end
--- utf extensies
-
-lpeg.UP = lpeg.P
-if utfcharacters then
+end -- of closure
- function lpeg.US(str)
- local p
- for uc in utfcharacters(str) do
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- return p
- end
+do -- create closure to overcome 200 locals limit
+package.loaded["l-dir"] = package.loaded["l-dir"] or true
-elseif utfgmatch then
+-- original size: 13139, stripped down to: 8196
- function lpeg.US(str)
- local p
- for uc in utfgmatch(str,".") do
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
+if not modules then modules={} end modules ['l-dir']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local type,select=type,select
+local find,gmatch,match,gsub=string.find,string.gmatch,string.match,string.gsub
+local concat,insert,remove=table.concat,table.insert,table.remove
+local lpegmatch=lpeg.match
+local P,S,R,C,Cc,Cs,Ct,Cv,V=lpeg.P,lpeg.S,lpeg.R,lpeg.C,lpeg.Cc,lpeg.Cs,lpeg.Ct,lpeg.Cv,lpeg.V
+dir=dir or {}
+local dir=dir
+local lfs=lfs
+local attributes=lfs.attributes
+local walkdir=lfs.dir
+local isdir=lfs.isdir
+local isfile=lfs.isfile
+local currentdir=lfs.currentdir
+local chdir=lfs.chdir
+if not isdir then
+ function isdir(name)
+ local a=attributes(name)
+ return a and a.mode=="directory"
+ end
+ lfs.isdir=isdir
+end
+if not isfile then
+ function isfile(name)
+ local a=attributes(name)
+ return a and a.mode=="file"
+ end
+ lfs.isfile=isfile
+end
+function dir.current()
+ return (gsub(currentdir(),"\\","/"))
+end
+local lfsisdir=isdir
+local function isdir(path)
+ path=gsub(path,"[/\\]+$","")
+ return lfsisdir(path)
+end
+lfs.isdir=isdir
+local function globpattern(path,patt,recurse,action)
+ if path=="/" then
+ path=path.."."
+ elseif not find(path,"/$") then
+ path=path..'/'
+ end
+ if isdir(path) then
+ for name in walkdir(path) do
+ local full=path..name
+ local mode=attributes(full,'mode')
+ if mode=='file' then
+ if find(full,patt) then
+ action(full)
+ end
+ elseif recurse and (mode=="directory") and (name~='.') and (name~="..") then
+ globpattern(full,patt,recurse,action)
+ end
+ end
+ end
+end
+dir.globpattern=globpattern
+local function collectpattern(path,patt,recurse,result)
+ local ok,scanner
+ result=result or {}
+ if path=="/" then
+ ok,scanner,first=xpcall(function() return walkdir(path..".") end,function() end)
+ else
+ ok,scanner,first=xpcall(function() return walkdir(path) end,function() end)
+ end
+ if ok and type(scanner)=="function" then
+ if not find(path,"/$") then path=path..'/' end
+ for name in scanner,first do
+ local full=path..name
+ local attr=attributes(full)
+ local mode=attr.mode
+ if mode=='file' then
+ if find(full,patt) then
+ result[name]=attr
+ end
+ elseif recurse and (mode=="directory") and (name~='.') and (name~="..") then
+ attr.list=collectpattern(full,patt,recurse)
+ result[name]=attr
+ end
+ end
+ end
+ return result
+end
+dir.collectpattern=collectpattern
+local pattern=Ct {
+ [1]=(C(P(".")+P("/")^1)+C(R("az","AZ")*P(":")*P("/")^0)+Cc("./"))*V(2)*V(3),
+ [2]=C(((1-S("*?/"))^0*P("/"))^0),
+ [3]=C(P(1)^0)
+}
+local filter=Cs ((
+ P("**")/".*"+P("*")/"[^/]*"+P("?")/"[^/]"+P(".")/"%%."+P("+")/"%%+"+P("-")/"%%-"+P(1)
+)^0 )
+local function glob(str,t)
+ if type(t)=="function" then
+ if type(str)=="table" then
+ for s=1,#str do
+ glob(str[s],t)
+ end
+ elseif isfile(str) then
+ t(str)
+ else
+ local split=lpegmatch(pattern,str)
+ if split then
+ local root,path,base=split[1],split[2],split[3]
+ local recurse=find(base,"%*%*")
+ local start=root..path
+ local result=lpegmatch(filter,start..base)
+ globpattern(start,result,recurse,t)
+ end
+ end
+ else
+ if type(str)=="table" then
+ local t=t or {}
+ for s=1,#str do
+ glob(str[s],t)
+ end
+ return t
+ elseif isfile(str) then
+ if t then
+ t[#t+1]=str
+ return t
+ else
+ return { str }
+ end
+ else
+ local split=lpegmatch(pattern,str)
+ if split then
+ local t=t or {}
+ local action=action or function(name) t[#t+1]=name end
+ local root,path,base=split[1],split[2],split[3]
+ local recurse=find(base,"%*%*")
+ local start=root..path
+ local result=lpegmatch(filter,start..base)
+ globpattern(start,result,recurse,action)
+ return t
+ else
+ return {}
+ end
+ end
+ end
+end
+dir.glob=glob
+local function globfiles(path,recurse,func,files)
+ if type(func)=="string" then
+ local s=func
+ func=function(name) return find(name,s) end
+ end
+ files=files or {}
+ local noffiles=#files
+ for name in walkdir(path) do
+ if find(name,"^%.") then
+ else
+ local mode=attributes(name,'mode')
+ if mode=="directory" then
+ if recurse then
+ globfiles(path.."/"..name,recurse,func,files)
end
- return p
- end
-
-else
-
- function lpeg.US(str)
- local p
- local f = function(uc)
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
+ elseif mode=="file" then
+ if not func or func(name) then
+ noffiles=noffiles+1
+ files[noffiles]=path.."/"..name
end
- match((utf8char/f)^0,str)
- return p
+ end
end
-
+ end
+ return files
end
-
-local range = Cs(utf8byte) * (Cs(utf8byte) + Cc(false))
-
-local utfchar = unicode and unicode.utf8 and unicode.utf8.char
-
-function lpeg.UR(str,more)
- local first, last
- if type(str) == "number" then
- first = str
- last = more or first
+dir.globfiles=globfiles
+function dir.ls(pattern)
+ return concat(glob(pattern),"\n")
+end
+local make_indeed=true
+local onwindows=os.type=="windows" or find(os.getenv("PATH"),";")
+if onwindows then
+ function dir.mkdirs(...)
+ local str,pth="",""
+ for i=1,select("#",...) do
+ local s=select(i,...)
+ if s=="" then
+ elseif str=="" then
+ str=s
+ else
+ str=str.."/"..s
+ end
+ end
+ local first,middle,last
+ local drive=false
+ first,middle,last=match(str,"^(//)(//*)(.*)$")
+ if first then
else
- first, last = match(range,str)
- if not last then
- return P(str)
+ first,last=match(str,"^(//)/*(.-)$")
+ if first then
+ middle,last=match(str,"([^/]+)/+(.-)$")
+ if middle then
+ pth="//"..middle
+ else
+ pth="//"..last
+ last=""
+ end
+ else
+ first,middle,last=match(str,"^([a-zA-Z]:)(/*)(.-)$")
+ if first then
+ pth,drive=first..middle,true
+ else
+ middle,last=match(str,"^(/*)(.-)$")
+ if not middle then
+ last=str
+ end
+ end
+ end
+ end
+ for s in gmatch(last,"[^/]+") do
+ if pth=="" then
+ pth=s
+ elseif drive then
+ pth,drive=pth..s,false
+ else
+ pth=pth.."/"..s
+ end
+ if make_indeed and not isdir(pth) then
+ lfs.mkdir(pth)
+ end
+ end
+ return pth,(isdir(pth)==true)
+ end
+else
+ function dir.mkdirs(...)
+ local str,pth="",""
+ for i=1,select("#",...) do
+ local s=select(i,...)
+ if s and s~="" then
+ if str~="" then
+ str=str.."/"..s
+ else
+ str=s
end
+ end
end
- if first == last then
- return P(str)
- elseif utfchar and last - first < 8 then -- a somewhat arbitrary criterium
- local p
- for i=first,last do
- if p then
- p = p + P(utfchar(i))
- else
- p = P(utfchar(i))
- end
+ str=gsub(str,"/+","/")
+ if find(str,"^/") then
+ pth="/"
+ for s in gmatch(str,"[^/]+") do
+ local first=(pth=="/")
+ if first then
+ pth=pth..s
+ else
+ pth=pth.."/"..s
end
- return p -- nil when invalid range
+ if make_indeed and not first and not isdir(pth) then
+ lfs.mkdir(pth)
+ end
+ end
else
- local f = function(b)
- return b >= first and b <= last
+ pth="."
+ for s in gmatch(str,"[^/]+") do
+ pth=pth.."/"..s
+ if make_indeed and not isdir(pth) then
+ lfs.mkdir(pth)
end
- return utf8byte / f -- nil when invalid range
+ end
end
+ return pth,(isdir(pth)==true)
+ end
end
-
-
-
-function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
- if type(list) ~= "table" then
- list = { list, ... }
+dir.makedirs=dir.mkdirs
+if onwindows then
+ function dir.expandname(str)
+ local first,nothing,last=match(str,"^(//)(//*)(.*)$")
+ if first then
+ first=dir.current().."/"
+ end
+ if not first then
+ first,last=match(str,"^(//)/*(.*)$")
+ end
+ if not first then
+ first,last=match(str,"^([a-zA-Z]:)(.*)$")
+ if first and not find(last,"^/") then
+ local d=currentdir()
+ if chdir(first) then
+ first=dir.current()
+ end
+ chdir(d)
+ end
+ end
+ if not first then
+ first,last=dir.current(),str
+ end
+ last=gsub(last,"//","/")
+ last=gsub(last,"/%./","/")
+ last=gsub(last,"^/*","")
+ first=gsub(first,"/*$","")
+ if last=="" or last=="." then
+ return first
+ else
+ return first.."/"..last
end
- -- sort(list) -- longest match first
- local p = P(list[1])
- for l=2,#list do
- p = p + P(list[l])
+ end
+else
+ function dir.expandname(str)
+ if not find(str,"^/") then
+ str=currentdir().."/"..str
end
- return p
+ str=gsub(str,"//","/")
+ str=gsub(str,"/%./","/")
+ str=gsub(str,"(.)/%.$","%1")
+ return str
+ end
end
-
-function lpeg.is_lpeg(p)
- return p and lpegtype(p) == "pattern"
+file.expandname=dir.expandname
+local stack={}
+function dir.push(newdir)
+ insert(stack,currentdir())
+ if newdir and newdir~="" then
+ chdir(newdir)
+ end
+end
+function dir.pop()
+ local d=remove(stack)
+ if d then
+ chdir(d)
+ end
+ return d
end
--- For the moment here, but it might move to utilities. Beware, we need to
--- have the longest keyword first, so 'aaa' comes beforte 'aa' which is why we
--- loop back from the end cq. prepend.
-
-local sort, fastcopy, sortedkeys = table.sort, table.fastcopy, table.sortedkeys -- dependency!
-function lpeg.append(list,pp,delayed,checked)
- local p = pp
- if #list > 0 then
- local keys = fastcopy(list)
- sort(keys)
- for i=#keys,1,-1 do
- local k = keys[i]
- if p then
- p = P(k) + p
- else
- p = P(k)
- end
- end
- elseif delayed then -- hm, it looks like the lpeg parser resolves anyway
- local keys = sortedkeys(list)
- if p then
- for i=1,#keys,1 do
- local k = keys[i]
- local v = list[k]
- p = P(k)/list + p
- end
- else
- for i=1,#keys do
- local k = keys[i]
- local v = list[k]
- if p then
- p = P(k) + p
- else
- p = P(k)
- end
- end
- if p then
- p = p / list
- end
- end
- elseif checked then
- -- problem: substitution gives a capture
- local keys = sortedkeys(list)
- for i=1,#keys do
- local k = keys[i]
- local v = list[k]
- if p then
- if k == v then
- p = P(k) + p
- else
- p = P(k)/v + p
- end
- else
- if k == v then
- p = P(k)
- else
- p = P(k)/v
- end
- end
- end
- else
- local keys = sortedkeys(list)
- for i=1,#keys do
- local k = keys[i]
- local v = list[k]
- if p then
- p = P(k)/v + p
- else
- p = P(k)/v
- end
- end
- end
- return p
-end
+end -- of closure
--- inspect(lpeg.append({ a = "1", aa = "1", aaa = "1" } ,nil,true))
--- inspect(lpeg.append({ ["degree celsius"] = "1", celsius = "1", degree = "1" } ,nil,true))
+do -- create closure to overcome 200 locals limit
--- function lpeg.exact_match(words,case_insensitive)
--- local pattern = concat(words)
--- if case_insensitive then
--- local pattern = S(upper(characters)) + S(lower(characters))
--- local list = { }
--- for i=1,#words do
--- list[lower(words[i])] = true
--- end
--- return Cmt(pattern^1, function(_,i,s)
--- return list[lower(s)] and i
--- end)
--- else
--- local pattern = S(concat(words))
--- local list = { }
--- for i=1,#words do
--- list[words[i]] = true
--- end
--- return Cmt(pattern^1, function(_,i,s)
--- return list[s] and i
--- end)
--- end
--- end
+package.loaded["l-boolean"] = package.loaded["l-boolean"] or true
--- experiment:
+-- original size: 1781, stripped down to: 1503
-local function make(t)
- local p
--- for k, v in next, t do
- for k, v in table.sortedhash(t) do
- if not p then
- if next(v) then
- p = P(k) * make(v)
- else
- p = P(k)
- end
- else
- if next(v) then
- p = p + P(k) * make(v)
- else
- p = p + P(k)
- end
- end
- end
- return p
+if not modules then modules={} end modules ['l-boolean']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local type,tonumber=type,tonumber
+boolean=boolean or {}
+local boolean=boolean
+function boolean.tonumber(b)
+ if b then return 1 else return 0 end
end
-
-function lpeg.utfchartabletopattern(list)
- local tree = { }
- for i=1,#list do
- local t = tree
- for c in gmatch(list[i],".") do
- if not t[c] then
- t[c] = { }
- end
- t = t[c]
- end
+function toboolean(str,tolerant)
+ if str==nil then
+ return false
+ elseif str==false then
+ return false
+ elseif str==true then
+ return true
+ elseif str=="true" then
+ return true
+ elseif str=="false" then
+ return false
+ elseif not tolerant then
+ return false
+ elseif str==0 then
+ return false
+ elseif (tonumber(str) or 0)>0 then
+ return true
+ else
+ return str=="yes" or str=="on" or str=="t"
+ end
+end
+string.toboolean=toboolean
+function string.booleanstring(str)
+ if str=="0" then
+ return false
+ elseif str=="1" then
+ return true
+ elseif str=="" then
+ return false
+ elseif str=="false" then
+ return false
+ elseif str=="true" then
+ return true
+ elseif (tonumber(str) or 0)>0 then
+ return true
+ else
+ return str=="yes" or str=="on" or str=="t"
+ end
+end
+function string.is_boolean(str,default)
+ if type(str)=="string" then
+ if str=="true" or str=="yes" or str=="on" or str=="t" then
+ return true
+ elseif str=="false" or str=="no" or str=="off" or str=="f" then
+ return false
end
- return make(tree)
+ end
+ return default
end
--- inspect ( lpeg.utfchartabletopattern {
--- utfchar(0x00A0), -- nbsp
--- utfchar(0x2000), -- enquad
--- utfchar(0x2001), -- emquad
--- utfchar(0x2002), -- enspace
--- utfchar(0x2003), -- emspace
--- utfchar(0x2004), -- threeperemspace
--- utfchar(0x2005), -- fourperemspace
--- utfchar(0x2006), -- sixperemspace
--- utfchar(0x2007), -- figurespace
--- utfchar(0x2008), -- punctuationspace
--- utfchar(0x2009), -- breakablethinspace
--- utfchar(0x200A), -- hairspace
--- utfchar(0x200B), -- zerowidthspace
--- utfchar(0x202F), -- narrownobreakspace
--- utfchar(0x205F), -- math thinspace
--- } )
-
end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-io'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local io = io
-local byte, find, gsub, format = string.byte, string.find, string.gsub, string.format
-local concat = table.concat
-local type = type
+package.loaded["l-unicode"] = package.loaded["l-unicode"] or true
-if string.find(os.getenv("PATH"),";") then
- io.fileseparator, io.pathseparator = "\\", ";"
-else
- io.fileseparator, io.pathseparator = "/" , ":"
-end
+-- original size: 26810, stripped down to: 11943
-function io.loaddata(filename,textmode)
- local f = io.open(filename,(textmode and 'r') or 'rb')
- if f then
- local data = f:read('*all')
- f:close()
- return data
+if not modules then modules={} end modules ['l-unicode']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+utf=utf or (unicode and unicode.utf8) or {}
+utf.characters=utf.characters or string.utfcharacters
+utf.values=utf.values or string.utfvalues
+local type=type
+local char,byte,format,sub=string.char,string.byte,string.format,string.sub
+local concat=table.concat
+local P,C,R,Cs,Ct,Cmt,Cc,Carg,Cp=lpeg.P,lpeg.C,lpeg.R,lpeg.Cs,lpeg.Ct,lpeg.Cmt,lpeg.Cc,lpeg.Carg,lpeg.Cp
+local lpegmatch,patterns=lpeg.match,lpeg.patterns
+local bytepairs=string.bytepairs
+local finder=lpeg.finder
+local replacer=lpeg.replacer
+local utfvalues=utf.values
+local utfgmatch=utf.gmatch
+local p_utftype=patterns.utftype
+local p_utfoffset=patterns.utfoffset
+local p_utf8char=patterns.utf8char
+local p_utf8byte=patterns.utf8byte
+local p_utfbom=patterns.utfbom
+local p_newline=patterns.newline
+local p_whitespace=patterns.whitespace
+if not unicode then
+ unicode={ utf=utf }
+end
+if not utf.char then
+ local floor,char=math.floor,string.char
+ function utf.char(n)
+ if n<0x80 then
+ return char(n)
+ elseif n<0x800 then
+ return char(
+ 0xC0+floor(n/0x40),
+ 0x80+(n%0x40)
+ )
+ elseif n<0x10000 then
+ return char(
+ 0xE0+floor(n/0x1000),
+ 0x80+(floor(n/0x40)%0x40),
+ 0x80+(n%0x40)
+ )
+ elseif n<0x200000 then
+ return char(
+ 0xF0+floor(n/0x40000),
+ 0x80+(floor(n/0x1000)%0x40),
+ 0x80+(floor(n/0x40)%0x40),
+ 0x80+(n%0x40)
+ )
else
- return nil
+ return ""
+ end
+ end
+end
+if not utf.byte then
+ local utf8byte=patterns.utf8byte
+ function utf.byte(c)
+ return lpegmatch(utf8byte,c)
+ end
+end
+local utfchar,utfbyte=utf.char,utf.byte
+function utf.filetype(data)
+ return data and lpegmatch(p_utftype,data) or "unknown"
+end
+local toentities=Cs (
+ (
+ patterns.utf8one+(
+ patterns.utf8two+patterns.utf8three+patterns.utf8four
+ )/function(s) local b=utfbyte(s) if b<127 then return s else return format("%X;",b) end end
+ )^0
+)
+patterns.toentities=toentities
+function utf.toentities(str)
+ return lpegmatch(toentities,str)
+end
+local one=P(1)
+local two=C(1)*C(1)
+local four=C(R(utfchar(0xD8),utfchar(0xFF)))*C(1)*C(1)*C(1)
+local pattern=P("\254\255")*Cs((
+ four/function(a,b,c,d)
+ local ab=0xFF*byte(a)+byte(b)
+ local cd=0xFF*byte(c)+byte(d)
+ return utfchar((ab-0xD800)*0x400+(cd-0xDC00)+0x10000)
+ end+two/function(a,b)
+ return utfchar(byte(a)*256+byte(b))
+ end+one
+ )^1 )+P("\255\254")*Cs((
+ four/function(b,a,d,c)
+ local ab=0xFF*byte(a)+byte(b)
+ local cd=0xFF*byte(c)+byte(d)
+ return utfchar((ab-0xD800)*0x400+(cd-0xDC00)+0x10000)
+ end+two/function(b,a)
+ return utfchar(byte(a)*256+byte(b))
+ end+one
+ )^1 )
+function string.toutf(s)
+ return lpegmatch(pattern,s) or s
+end
+local validatedutf=Cs (
+ (
+ patterns.utf8one+patterns.utf8two+patterns.utf8three+patterns.utf8four+P(1)/"�"
+ )^0
+)
+patterns.validatedutf=validatedutf
+function utf.is_valid(str)
+ return type(str)=="string" and lpegmatch(validatedutf,str) or false
+end
+if not utf.len then
+ local n,f=0,1
+ local utfcharcounter=patterns.utfbom^-1*Cmt (
+ Cc(1)*patterns.utf8one^1+Cc(2)*patterns.utf8two^1+Cc(3)*patterns.utf8three^1+Cc(4)*patterns.utf8four^1,
+ function(_,t,d)
+ n=n+(t-f)/d
+ f=t
+ return true
+ end
+ )^0
+ function utf.len(str)
+ n,f=0,1
+ lpegmatch(utfcharcounter,str or "")
+ return n
+ end
+end
+utf.length=utf.len
+if not utf.sub then
+ local utflength=utf.length
+ local b,e,n,first,last=0,0,0,0,0
+ local function slide_zero(s,p)
+ n=n+1
+ if n>=last then
+ e=p-1
+ else
+ return p
end
-end
-
-function io.savedata(filename,data,joiner)
- local f = io.open(filename,"wb")
- if f then
- if type(data) == "table" then
- f:write(concat(data,joiner or ""))
- elseif type(data) == "function" then
- data(f)
+ end
+ local function slide_one(s,p)
+ n=n+1
+ if n==first then
+ b=p
+ end
+ if n>=last then
+ e=p-1
+ else
+ return p
+ end
+ end
+ local function slide_two(s,p)
+ n=n+1
+ if n==first then
+ b=p
+ else
+ return true
+ end
+ end
+ local pattern_zero=Cmt(p_utf8char,slide_zero)^0
+ local pattern_one=Cmt(p_utf8char,slide_one )^0
+ local pattern_two=Cmt(p_utf8char,slide_two )^0
+ function utf.sub(str,start,stop)
+ if not start then
+ return str
+ end
+ if start==0 then
+ start=1
+ end
+ if not stop then
+ if start<0 then
+ local l=utflength(str)
+ start=l+start
+ else
+ start=start-1
+ end
+ b,n,first=0,0,start
+ lpegmatch(pattern_two,str)
+ if n>=first then
+ return sub(str,b)
+ else
+ return ""
+ end
+ end
+ if start<0 or stop<0 then
+ local l=utf.length(str)
+ if start<0 then
+ start=l+start
+ if start<=0 then
+ start=1
else
- f:write(data or "")
+ start=start+1
end
- f:close()
- io.flush()
- return true
+ end
+ if stop<0 then
+ stop=l+stop
+ if stop==0 then
+ stop=1
+ else
+ stop=stop+1
+ end
+ end
+ end
+ if start>stop then
+ return ""
+ elseif start>1 then
+ b,e,n,first,last=0,0,0,start-1,stop
+ lpegmatch(pattern_one,str)
+ if n>=first and e==0 then
+ e=#str
+ end
+ return sub(str,b,e)
else
- return false
- end
-end
-
-function io.exists(filename)
- local f = io.open(filename)
- if f == nil then
- return false
+ b,e,n,last=1,0,0,stop
+ lpegmatch(pattern_zero,str)
+ if e==0 then
+ e=#str
+ end
+ return sub(str,b,e)
+ end
+ end
+end
+function utf.remapper(mapping)
+ local pattern=Cs((p_utf8char/mapping)^0)
+ return function(str)
+ if not str or str=="" then
+ return ""
else
- assert(f:close())
- return true
- end
-end
-
-function io.size(filename)
- local f = io.open(filename)
- if f == nil then
- return 0
+ return lpegmatch(pattern,str)
+ end
+ end,pattern
+end
+function utf.replacer(t)
+ local r=replacer(t,false,false,true)
+ return function(str)
+ return lpegmatch(r,str)
+ end
+end
+function utf.subtituter(t)
+ local f=finder (t)
+ local r=replacer(t,false,false,true)
+ return function(str)
+ local i=lpegmatch(f,str)
+ if not i then
+ return str
+ elseif i>#str then
+ return str
else
- local s = f:seek("end")
- assert(f:close())
- return s
- end
+ return lpegmatch(r,str)
+ end
+ end
+end
+local utflinesplitter=p_utfbom^-1*lpeg.tsplitat(p_newline)
+local utfcharsplitter_ows=p_utfbom^-1*Ct(C(p_utf8char)^0)
+local utfcharsplitter_iws=p_utfbom^-1*Ct((p_whitespace^1+C(p_utf8char))^0)
+local utfcharsplitter_raw=Ct(C(p_utf8char)^0)
+patterns.utflinesplitter=utflinesplitter
+function utf.splitlines(str)
+ return lpegmatch(utflinesplitter,str or "")
+end
+function utf.split(str,ignorewhitespace)
+ if ignorewhitespace then
+ return lpegmatch(utfcharsplitter_iws,str or "")
+ else
+ return lpegmatch(utfcharsplitter_ows,str or "")
+ end
+end
+function utf.totable(str)
+ return lpegmatch(utfcharsplitter_raw,str)
+end
+function utf.magic(f)
+ local str=f:read(4) or ""
+ local off=lpegmatch(p_utfoffset,str)
+ if off<4 then
+ f:seek('set',off)
+ end
+ return lpegmatch(p_utftype,str)
end
-
-function io.noflines(f)
- if type(f) == "string" then
- local f = io.open(filename)
- local n = f and io.noflines(f) or 0
- assert(f:close())
- return n
- else
- local n = 0
- for _ in f:lines() do
- n = n + 1
+local function utf16_to_utf8_be(t)
+ if type(t)=="string" then
+ t=lpegmatch(utflinesplitter,t)
+ end
+ local result={}
+ for i=1,#t do
+ local r,more=0,0
+ for left,right in bytepairs(t[i]) do
+ if right then
+ local now=256*left+right
+ if more>0 then
+ now=(more-0xD800)*0x400+(now-0xDC00)+0x10000
+ more=0
+ r=r+1
+ result[r]=utfchar(now)
+ elseif now>=0xD800 and now<=0xDBFF then
+ more=now
+ else
+ r=r+1
+ result[r]=utfchar(now)
end
- f:seek('set',0)
- return n
+ end
end
+ t[i]=concat(result,"",1,r)
+ end
+ return t
end
-
-local nextchar = {
- [ 4] = function(f)
- return f:read(1,1,1,1)
- end,
- [ 2] = function(f)
- return f:read(1,1)
- end,
- [ 1] = function(f)
- return f:read(1)
- end,
- [-2] = function(f)
- local a, b = f:read(1,1)
- return b, a
- end,
- [-4] = function(f)
- local a, b, c, d = f:read(1,1,1,1)
- return d, c, b, a
- end
-}
-
-function io.characters(f,n)
- if f then
- return nextchar[n or 1], f
+local function utf16_to_utf8_le(t)
+ if type(t)=="string" then
+ t=lpegmatch(utflinesplitter,t)
+ end
+ local result={}
+ for i=1,#t do
+ local r,more=0,0
+ for left,right in bytepairs(t[i]) do
+ if right then
+ local now=256*right+left
+ if more>0 then
+ now=(more-0xD800)*0x400+(now-0xDC00)+0x10000
+ more=0
+ r=r+1
+ result[r]=utfchar(now)
+ elseif now>=0xD800 and now<=0xDBFF then
+ more=now
+ else
+ r=r+1
+ result[r]=utfchar(now)
+ end
+ end
end
+ t[i]=concat(result,"",1,r)
+ end
+ return t
end
-
-local nextbyte = {
- [4] = function(f)
- local a, b, c, d = f:read(1,1,1,1)
- if d then
- return byte(a), byte(b), byte(c), byte(d)
- end
- end,
- [3] = function(f)
- local a, b, c = f:read(1,1,1)
- if b then
- return byte(a), byte(b), byte(c)
- end
- end,
- [2] = function(f)
- local a, b = f:read(1,1)
- if b then
- return byte(a), byte(b)
- end
- end,
- [1] = function (f)
- local a = f:read(1)
- if a then
- return byte(a)
- end
- end,
- [-2] = function (f)
- local a, b = f:read(1,1)
- if b then
- return byte(b), byte(a)
- end
- end,
- [-3] = function(f)
- local a, b, c = f:read(1,1,1)
- if b then
- return byte(c), byte(b), byte(a)
- end
- end,
- [-4] = function(f)
- local a, b, c, d = f:read(1,1,1,1)
- if d then
- return byte(d), byte(c), byte(b), byte(a)
+local function utf32_to_utf8_be(t)
+ if type(t)=="string" then
+ t=lpegmatch(utflinesplitter,t)
+ end
+ local result={}
+ for i=1,#t do
+ local r,more=0,-1
+ for a,b in bytepairs(t[i]) do
+ if a and b then
+ if more<0 then
+ more=256*256*256*a+256*256*b
+ else
+ r=r+1
+ result[t]=utfchar(more+256*a+b)
+ more=-1
end
+ else
+ break
+ end
end
-}
-
-function io.bytes(f,n)
- if f then
- return nextbyte[n or 1], f
- else
- return nil, nil
- end
+ t[i]=concat(result,"",1,r)
+ end
+ return t
end
-
-function io.ask(question,default,options)
- while true do
- io.write(question)
- if options then
- io.write(format(" [%s]",concat(options,"|")))
- end
- if default then
- io.write(format(" [%s]",default))
- end
- io.write(format(" "))
- io.flush()
- local answer = io.read()
- answer = gsub(answer,"^%s*(.*)%s*$","%1")
- if answer == "" and default then
- return default
- elseif not options then
- return answer
+local function utf32_to_utf8_le(t)
+ if type(t)=="string" then
+ t=lpegmatch(utflinesplitter,t)
+ end
+ local result={}
+ for i=1,#t do
+ local r,more=0,-1
+ for a,b in bytepairs(t[i]) do
+ if a and b then
+ if more<0 then
+ more=256*b+a
else
- for k=1,#options do
- if options[k] == answer then
- return answer
- end
- end
- local pattern = "^" .. answer
- for k=1,#options do
- local v = options[k]
- if find(v,pattern) then
- return v
- end
- end
+ r=r+1
+ result[t]=utfchar(more+256*256*256*b+256*256*a)
+ more=-1
end
+ else
+ break
+ end
end
+ t[i]=concat(result,"",1,r)
+ end
+ return t
end
-
-local function readnumber(f,n,m)
- if m then
- f:seek("set",n)
- n = m
- end
- if n == 1 then
- return byte(f:read(1))
- elseif n == 2 then
- local a, b = byte(f:read(2),1,2)
- return 256 * a + b
- elseif n == 3 then
- local a, b, c = byte(f:read(3),1,3)
- return 256*256 * a + 256 * b + c
- elseif n == 4 then
- local a, b, c, d = byte(f:read(4),1,4)
- return 256*256*256 * a + 256*256 * b + 256 * c + d
- elseif n == 8 then
- local a, b = readnumber(f,4), readnumber(f,4)
- return 256 * a + b
- elseif n == 12 then
- local a, b, c = readnumber(f,4), readnumber(f,4), readnumber(f,4)
- return 256*256 * a + 256 * b + c
- elseif n == -2 then
- local b, a = byte(f:read(2),1,2)
- return 256*a + b
- elseif n == -3 then
- local c, b, a = byte(f:read(3),1,3)
- return 256*256 * a + 256 * b + c
- elseif n == -4 then
- local d, c, b, a = byte(f:read(4),1,4)
- return 256*256*256 * a + 256*256 * b + 256*c + d
- elseif n == -8 then
- local h, g, f, e, d, c, b, a = byte(f:read(8),1,8)
- return 256*256*256*256*256*256*256 * a +
- 256*256*256*256*256*256 * b +
- 256*256*256*256*256 * c +
- 256*256*256*256 * d +
- 256*256*256 * e +
- 256*256 * f +
- 256 * g +
- h
+utf.utf32_to_utf8_be=utf32_to_utf8_be
+utf.utf32_to_utf8_le=utf32_to_utf8_le
+utf.utf16_to_utf8_be=utf16_to_utf8_be
+utf.utf16_to_utf8_le=utf16_to_utf8_le
+function utf.utf8_to_utf8(t)
+ return type(t)=="string" and lpegmatch(utflinesplitter,t) or t
+end
+function utf.utf16_to_utf8(t,endian)
+ return endian and utf16_to_utf8_be(t) or utf16_to_utf8_le(t) or t
+end
+function utf.utf32_to_utf8(t,endian)
+ return endian and utf32_to_utf8_be(t) or utf32_to_utf8_le(t) or t
+end
+local function little(c)
+ local b=byte(c)
+ if b<0x10000 then
+ return char(b%256,b/256)
+ else
+ b=b-0x10000
+ local b1,b2=b/1024+0xD800,b%1024+0xDC00
+ return char(b1%256,b1/256,b2%256,b2/256)
+ end
+end
+local function big(c)
+ local b=byte(c)
+ if b<0x10000 then
+ return char(b/256,b%256)
+ else
+ b=b-0x10000
+ local b1,b2=b/1024+0xD800,b%1024+0xDC00
+ return char(b1/256,b1%256,b2/256,b2%256)
+ end
+end
+local _,l_remap=utf.remapper(little)
+local _,b_remap=utf.remapper(big)
+function utf.utf8_to_utf16(str,littleendian)
+ if littleendian then
+ return char(255,254)..lpegmatch(l_remap,str)
+ else
+ return char(254,255)..lpegmatch(b_remap,str)
+ end
+end
+local pattern=Cs (
+ (p_utf8byte/function(unicode ) return format("0x%04X",unicode) end)*(p_utf8byte*Carg(1)/function(unicode,separator) return format("%s0x%04X",separator,unicode) end)^0
+)
+function utf.tocodes(str,separator)
+ return lpegmatch(pattern,str,1,separator or " ")
+end
+function utf.ustring(s)
+ return format("U+%05X",type(s)=="number" and s or utfbyte(s))
+end
+function utf.xstring(s)
+ return format("0x%05X",type(s)=="number" and s or utfbyte(s))
+end
+local p_nany=p_utf8char/""
+if utfgmatch then
+ function utf.count(str,what)
+ if type(what)=="string" then
+ local n=0
+ for _ in utfgmatch(str,what) do
+ n=n+1
+ end
+ return n
+ else
+ return #lpegmatch(Cs((P(what)/" "+p_nany)^0),str)
+ end
+ end
+else
+ local cache={}
+ function utf.count(str,what)
+ if type(what)=="string" then
+ local p=cache[what]
+ if not p then
+ p=Cs((P(what)/" "+p_nany)^0)
+ cache[p]=p
+ end
+ return #lpegmatch(p,str)
+ else
+ return #lpegmatch(Cs((P(what)/" "+p_nany)^0),str)
+ end
+ end
+end
+if not utf.characters then
+ function utf.characters(str)
+ return gmatch(str,".[\128-\191]*")
+ end
+ string.utfcharacters=utf.characters
+end
+if not utf.values then
+ local find=string.find
+ local dummy=function()
+ end
+ function utf.values(str)
+ local n=#str
+ if n==0 then
+ return dummy
+ elseif n==1 then
+ return function() return utfbyte(str) end
else
- return 0
+ local p=1
+ return function()
+ local b,e=find(str,".[\128-\191]*",p)
+ if b then
+ p=e+1
+ return utfbyte(sub(str,b,e))
+ end
+ end
end
+ end
+ string.utfvalues=utf.values
end
-io.readnumber = readnumber
-function io.readstring(f,n,m)
- if m then
- f:seek("set",n)
- n = m
- end
- local str = gsub(f:read(n),"%z","")
- return str
-end
+end -- of closure
---
+do -- create closure to overcome 200 locals limit
+
+package.loaded["l-math"] = package.loaded["l-math"] or true
-if not io.i_limiter then function io.i_limiter() end end -- dummy so we can test safely
-if not io.o_limiter then function io.o_limiter() end end -- dummy so we can test safely
+-- original size: 915, stripped down to: 836
+
+if not modules then modules={} end modules ['l-math']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local floor,sin,cos,tan=math.floor,math.sin,math.cos,math.tan
+if not math.round then
+ function math.round(x) return floor(x+0.5) end
+end
+if not math.div then
+ function math.div(n,m) return floor(n/m) end
+end
+if not math.mod then
+ function math.mod(n,m) return n%m end
+end
+local pipi=2*math.pi/360
+if not math.sind then
+ function math.sind(d) return sin(d*pipi) end
+ function math.cosd(d) return cos(d*pipi) end
+ function math.tand(d) return tan(d*pipi) end
+end
+if not math.odd then
+ function math.odd (n) return n%2~=0 end
+ function math.even(n) return n%2==0 end
+end
end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-number'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
+package.loaded["util-str"] = package.loaded["util-str"] or true
--- this module will be replaced when we have the bit library
+-- original size: 22834, stripped down to: 12570
+if not modules then modules={} end modules ['util-str']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+utilities=utilities or {}
+utilities.strings=utilities.strings or {}
+local strings=utilities.strings
+local format,gsub,rep,sub=string.format,string.gsub,string.rep,string.sub
+local load,dump=load,string.dump
+local tonumber,type,tostring=tonumber,type,tostring
+local unpack,concat=table.unpack,table.concat
+local P,V,C,S,R,Ct,Cs,Cp,Carg,Cc=lpeg.P,lpeg.V,lpeg.C,lpeg.S,lpeg.R,lpeg.Ct,lpeg.Cs,lpeg.Cp,lpeg.Carg,lpeg.Cc
+local patterns,lpegmatch=lpeg.patterns,lpeg.match
+local utfchar,utfbyte=utf.char,utf.byte
+local loadstripped=_LUAVERSION<5.2 and load or function(str)
+ return load(dump(load(str),true))
+end
+if not number then number={} end
+local stripper=patterns.stripzeros
+local function points(n)
+ return (not n or n==0) and "0pt" or lpegmatch(stripper,format("%.5fpt",n/65536))
+end
+local function basepoints(n)
+ return (not n or n==0) and "0bp" or lpegmatch(stripper,format("%.5fbp",n*(7200/7227)/65536))
+end
+number.points=points
+number.basepoints=basepoints
+local rubish=patterns.spaceortab^0*patterns.newline
+local anyrubish=patterns.spaceortab+patterns.newline
+local anything=patterns.anything
+local stripped=(patterns.spaceortab^1/"")*patterns.newline
+local leading=rubish^0/""
+local trailing=(anyrubish^1*patterns.endofstring)/""
+local redundant=rubish^3/"\n"
+local pattern=Cs(leading*(trailing+redundant+stripped+anything)^0)
+function strings.collapsecrlf(str)
+ return lpegmatch(pattern,str)
+end
+local repeaters={}
+function strings.newrepeater(str,offset)
+ offset=offset or 0
+ local s=repeaters[str]
+ if not s then
+ s={}
+ repeaters[str]=s
+ end
+ local t=s[offset]
+ if t then
+ return t
+ end
+ t={}
+ setmetatable(t,{ __index=function(t,k)
+ if not k then
+ return ""
+ end
+ local n=k+offset
+ local s=n>0 and rep(str,n) or ""
+ t[k]=s
+ return s
+ end })
+ s[offset]=t
+ return t
+end
+local extra,tab,start=0,0,4,0
+local nspaces=strings.newrepeater(" ")
+string.nspaces=nspaces
+local pattern=Carg(1)/function(t)
+ extra,tab,start=0,t or 7,1
+ end*Cs((
+ Cp()*patterns.tab/function(position)
+ local current=(position-start+1)+extra
+ local spaces=tab-(current-1)%tab
+ if spaces>0 then
+ extra=extra+spaces-1
+ return nspaces[spaces]
+ else
+ return ""
+ end
+ end+patterns.newline*Cp()/function(position)
+ extra,start=0,position
+ end+patterns.anything
+ )^1)
+function strings.tabtospace(str,tab)
+ return lpegmatch(pattern,str,1,tab or 7)
+end
+function strings.striplong(str)
+ str=gsub(str,"^%s*","")
+ str=gsub(str,"[\n\r]+ *","\n")
+ return str
+end
+function strings.nice(str)
+ str=gsub(str,"[:%-+_]+"," ")
+ return str
+end
+local n=0
+local sequenced=table.sequenced
+function string.autodouble(s,sep)
+ if s==nil then
+ return '""'
+ end
+ local t=type(s)
+ if t=="number" then
+ return tostring(s)
+ end
+ if t=="table" then
+ return ('"'..sequenced(s,sep or ",")..'"')
+ end
+ return ('"'..tostring(s)..'"')
+end
+function string.autosingle(s,sep)
+ if s==nil then
+ return "''"
+ end
+ local t=type(s)
+ if t=="number" then
+ return tostring(s)
+ end
+ if t=="table" then
+ return ("'"..sequenced(s,sep or ",").."'")
+ end
+ return ("'"..tostring(s).."'")
+end
+local tracedchars={}
+string.tracedchars=tracedchars
+strings.tracers=tracedchars
+function string.tracedchar(b)
+ if type(b)=="number" then
+ return tracedchars[b] or (utfchar(b).." (U+"..format('%05X',b)..")")
+ else
+ local c=utfbyte(b)
+ return tracedchars[c] or (b.." (U+"..format('%05X',c)..")")
+ end
+end
+function number.signed(i)
+ if i>0 then
+ return "+",i
+ else
+ return "-",-i
+ end
+end
+local preamble=[[
+local type = type
local tostring = tostring
-local format, floor, match, rep = string.format, math.floor, string.match, string.rep
-local concat, insert = table.concat, table.insert
+local tonumber = tonumber
+local format = string.format
+local concat = table.concat
+local signed = number.signed
+local points = number.points
+local basepoints = number.basepoints
+local utfchar = utf.char
+local utfbyte = utf.byte
local lpegmatch = lpeg.match
-
-number = number or { }
-local number = number
-
--- a,b,c,d,e,f = number.toset(100101)
-
-function number.toset(n)
- return match(tostring(n),"(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.?)")
-end
-
-function number.toevenhex(n)
- local s = format("%X",n)
- if #s % 2 == 0 then
- return s
+local nspaces = string.nspaces
+local tracedchar = string.tracedchar
+local autosingle = string.autosingle
+local autodouble = string.autodouble
+local sequenced = table.sequenced
+]]
+local template=[[
+%s
+%s
+return function(%s) return %s end
+]]
+local arguments={ "a1" }
+setmetatable(arguments,{ __index=function(t,k)
+ local v=t[k-1]..",a"..k
+ t[k]=v
+ return v
+ end
+})
+local prefix_any=C((S("+- .")+R("09"))^0)
+local prefix_tab=C((1-R("az","AZ","09","%%"))^0)
+local format_s=function(f)
+ n=n+1
+ if f and f~="" then
+ return format("format('%%%ss',a%s)",f,n)
+ else
+ return format("(a%s or '')",n)
+ end
+end
+local format_S=function(f)
+ n=n+1
+ if f and f~="" then
+ return format("format('%%%ss',tostring(a%s))",f,n)
+ else
+ return format("tostring(a%s)",n)
+ end
+end
+local format_q=function()
+ n=n+1
+ return format("(a%s and format('%%q',a%s) or '')",n,n)
+end
+local format_Q=function()
+ n=n+1
+ return format("format('%%q',tostring(a%s))",n)
+end
+local format_i=function(f)
+ n=n+1
+ if f and f~="" then
+ return format("format('%%%si',a%s)",f,n)
+ else
+ return format("a%s",n)
+ end
+end
+local format_d=format_i
+local format_I=function(f)
+ n=n+1
+ return format("format('%%s%%%si',signed(a%s))",f,n)
+end
+local format_f=function(f)
+ n=n+1
+ return format("format('%%%sf',a%s)",f,n)
+end
+local format_g=function(f)
+ n=n+1
+ return format("format('%%%sg',a%s)",f,n)
+end
+local format_G=function(f)
+ n=n+1
+ return format("format('%%%sG',a%s)",f,n)
+end
+local format_e=function(f)
+ n=n+1
+ return format("format('%%%se',a%s)",f,n)
+end
+local format_E=function(f)
+ n=n+1
+ return format("format('%%%sE',a%s)",f,n)
+end
+local format_x=function(f)
+ n=n+1
+ return format("format('%%%sx',a%s)",f,n)
+end
+local format_X=function(f)
+ n=n+1
+ return format("format('%%%sX',a%s)",f,n)
+end
+local format_o=function(f)
+ n=n+1
+ return format("format('%%%so',a%s)",f,n)
+end
+local format_c=function()
+ n=n+1
+ return format("utfchar(a%s)",n)
+end
+local format_C=function()
+ n=n+1
+ return format("tracedchar(a%s)",n)
+end
+local format_r=function(f)
+ n=n+1
+ return format("format('%%%s.0f',a%s)",f,n)
+end
+local format_h=function(f)
+ n=n+1
+ if f=="-" then
+ f=sub(f,2)
+ return format("format('%%%sx',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n)
+ else
+ return format("format('0x%%%sx',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n)
+ end
+end
+local format_H=function(f)
+ n=n+1
+ if f=="-" then
+ f=sub(f,2)
+ return format("format('%%%sX',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n)
+ else
+ return format("format('0x%%%sX',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n)
+ end
+end
+local format_u=function(f)
+ n=n+1
+ if f=="-" then
+ f=sub(f,2)
+ return format("format('%%%sx',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n)
+ else
+ return format("format('u+%%%sx',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n)
+ end
+end
+local format_U=function(f)
+ n=n+1
+ if f=="-" then
+ f=sub(f,2)
+ return format("format('%%%sX',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n)
+ else
+ return format("format('U+%%%sX',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n)
+ end
+end
+local format_p=function()
+ n=n+1
+ return format("points(a%s)",n)
+end
+local format_b=function()
+ n=n+1
+ return format("basepoints(a%s)",n)
+end
+local format_t=function(f)
+ n=n+1
+ if f and f~="" then
+ return format("concat(a%s,%q)",n,f)
+ else
+ return format("concat(a%s)",n)
+ end
+end
+local format_T=function(f)
+ n=n+1
+ if f and f~="" then
+ return format("sequenced(a%s,%q)",n,f)
+ else
+ return format("sequenced(a%s)",n)
+ end
+end
+local format_l=function()
+ n=n+1
+ return format("(a%s and 'true' or 'false')",n)
+end
+local format_L=function()
+ n=n+1
+ return format("(a%s and 'TRUE' or 'FALSE')",n)
+end
+local format_N=function()
+ n=n+1
+ return format("tostring(tonumber(a%s) or a%s)",n,n)
+end
+local format_a=function(f)
+ n=n+1
+ if f and f~="" then
+ return format("autosingle(a%s,%q)",n,f)
+ else
+ return format("autosingle(a%s)",n)
+ end
+end
+local format_A=function(f)
+ n=n+1
+ if f and f~="" then
+ return format("autodouble(a%s,%q)",n,f)
+ else
+ return format("autodouble(a%s)",n)
+ end
+end
+local format_w=function(f)
+ n=n+1
+ f=tonumber(f)
+ if f then
+ return format("nspaces[%s+a%s]",f,n)
+ else
+ return format("nspaces[a%s]",n)
+ end
+end
+local format_W=function(f)
+ return format("nspaces[%s]",tonumber(f) or 0)
+end
+local format_rest=function(s)
+ return format("%q",s)
+end
+local format_extension=function(extensions,f,name)
+ local extension=extensions[name] or "tostring(%s)"
+ local f=tonumber(f) or 1
+ if f==0 then
+ return extension
+ elseif f==1 then
+ n=n+1
+ local a="a"..n
+ return format(extension,a,a)
+ elseif f<0 then
+ local a="a"..(n+f+1)
+ return format(extension,a,a)
+ else
+ local t={}
+ for i=1,f do
+ n=n+1
+ t[#t+1]="a"..n
+ end
+ return format(extension,unpack(t))
+ end
+end
+local builder=Cs { "start",
+ start=(
+ (
+ P("%")/""*(
+ V("!")
++V("s")+V("q")+V("i")+V("d")+V("f")+V("g")+V("G")+V("e")+V("E")+V("x")+V("X")+V("o")
++V("c")+V("C")+V("S")
++V("Q")
++V("N")
++V("r")+V("h")+V("H")+V("u")+V("U")+V("p")+V("b")+V("t")+V("T")+V("l")+V("L")+V("I")+V("h")
++V("w")
++V("W")
++V("a")
++V("A")
++V("*")
+ )+V("*")
+ )*(P(-1)+Carg(1))
+ )^0,
+ ["s"]=(prefix_any*P("s"))/format_s,
+ ["q"]=(prefix_any*P("q"))/format_q,
+ ["i"]=(prefix_any*P("i"))/format_i,
+ ["d"]=(prefix_any*P("d"))/format_d,
+ ["f"]=(prefix_any*P("f"))/format_f,
+ ["g"]=(prefix_any*P("g"))/format_g,
+ ["G"]=(prefix_any*P("G"))/format_G,
+ ["e"]=(prefix_any*P("e"))/format_e,
+ ["E"]=(prefix_any*P("E"))/format_E,
+ ["x"]=(prefix_any*P("x"))/format_x,
+ ["X"]=(prefix_any*P("X"))/format_X,
+ ["o"]=(prefix_any*P("o"))/format_o,
+ ["S"]=(prefix_any*P("S"))/format_S,
+ ["Q"]=(prefix_any*P("Q"))/format_S,
+ ["N"]=(prefix_any*P("N"))/format_N,
+ ["c"]=(prefix_any*P("c"))/format_c,
+ ["C"]=(prefix_any*P("C"))/format_C,
+ ["r"]=(prefix_any*P("r"))/format_r,
+ ["h"]=(prefix_any*P("h"))/format_h,
+ ["H"]=(prefix_any*P("H"))/format_H,
+ ["u"]=(prefix_any*P("u"))/format_u,
+ ["U"]=(prefix_any*P("U"))/format_U,
+ ["p"]=(prefix_any*P("p"))/format_p,
+ ["b"]=(prefix_any*P("b"))/format_b,
+ ["t"]=(prefix_tab*P("t"))/format_t,
+ ["T"]=(prefix_tab*P("T"))/format_T,
+ ["l"]=(prefix_tab*P("l"))/format_l,
+ ["L"]=(prefix_tab*P("L"))/format_L,
+ ["I"]=(prefix_any*P("I"))/format_I,
+ ["w"]=(prefix_any*P("w"))/format_w,
+ ["W"]=(prefix_any*P("W"))/format_W,
+ ["a"]=(prefix_any*P("a"))/format_a,
+ ["A"]=(prefix_any*P("A"))/format_A,
+ ["*"]=Cs(((1-P("%"))^1+P("%%")/"%%%%")^1)/format_rest,
+ ["!"]=Carg(2)*prefix_any*P("!")*C((1-P("!"))^1)*P("!")/format_extension,
+}
+local direct=Cs (
+ P("%")/""*Cc([[local format = string.format return function(str) return format("%]])*(S("+- .")+R("09"))^0*S("sqidfgGeExXo")*Cc([[",str) end]])*P(-1)
+ )
+local function make(t,str)
+ local f
+ local p
+ local p=lpegmatch(direct,str)
+ if p then
+ f=loadstripped(p)()
+ else
+ n=0
+ p=lpegmatch(builder,str,1,"..",t._extensions_)
+ if n>0 then
+ p=format(template,preamble,t._preamble_,arguments[n],p)
+ f=loadstripped(p)()
else
- return "0" .. s
+ f=function() return str end
end
+ end
+ t[str]=f
+ return f
end
-
--- the lpeg way is slower on 8 digits, but faster on 4 digits, some 7.5%
--- on
---
--- for i=1,1000000 do
--- local a,b,c,d,e,f,g,h = number.toset(12345678)
--- local a,b,c,d = number.toset(1234)
--- local a,b,c = number.toset(123)
--- end
---
--- of course dedicated "(.)(.)(.)(.)" matches are even faster
-
-local one = lpeg.C(1-lpeg.S(''))^1
-
-function number.toset(n)
- return lpegmatch(one,tostring(n))
+local function use(t,fmt,...)
+ return t[fmt](...)
end
-
-function number.bits(n,zero)
- local t, i = { }, (zero and 0) or 1
- while n > 0 do
- local m = n % 2
- if m > 0 then
- insert(t,1,i)
- end
- n = floor(n/2)
- i = i + 1
+strings.formatters={}
+function strings.formatters.new()
+ local t={ _extensions_={},_preamble_="",_type_="formatter" }
+ setmetatable(t,{ __index=make,__call=use })
+ return t
+end
+local formatters=strings.formatters.new()
+string.formatters=formatters
+string.formatter=function(str,...) return formatters[str](...) end
+local function add(t,name,template,preamble)
+ if type(t)=="table" and t._type_=="formatter" then
+ t._extensions_[name]=template or "%s"
+ if preamble then
+ t._preamble_=preamble.."\n"..t._preamble_
end
- return t
+ end
end
+strings.formatters.add=add
+lpeg.patterns.xmlescape=Cs((P("<")/"<"+P(">")/">"+P("&")/"&"+P('"')/"""+P(1))^0)
+lpeg.patterns.texescape=Cs((C(S("#$%\\{}"))/"\\%1"+P(1))^0)
+add(formatters,"xml",[[lpegmatch(xmlescape,%s)]],[[local xmlescape = lpeg.patterns.xmlescape]])
+add(formatters,"tex",[[lpegmatch(texescape,%s)]],[[local texescape = lpeg.patterns.texescape]])
-function number.bit(p)
- return 2 ^ (p - 1) -- 1-based indexing
-end
-
-function number.hasbit(x, p) -- typical call: if hasbit(x, bit(3)) then ...
- return x % (p + p) >= p
-end
+end -- of closure
-function number.setbit(x, p)
- return hasbit(x, p) and x or x + p
-end
+do -- create closure to overcome 200 locals limit
-function number.clearbit(x, p)
- return hasbit(x, p) and x - p or x
-end
+package.loaded["util-tab"] = package.loaded["util-tab"] or true
+-- original size: 14491, stripped down to: 8512
-function number.tobitstring(n,m)
- if n == 0 then
- if m then
- rep("00000000",m)
+if not modules then modules={} end modules ['util-tab']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+utilities=utilities or {}
+utilities.tables=utilities.tables or {}
+local tables=utilities.tables
+local format,gmatch,gsub=string.format,string.gmatch,string.gsub
+local concat,insert,remove=table.concat,table.insert,table.remove
+local setmetatable,getmetatable,tonumber,tostring=setmetatable,getmetatable,tonumber,tostring
+local type,next,rawset,tonumber,tostring,load,select=type,next,rawset,tonumber,tostring,load,select
+local lpegmatch,P,Cs,Cc=lpeg.match,lpeg.P,lpeg.Cs,lpeg.Cc
+local serialize,sortedkeys,sortedpairs=table.serialize,table.sortedkeys,table.sortedpairs
+local formatters=string.formatters
+local splitter=lpeg.tsplitat(".")
+function tables.definetable(target,nofirst,nolast)
+ local composed,shortcut,t=nil,nil,{}
+ local snippets=lpegmatch(splitter,target)
+ for i=1,#snippets-(nolast and 1 or 0) do
+ local name=snippets[i]
+ if composed then
+ composed=shortcut.."."..name
+ shortcut=shortcut.."_"..name
+ t[#t+1]=formatters["local %s = %s if not %s then %s = { } %s = %s end"](shortcut,composed,shortcut,shortcut,composed,shortcut)
+ else
+ composed=name
+ shortcut=name
+ if not nofirst then
+ t[#t+1]=formatters["%s = %s or { }"](composed,composed)
+ end
+ end
+ end
+ if nolast then
+ composed=shortcut.."."..snippets[#snippets]
+ end
+ return concat(t,"\n"),composed
+end
+function tables.definedtable(...)
+ local t=_G
+ for i=1,select("#",...) do
+ local li=select(i,...)
+ local tl=t[li]
+ if not tl then
+ tl={}
+ t[li]=tl
+ end
+ t=tl
+ end
+ return t
+end
+function tables.accesstable(target,root)
+ local t=root or _G
+ for name in gmatch(target,"([^%.]+)") do
+ t=t[name]
+ if not t then
+ return
+ end
+ end
+ return t
+end
+function tables.migratetable(target,v,root)
+ local t=root or _G
+ local names=string.split(target,".")
+ for i=1,#names-1 do
+ local name=names[i]
+ t[name]=t[name] or {}
+ t=t[name]
+ if not t then
+ return
+ end
+ end
+ t[names[#names]]=v
+end
+function tables.removevalue(t,value)
+ if value then
+ for i=1,#t do
+ if t[i]==value then
+ remove(t,i)
+ end
+ end
+ end
+end
+function tables.insertbeforevalue(t,value,extra)
+ for i=1,#t do
+ if t[i]==extra then
+ remove(t,i)
+ end
+ end
+ for i=1,#t do
+ if t[i]==value then
+ insert(t,i,extra)
+ return
+ end
+ end
+ insert(t,1,extra)
+end
+function tables.insertaftervalue(t,value,extra)
+ for i=1,#t do
+ if t[i]==extra then
+ remove(t,i)
+ end
+ end
+ for i=1,#t do
+ if t[i]==value then
+ insert(t,i+1,extra)
+ return
+ end
+ end
+ insert(t,#t+1,extra)
+end
+local escape=Cs(Cc('"')*((P('"')/'""'+P(1))^0)*Cc('"'))
+function table.tocsv(t,specification)
+ if t and #t>0 then
+ local result={}
+ local r={}
+ specification=specification or {}
+ local fields=specification.fields
+ if type(fields)~="string" then
+ fields=sortedkeys(t[1])
+ end
+ local separator=specification.separator or ","
+ if specification.preamble==true then
+ for f=1,#fields do
+ r[f]=lpegmatch(escape,tostring(fields[f]))
+ end
+ result[1]=concat(r,separator)
+ end
+ for i=1,#t do
+ local ti=t[i]
+ for f=1,#fields do
+ local field=ti[fields[f]]
+ if type(field)=="string" then
+ r[f]=lpegmatch(escape,field)
else
- return "00000000"
+ r[f]=tostring(field)
end
+ end
+ result[#result+1]=concat(r,separator)
+ end
+ return concat(result,"\n")
+ else
+ return ""
+ end
+end
+local nspaces=utilities.strings.newrepeater(" ")
+local function toxml(t,d,result,step)
+ for k,v in sortedpairs(t) do
+ local s=nspaces[d]
+ local tk=type(k)
+ local tv=type(v)
+ if tv=="table" then
+ if tk=="number" then
+ result[#result+1]=formatters["%s"](s,k)
+ toxml(v,d+step,result,step)
+ result[#result+1]=formatters["%s "](s,k)
+ else
+ result[#result+1]=formatters["%s<%s>"](s,k)
+ toxml(v,d+step,result,step)
+ result[#result+1]=formatters["%s%s>"](s,k)
+ end
+ elseif tv=="string" then
+ if tk=="number" then
+ result[#result+1]=formatters["%s%!xml! "](s,k,v,k)
+ else
+ result[#result+1]=formatters["%s<%s>%!xml!%s>"](s,k,v,k)
+ end
+ elseif tk=="number" then
+ result[#result+1]=formatters["%s%S "](s,k,v,k)
else
- local t = { }
- while n > 0 do
- insert(t,1,n % 2 > 0 and 1 or 0)
- n = floor(n/2)
- end
- local nn = 8 - #t % 8
- if nn > 0 and nn < 8 then
- for i=1,nn do
- insert(t,1,0)
- end
- end
- if m then
- m = m * 8 - #t
- if m > 0 then
- insert(t,1,rep("0",m))
- end
- end
- return concat(t)
+ result[#result+1]=formatters["%s<%s>%S%s>"](s,k,v,k)
+ end
+ end
+end
+function table.toxml(t,specification)
+ specification=specification or {}
+ local name=specification.name
+ local noroot=name==false
+ local result=(specification.nobanner or noroot) and {} or { "" }
+ local indent=specification.indent or 0
+ local spaces=specification.spaces or 1
+ if noroot then
+ toxml(t,indent,result,spaces)
+ else
+ toxml({ [name or "data"]=t },indent,result,spaces)
+ end
+ return concat(result,"\n")
+end
+function tables.encapsulate(core,capsule,protect)
+ if type(capsule)~="table" then
+ protect=true
+ capsule={}
+ end
+ for key,value in next,core do
+ if capsule[key] then
+ print(formatters["\ninvalid %s %a in %a"]("inheritance",key,core))
+ os.exit()
+ else
+ capsule[key]=value
+ end
+ end
+ if protect then
+ for key,value in next,core do
+ core[key]=nil
end
+ setmetatable(core,{
+ __index=capsule,
+ __newindex=function(t,key,value)
+ if capsule[key] then
+ print(formatters["\ninvalid %s %a' in %a"]("overload",key,core))
+ os.exit()
+ else
+ rawset(t,key,value)
+ end
+ end
+ } )
+ end
+end
+local function fastserialize(t,r,outer)
+ r[#r+1]="{"
+ local n=#t
+ if n>0 then
+ for i=1,n do
+ local v=t[i]
+ local tv=type(v)
+ if tv=="string" then
+ r[#r+1]=formatters["%q,"](v)
+ elseif tv=="number" then
+ r[#r+1]=formatters["%s,"](v)
+ elseif tv=="table" then
+ fastserialize(v,r)
+ elseif tv=="boolean" then
+ r[#r+1]=formatters["%S,"](v)
+ end
+ end
+ else
+ for k,v in next,t do
+ local tv=type(v)
+ if tv=="string" then
+ r[#r+1]=formatters["[%q]=%q,"](k,v)
+ elseif tv=="number" then
+ r[#r+1]=formatters["[%q]=%s,"](k,v)
+ elseif tv=="table" then
+ r[#r+1]=formatters["[%q]="](k)
+ fastserialize(v,r)
+ elseif tv=="boolean" then
+ r[#r+1]=formatters["[%q]=%S,"](k,v)
+ end
+ end
+ end
+ if outer then
+ r[#r+1]="}"
+ else
+ r[#r+1]="},"
+ end
+ return r
+end
+function table.fastserialize(t,prefix)
+ return concat(fastserialize(t,{ prefix or "return" },true))
+end
+function table.deserialize(str)
+ if not str or str=="" then
+ return
+ end
+ local code=load(str)
+ if not code then
+ return
+ end
+ code=code()
+ if not code then
+ return
+ end
+ return code
+end
+function table.load(filename)
+ if filename then
+ local t=io.loaddata(filename)
+ if t and t~="" then
+ t=load(t)
+ if type(t)=="function" then
+ t=t()
+ if type(t)=="table" then
+ return t
+ end
+ end
+ end
+ end
+end
+function table.save(filename,t,n,...)
+ io.savedata(filename,serialize(t,n==nil and true or n,...))
+end
+local function slowdrop(t)
+ local r={}
+ local l={}
+ for i=1,#t do
+ local ti=t[i]
+ local j=0
+ for k,v in next,ti do
+ j=j+1
+ l[j]=formatters["%s=%q"](k,v)
+ end
+ r[i]=formatters[" {%t},\n"](l)
+ end
+ return formatters["return {\n%st}"](r)
+end
+local function fastdrop(t)
+ local r={ "return {\n" }
+ for i=1,#t do
+ local ti=t[i]
+ r[#r+1]=" {"
+ for k,v in next,ti do
+ r[#r+1]=formatters["%s=%q"](k,v)
+ end
+ r[#r+1]="},\n"
+ end
+ r[#r+1]="}"
+ return concat(r)
+end
+function table.drop(t,slow)
+ if #t==0 then
+ return "return { }"
+ elseif slow==true then
+ return slowdrop(t)
+ else
+ return fastdrop(t)
+ end
+end
+function table.autokey(t,k)
+ local v={}
+ t[k]=v
+ return v
+end
+local selfmapper={ __index=function(t,k) t[k]=k return k end }
+function table.twowaymapper(t)
+ if not t then
+ t={}
+ else
+ for i=0,#t do
+ local ti=t[i]
+ if ti then
+ local i=tostring(i)
+ t[i]=ti
+ t[ti]=i
+ end
+ end
+ t[""]=t[0] or ""
+ end
+ setmetatable(t,selfmapper)
+ return t
end
-
end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-set'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- This will become obsolete when we have the bitset library embedded.
-
-set = set or { }
-
-local nums = { }
-local tabs = { }
-local concat = table.concat
-local next, type = next, type
+package.loaded["util-sto"] = package.loaded["util-sto"] or true
-set.create = table.tohash
+-- original size: 4432, stripped down to: 3123
-function set.tonumber(t)
- if next(t) then
- local s = ""
- -- we could save mem by sorting, but it slows down
- for k, v in next, t do
- if v then
- -- why bother about the leading space
- s = s .. " " .. k
- end
- end
- local n = nums[s]
- if not n then
- n = #tabs + 1
- tabs[n] = t
- nums[s] = n
- end
- return n
- else
- return 0
- end
+if not modules then modules={} end modules ['util-sto']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local setmetatable,getmetatable,type=setmetatable,getmetatable,type
+utilities=utilities or {}
+utilities.storage=utilities.storage or {}
+local storage=utilities.storage
+function storage.mark(t)
+ if not t then
+ print("\nfatal error: storage cannot be marked\n")
+ os.exit()
+ return
+ end
+ local m=getmetatable(t)
+ if not m then
+ m={}
+ setmetatable(t,m)
+ end
+ m.__storage__=true
+ return t
end
-
-function set.totable(n)
- if n == 0 then
- return { }
+function storage.allocate(t)
+ t=t or {}
+ local m=getmetatable(t)
+ if not m then
+ m={}
+ setmetatable(t,m)
+ end
+ m.__storage__=true
+ return t
+end
+function storage.marked(t)
+ local m=getmetatable(t)
+ return m and m.__storage__
+end
+function storage.checked(t)
+ if not t then
+ report("\nfatal error: storage has not been allocated\n")
+ os.exit()
+ return
+ end
+ return t
+end
+function storage.setinitializer(data,initialize)
+ local m=getmetatable(data) or {}
+ m.__index=function(data,k)
+ m.__index=nil
+ initialize()
+ return data[k]
+ end
+ setmetatable(data,m)
+end
+local keyisvalue={ __index=function(t,k)
+ t[k]=k
+ return k
+end }
+function storage.sparse(t)
+ t=t or {}
+ setmetatable(t,keyisvalue)
+ return t
+end
+local function f_empty () return "" end
+local function f_self (t,k) t[k]=k return k end
+local function f_table (t,k) local v={} t[k]=v return v end
+local function f_ignore() end
+local t_empty={ __index=f_empty }
+local t_self={ __index=f_self }
+local t_table={ __index=f_table }
+local t_ignore={ __newindex=f_ignore }
+function table.setmetatableindex(t,f)
+ if type(t)~="table" then
+ f,t=t,{}
+ end
+ local m=getmetatable(t)
+ if m then
+ if f=="empty" then
+ m.__index=f_empty
+ elseif f=="key" then
+ m.__index=f_self
+ elseif f=="table" then
+ m.__index=f_table
else
- return tabs[n] or { }
+ m.__index=f
+ end
+ else
+ if f=="empty" then
+ setmetatable(t,t_empty)
+ elseif f=="key" then
+ setmetatable(t,t_self)
+ elseif f=="table" then
+ setmetatable(t,t_table)
+ else
+ setmetatable(t,{ __index=f })
end
+ end
+ return t
end
-
-function set.tolist(n)
- if n == 0 or not tabs[n] then
- return ""
+function table.setmetatablenewindex(t,f)
+ if type(t)~="table" then
+ f,t=t,{}
+ end
+ local m=getmetatable(t)
+ if m then
+ if f=="ignore" then
+ m.__newindex=f_ignore
else
- local t, n = { }, 0
- for k, v in next, tabs[n] do
- if v then
- n = n + 1
- t[n] = k
- end
- end
- return concat(t," ")
+ m.__newindex=f
end
-end
-
-function set.contains(n,s)
- if type(n) == "table" then
- return n[s]
- elseif n == 0 then
- return false
+ else
+ if f=="ignore" then
+ setmetatable(t,t_ignore)
else
- local t = tabs[n]
- return t and t[s]
+ setmetatable(t,{ __newindex=f })
end
+ end
+ return t
+end
+function table.setmetatablecall(t,f)
+ if type(t)~="table" then
+ f,t=t,{}
+ end
+ local m=getmetatable(t)
+ if m then
+ m.__call=f
+ else
+ setmetatable(t,{ __call=f })
+ end
+ return t
+end
+function table.setmetatablekey(t,key,value)
+ local m=getmetatable(t)
+ if not m then
+ m={}
+ setmetatable(t,m)
+ end
+ m[key]=value
+ return t
+end
+function table.getmetatablekey(t,key,value)
+ local m=getmetatable(t)
+ return m and m[key]
end
-
-
end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-os'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- This file deals with some operating system issues. Please don't bother me
--- with the pros and cons of operating systems as they all have their flaws
--- and benefits. Bashing one of them won't help solving problems and fixing
--- bugs faster and is a waste of time and energy.
---
--- path separators: / or \ ... we can use / everywhere
--- suffixes : dll so exe ... no big deal
--- quotes : we can use "" in most cases
--- expansion : unless "" are used * might give side effects
--- piping/threads : somewhat different for each os
--- locations : specific user file locations and settings can change over time
---
--- os.type : windows | unix (new, we already guessed os.platform)
--- os.name : windows | msdos | linux | macosx | solaris | .. | generic (new)
--- os.platform : extended os.name with architecture
-
--- maybe build io.flush in os.execute
-
-local os = os
-local find, format, gsub, upper, gmatch = string.find, string.format, string.gsub, string.upper, string.gmatch
-local concat = table.concat
-local random, ceil = math.random, math.ceil
-local rawget, rawset, type, getmetatable, setmetatable, tonumber = rawget, rawset, type, getmetatable, setmetatable, tonumber
-
--- The following code permits traversing the environment table, at least
--- in luatex. Internally all environment names are uppercase.
-
-if not os.__getenv__ then
-
- os.__getenv__ = os.getenv
- os.__setenv__ = os.setenv
+package.loaded["util-prs"] = package.loaded["util-prs"] or true
- if os.env then
-
- local osgetenv = os.getenv
- local ossetenv = os.setenv
- local osenv = os.env local _ = osenv.PATH -- initialize the table
-
- function os.setenv(k,v)
- if v == nil then
- v = ""
- end
- local K = upper(k)
- osenv[K] = v
- if type(v) == "table" then
- v = concat(v,";") -- path
- end
- ossetenv(K,v)
- end
-
- function os.getenv(k)
- local K = upper(k)
- local v = osenv[K] or osenv[k] or osgetenv(K) or osgetenv(k)
- if v == "" then
- return nil
- else
- return v
- end
- end
+-- original size: 16976, stripped down to: 12143
+if not modules then modules={} end modules ['util-prs']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local lpeg,table,string=lpeg,table,string
+local P,R,V,S,C,Ct,Cs,Carg,Cc,Cg,Cf,Cp=lpeg.P,lpeg.R,lpeg.V,lpeg.S,lpeg.C,lpeg.Ct,lpeg.Cs,lpeg.Carg,lpeg.Cc,lpeg.Cg,lpeg.Cf,lpeg.Cp
+local lpegmatch,lpegpatterns=lpeg.match,lpeg.patterns
+local concat,format,gmatch,find=table.concat,string.format,string.gmatch,string.find
+local tostring,type,next,rawset=tostring,type,next,rawset
+utilities=utilities or {}
+local parsers=utilities.parsers or {}
+utilities.parsers=parsers
+local patterns=parsers.patterns or {}
+parsers.patterns=patterns
+local setmetatableindex=table.setmetatableindex
+local sortedhash=table.sortedhash
+local digit=R("09")
+local space=P(' ')
+local equal=P("=")
+local comma=P(",")
+local lbrace=P("{")
+local rbrace=P("}")
+local lparent=P("(")
+local rparent=P(")")
+local period=S(".")
+local punctuation=S(".,:;")
+local spacer=lpegpatterns.spacer
+local whitespace=lpegpatterns.whitespace
+local newline=lpegpatterns.newline
+local anything=lpegpatterns.anything
+local endofstring=lpegpatterns.endofstring
+local nobrace=1-(lbrace+rbrace )
+local noparent=1-(lparent+rparent)
+local escape,left,right=P("\\"),P('{'),P('}')
+lpegpatterns.balanced=P {
+ [1]=((escape*(left+right))+(1-(left+right))+V(2))^0,
+ [2]=left*V(1)*right
+}
+local nestedbraces=P { lbrace*(nobrace+V(1))^0*rbrace }
+local nestedparents=P { lparent*(noparent+V(1))^0*rparent }
+local spaces=space^0
+local argument=Cs((lbrace/"")*((nobrace+nestedbraces)^0)*(rbrace/""))
+local content=(1-endofstring)^0
+lpegpatterns.nestedbraces=nestedbraces
+lpegpatterns.nestedparents=nestedparents
+lpegpatterns.nested=nestedbraces
+lpegpatterns.argument=argument
+lpegpatterns.content=content
+local value=P(lbrace*C((nobrace+nestedbraces)^0)*rbrace)+C((nestedbraces+(1-comma))^0)
+local key=C((1-equal-comma)^1)
+local pattern_a=(space+comma)^0*(key*equal*value+key*C(""))
+local pattern_c=(space+comma)^0*(key*equal*value)
+local key=C((1-space-equal-comma)^1)
+local pattern_b=spaces*comma^0*spaces*(key*((spaces*equal*spaces*value)+C("")))
+local hash={}
+local function set(key,value)
+ hash[key]=value
+end
+local pattern_a_s=(pattern_a/set)^1
+local pattern_b_s=(pattern_b/set)^1
+local pattern_c_s=(pattern_c/set)^1
+patterns.settings_to_hash_a=pattern_a_s
+patterns.settings_to_hash_b=pattern_b_s
+patterns.settings_to_hash_c=pattern_c_s
+function parsers.make_settings_to_hash_pattern(set,how)
+ if how=="strict" then
+ return (pattern_c/set)^1
+ elseif how=="tolerant" then
+ return (pattern_b/set)^1
+ else
+ return (pattern_a/set)^1
+ end
+end
+function parsers.settings_to_hash(str,existing)
+ if str and str~="" then
+ hash=existing or {}
+ lpegmatch(pattern_a_s,str)
+ return hash
+ else
+ return {}
+ end
+end
+function parsers.settings_to_hash_tolerant(str,existing)
+ if str and str~="" then
+ hash=existing or {}
+ lpegmatch(pattern_b_s,str)
+ return hash
+ else
+ return {}
+ end
+end
+function parsers.settings_to_hash_strict(str,existing)
+ if str and str~="" then
+ hash=existing or {}
+ lpegmatch(pattern_c_s,str)
+ return next(hash) and hash
+ else
+ return nil
+ end
+end
+local separator=comma*space^0
+local value=P(lbrace*C((nobrace+nestedbraces)^0)*rbrace)+C((nestedbraces+(1-comma))^0)
+local pattern=spaces*Ct(value*(separator*value)^0)
+patterns.settings_to_array=pattern
+function parsers.settings_to_array(str,strict)
+ if not str or str=="" then
+ return {}
+ elseif strict then
+ if find(str,"{") then
+ return lpegmatch(pattern,str)
else
-
- local ossetenv = os.setenv
- local osgetenv = os.getenv
- local osenv = { }
-
- function os.setenv(k,v)
- if v == nil then
- v = ""
- end
- local K = upper(k)
- osenv[K] = v
- end
-
- function os.getenv(k)
- local K = upper(k)
- local v = osenv[K] or osgetenv(K) or osgetenv(k)
- if v == "" then
- return nil
- else
- return v
- end
- end
-
- local function __index(t,k)
- return os.getenv(k)
- end
- local function __newindex(t,k,v)
- os.setenv(k,v)
+ return { str }
+ end
+ else
+ return lpegmatch(pattern,str)
+ end
+end
+local function set(t,v)
+ t[#t+1]=v
+end
+local value=P(Carg(1)*value)/set
+local pattern=value*(separator*value)^0*Carg(1)
+function parsers.add_settings_to_array(t,str)
+ return lpegmatch(pattern,str,nil,t)
+end
+function parsers.hash_to_string(h,separator,yes,no,strict,omit)
+ if h then
+ local t,tn,s={},0,table.sortedkeys(h)
+ omit=omit and table.tohash(omit)
+ for i=1,#s do
+ local key=s[i]
+ if not omit or not omit[key] then
+ local value=h[key]
+ if type(value)=="boolean" then
+ if yes and no then
+ if value then
+ tn=tn+1
+ t[tn]=key..'='..yes
+ elseif not strict then
+ tn=tn+1
+ t[tn]=key..'='..no
+ end
+ elseif value or not strict then
+ tn=tn+1
+ t[tn]=key..'='..tostring(value)
+ end
+ else
+ tn=tn+1
+ t[tn]=key..'='..value
end
-
- os.env = { }
-
- setmetatable(os.env, { __index = __index, __newindex = __newindex } )
-
+ end
end
-
+ return concat(t,separator or ",")
+ else
+ return ""
+ end
end
-
--- end of environment hack
-
-local execute, spawn, exec, iopopen, ioflush = os.execute, os.spawn or os.execute, os.exec or os.execute, io.popen, io.flush
-
-function os.execute(...) ioflush() return execute(...) end
-function os.spawn (...) ioflush() return spawn (...) end
-function os.exec (...) ioflush() return exec (...) end
-function io.popen (...) ioflush() return iopopen(...) end
-
-function os.resultof(command)
- local handle = io.popen(command,"r")
- return handle and handle:read("*all") or ""
+function parsers.array_to_string(a,separator)
+ if a then
+ return concat(a,separator or ",")
+ else
+ return ""
+ end
+end
+function parsers.settings_to_set(str,t)
+ t=t or {}
+ for s in gmatch(str,"[^, ]+") do
+ t[s]=true
+ end
+ return t
+end
+function parsers.simple_hash_to_string(h,separator)
+ local t,tn={},0
+ for k,v in sortedhash(h) do
+ if v then
+ tn=tn+1
+ t[tn]=k
+ end
+ end
+ return concat(t,separator or ",")
end
-
-if not io.fileseparator then
- if find(os.getenv("PATH"),";") then
- io.fileseparator, io.pathseparator, os.type = "\\", ";", os.type or "mswin"
+local value=P(lbrace*C((nobrace+nestedbraces)^0)*rbrace)+C(digit^1*lparent*(noparent+nestedparents)^1*rparent)+C((nestedbraces+(1-comma))^1)
+local pattern_a=spaces*Ct(value*(separator*value)^0)
+local function repeater(n,str)
+ if not n then
+ return str
+ else
+ local s=lpegmatch(pattern_a,str)
+ if n==1 then
+ return unpack(s)
else
- io.fileseparator, io.pathseparator, os.type = "/" , ":", os.type or "unix"
- end
+ local t,tn={},0
+ for i=1,n do
+ for j=1,#s do
+ tn=tn+1
+ t[tn]=s[j]
+ end
+ end
+ return unpack(t)
+ end
+ end
+end
+local value=P(lbrace*C((nobrace+nestedbraces)^0)*rbrace)+(C(digit^1)/tonumber*lparent*Cs((noparent+nestedparents)^1)*rparent)/repeater+C((nestedbraces+(1-comma))^1)
+local pattern_b=spaces*Ct(value*(separator*value)^0)
+function parsers.settings_to_array_with_repeat(str,expand)
+ if expand then
+ return lpegmatch(pattern_b,str) or {}
+ else
+ return lpegmatch(pattern_a,str) or {}
+ end
+end
+local value=lbrace*C((nobrace+nestedbraces)^0)*rbrace
+local pattern=Ct((space+value)^0)
+function parsers.arguments_to_table(str)
+ return lpegmatch(pattern,str)
end
-
-os.type = os.type or (io.pathseparator == ";" and "windows") or "unix"
-os.name = os.name or (os.type == "windows" and "mswin" ) or "linux"
-
-if os.type == "windows" then
- os.libsuffix, os.binsuffix, os.binsuffixes = 'dll', 'exe', { 'exe', 'cmd', 'bat' }
-else
- os.libsuffix, os.binsuffix, os.binsuffixes = 'so', '', { '' }
+function parsers.getparameters(self,class,parentclass,settings)
+ local sc=self[class]
+ if not sc then
+ sc={}
+ self[class]=sc
+ if parentclass then
+ local sp=self[parentclass]
+ if not sp then
+ sp={}
+ self[parentclass]=sp
+ end
+ setmetatableindex(sc,sp)
+ end
+ end
+ parsers.settings_to_hash(settings,sc)
end
-
-function os.launch(str)
- if os.type == "windows" then
- os.execute("start " .. str) -- os.spawn ?
+function parsers.listitem(str)
+ return gmatch(str,"[^, ]+")
+end
+local pattern=Cs { "start",
+ start=V("one")+V("two")+V("three"),
+ rest=(Cc(",")*V("thousand"))^0*(P(".")+endofstring)*anything^0,
+ thousand=digit*digit*digit,
+ one=digit*V("rest"),
+ two=digit*digit*V("rest"),
+ three=V("thousand")*V("rest"),
+}
+lpegpatterns.splitthousands=pattern
+function parsers.splitthousands(str)
+ return lpegmatch(pattern,str) or str
+end
+local optionalwhitespace=whitespace^0
+lpegpatterns.words=Ct((Cs((1-punctuation-whitespace)^1)+anything)^1)
+lpegpatterns.sentences=Ct((optionalwhitespace*Cs((1-period)^0*period))^1)
+lpegpatterns.paragraphs=Ct((optionalwhitespace*Cs((whitespace^1*endofstring/""+1-(spacer^0*newline*newline))^1))^1)
+local dquote=P('"')
+local equal=P('=')
+local escape=P('\\')
+local separator=S(' ,')
+local key=C((1-equal)^1)
+local value=dquote*C((1-dquote-escape*dquote)^0)*dquote
+local pattern=Cf(Ct("")*Cg(key*equal*value)*separator^0,rawset)^0*P(-1)
+patterns.keq_to_hash_c=pattern
+function parsers.keq_to_hash(str)
+ if str and str~="" then
+ return lpegmatch(pattern,str)
+ else
+ return {}
+ end
+end
+local defaultspecification={ separator=",",quote='"' }
+function parsers.csvsplitter(specification)
+ specification=specification and table.setmetatableindex(specification,defaultspecification) or defaultspecification
+ local separator=specification.separator
+ local quotechar=specification.quote
+ local separator=S(separator~="" and separator or ",")
+ local whatever=C((1-separator-newline)^0)
+ if quotechar and quotechar~="" then
+ local quotedata=nil
+ for chr in gmatch(quotechar,".") do
+ local quotechar=P(chr)
+ local quoteword=quotechar*C((1-quotechar)^0)*quotechar
+ if quotedata then
+ quotedata=quotedata+quoteword
+ else
+ quotedata=quoteword
+ end
+ end
+ whatever=quotedata+whatever
+ end
+ local parser=Ct((Ct(whatever*(separator*whatever)^0)*S("\n\r"))^0 )
+ return function(data)
+ return lpegmatch(parser,data)
+ end
+end
+function parsers.rfc4180splitter(specification)
+ specification=specification and table.setmetatableindex(specification,defaultspecification) or defaultspecification
+ local separator=specification.separator
+ local quotechar=P(specification.quote)
+ local dquotechar=quotechar*quotechar
+/specification.quote
+ local separator=S(separator~="" and separator or ",")
+ local escaped=quotechar*Cs((dquotechar+(1-quotechar))^0)*quotechar
+ local non_escaped=C((1-quotechar-newline-separator)^1)
+ local field=escaped+non_escaped
+ local record=Ct((field*separator^-1)^1)
+ local headerline=record*Cp()
+ local wholeblob=Ct((newline^-1*record)^0)
+ return function(data,getheader)
+ if getheader then
+ local header,position=lpegmatch(headerline,data)
+ local data=lpegmatch(wholeblob,data,position)
+ return data,header
else
- os.execute(str .. " &") -- os.spawn ?
+ return lpegmatch(wholeblob,data)
+ end
+ end
+end
+local function ranger(first,last,n,action)
+ if not first then
+ elseif last==true then
+ for i=first,n or first do
+ action(i)
+ end
+ elseif last then
+ for i=first,last do
+ action(i)
+ end
+ else
+ action(first)
+ end
+end
+local cardinal=lpegpatterns.cardinal/tonumber
+local spacers=lpegpatterns.spacer^0
+local endofstring=lpegpatterns.endofstring
+local stepper=spacers*(C(cardinal)*(spacers*S(":-")*spacers*(C(cardinal)+Cc(true) )+Cc(false) )*Carg(1)*Carg(2)/ranger*S(", ")^0 )^1
+local stepper=spacers*(C(cardinal)*(spacers*S(":-")*spacers*(C(cardinal)+(P("*")+endofstring)*Cc(true) )+Cc(false) )*Carg(1)*Carg(2)/ranger*S(", ")^0 )^1*endofstring
+function parsers.stepper(str,n,action)
+ if type(n)=="function" then
+ lpegmatch(stepper,str,1,false,n or print)
+ else
+ lpegmatch(stepper,str,1,n,action or print)
+ end
+end
+local pattern_math=Cs((P("%")/"\\percent "+P("^")*Cc("{")*lpegpatterns.integer*Cc("}")+P(1))^0)
+local pattern_text=Cs((P("%")/"\\percent "+(P("^")/"\\high")*Cc("{")*lpegpatterns.integer*Cc("}")+P(1))^0)
+patterns.unittotex=pattern
+function parsers.unittotex(str,textmode)
+ return lpegmatch(textmode and pattern_text or pattern_math,str)
+end
+local pattern=Cs((P("^")/""*lpegpatterns.integer*Cc(" ")+P(1))^0)
+function parsers.unittoxml(str)
+ return lpegmatch(pattern,str)
+end
+local cache={}
+local spaces=lpeg.patterns.space^0
+local dummy=function() end
+table.setmetatableindex(cache,function(t,k)
+ local separator=P(k)
+ local value=(1-separator)^0
+ local pattern=spaces*C(value)*separator^0*Cp()
+ t[k]=pattern
+ return pattern
+end)
+local commalistiterator=cache[","]
+function utilities.parsers.iterator(str,separator)
+ local n=#str
+ if n==0 then
+ return dummy
+ else
+ local pattern=separator and cache[separator] or commalistiterator
+ local p=1
+ return function()
+ if p<=n then
+ local s,e=lpegmatch(pattern,str,p)
+ if e then
+ p=e
+ return s
+ end
+ end
end
+ end
end
-
-if not os.times then
- -- utime = user time
- -- stime = system time
- -- cutime = children user time
- -- cstime = children system time
- function os.times()
- return {
- utime = os.gettimeofday(), -- user
- stime = 0, -- system
- cutime = 0, -- children user
- cstime = 0, -- children system
- }
+local function initialize(t,name)
+ local source=t[name]
+ if source then
+ local result={}
+ for k,v in next,t[name] do
+ result[k]=v
end
+ return result
+ else
+ return {}
+ end
end
-
-os.gettimeofday = os.gettimeofday or os.clock
-
-local startuptime = os.gettimeofday()
-
-function os.runtime()
- return os.gettimeofday() - startuptime
+local function fetch(t,name)
+ return t[name] or {}
end
-
-
--- no need for function anymore as we have more clever code and helpers now
--- this metatable trickery might as well disappear
-
-os.resolvers = os.resolvers or { } -- will become private
-
-local resolvers = os.resolvers
-
-local osmt = getmetatable(os) or { __index = function(t,k) t[k] = "unset" return "unset" end } -- maybe nil
-local osix = osmt.__index
-
-osmt.__index = function(t,k)
- return (resolvers[k] or osix)(t,k)
+function process(result,more)
+ for k,v in next,more do
+ result[k]=v
+ end
+ return result
end
-
-setmetatable(os,osmt)
-
--- we can use HOSTTYPE on some platforms
-
-local name, platform = os.name or "linux", os.getenv("MTX_PLATFORM") or ""
-
-local function guess()
- local architecture = os.resultof("uname -m") or ""
- if architecture ~= "" then
- return architecture
- end
- architecture = os.getenv("HOSTTYPE") or ""
- if architecture ~= "" then
- return architecture
- end
- return os.resultof("echo $HOSTTYPE") or ""
+local name=C((1-S(", "))^1)
+local parser=(Carg(1)*name/initialize)*(S(", ")^1*(Carg(1)*name/fetch))^0
+local merge=Cf(parser,process)
+function utilities.parsers.mergehashes(hash,list)
+ return lpegmatch(merge,list,1,hash)
end
-if platform ~= "" then
-
- os.platform = platform
-elseif os.type == "windows" then
+end -- of closure
- -- we could set the variable directly, no function needed here
+do -- create closure to overcome 200 locals limit
- function os.resolvers.platform(t,k)
- local platform, architecture = "", os.getenv("PROCESSOR_ARCHITECTURE") or ""
- if find(architecture,"AMD64") then
- platform = "mswin-64"
- else
- platform = "mswin"
- end
- os.setenv("MTX_PLATFORM",platform)
- os.platform = platform
- return platform
- end
+package.loaded["util-fmt"] = package.loaded["util-fmt"] or true
-elseif name == "linux" then
+-- original size: 2274, stripped down to: 1781
- function os.resolvers.platform(t,k)
- -- we sometimes have HOSTTYPE set so let's check that first
- local platform, architecture = "", os.getenv("HOSTTYPE") or os.resultof("uname -m") or ""
- if find(architecture,"x86_64") then
- platform = "linux-64"
- elseif find(architecture,"ppc") then
- platform = "linux-ppc"
- else
- platform = "linux"
- end
- os.setenv("MTX_PLATFORM",platform)
- os.platform = platform
- return platform
- end
-
-elseif name == "macosx" then
-
- --[[
- Identifying the architecture of OSX is quite a mess and this
- is the best we can come up with. For some reason $HOSTTYPE is
- a kind of pseudo environment variable, not known to the current
- environment. And yes, uname cannot be trusted either, so there
- is a change that you end up with a 32 bit run on a 64 bit system.
- Also, some proper 64 bit intel macs are too cheap (low-end) and
- therefore not permitted to run the 64 bit kernel.
- ]]--
-
- function os.resolvers.platform(t,k)
- -- local platform, architecture = "", os.getenv("HOSTTYPE") or ""
- -- if architecture == "" then
- -- architecture = os.resultof("echo $HOSTTYPE") or ""
- -- end
- local platform, architecture = "", os.resultof("echo $HOSTTYPE") or ""
- if architecture == "" then
- -- print("\nI have no clue what kind of OSX you're running so let's assume an 32 bit intel.\n")
- platform = "osx-intel"
- elseif find(architecture,"i386") then
- platform = "osx-intel"
- elseif find(architecture,"x86_64") then
- platform = "osx-64"
+if not modules then modules={} end modules ['util-fmt']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+utilities=utilities or {}
+utilities.formatters=utilities.formatters or {}
+local formatters=utilities.formatters
+local concat,format=table.concat,string.format
+local tostring,type=tostring,type
+local strip=string.strip
+local lpegmatch=lpeg.match
+local stripper=lpeg.patterns.stripzeros
+function formatters.stripzeros(str)
+ return lpegmatch(stripper,str)
+end
+function formatters.formatcolumns(result,between)
+ if result and #result>0 then
+ between=between or " "
+ local widths,numbers={},{}
+ local first=result[1]
+ local n=#first
+ for i=1,n do
+ widths[i]=0
+ end
+ for i=1,#result do
+ local r=result[i]
+ for j=1,n do
+ local rj=r[j]
+ local tj=type(rj)
+ if tj=="number" then
+ numbers[j]=true
+ end
+ if tj~="string" then
+ rj=tostring(rj)
+ r[j]=rj
+ end
+ local w=#rj
+ if w>widths[j] then
+ widths[j]=w
+ end
+ end
+ end
+ for i=1,n do
+ local w=widths[i]
+ if numbers[i] then
+ if w>80 then
+ widths[i]="%s"..between
+ else
+ widths[i]="%0"..w.."i"..between
+ end
+ else
+ if w>80 then
+ widths[i]="%s"..between
+ elseif w>0 then
+ widths[i]="%-"..w.."s"..between
else
- platform = "osx-ppc"
+ widths[i]="%s"
end
- os.setenv("MTX_PLATFORM",platform)
- os.platform = platform
- return platform
+ end
+ end
+ local template=strip(concat(widths))
+ for i=1,#result do
+ local str=format(template,unpack(result[i]))
+ result[i]=strip(str)
end
+ end
+ return result
+end
-elseif name == "sunos" then
- function os.resolvers.platform(t,k)
- local platform, architecture = "", os.resultof("uname -m") or ""
- if find(architecture,"sparc") then
- platform = "solaris-sparc"
- else -- if architecture == 'i86pc'
- platform = "solaris-intel"
- end
- os.setenv("MTX_PLATFORM",platform)
- os.platform = platform
- return platform
- end
+end -- of closure
-elseif name == "freebsd" then
+do -- create closure to overcome 200 locals limit
- function os.resolvers.platform(t,k)
- local platform, architecture = "", os.resultof("uname -m") or ""
- if find(architecture,"amd64") then
- platform = "freebsd-amd64"
- else
- platform = "freebsd"
- end
- os.setenv("MTX_PLATFORM",platform)
- os.platform = platform
- return platform
- end
+package.loaded["trac-set"] = package.loaded["trac-set"] or true
-elseif name == "kfreebsd" then
+-- original size: 12365, stripped down to: 8799
- function os.resolvers.platform(t,k)
- -- we sometimes have HOSTTYPE set so let's check that first
- local platform, architecture = "", os.getenv("HOSTTYPE") or os.resultof("uname -m") or ""
- if find(architecture,"x86_64") then
- platform = "kfreebsd-amd64"
+if not modules then modules={} end modules ['trac-set']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local type,next,tostring=type,next,tostring
+local concat=table.concat
+local format,find,lower,gsub,topattern=string.format,string.find,string.lower,string.gsub,string.topattern
+local is_boolean=string.is_boolean
+local settings_to_hash=utilities.parsers.settings_to_hash
+local allocate=utilities.storage.allocate
+utilities=utilities or {}
+local utilities=utilities
+local setters=utilities.setters or {}
+utilities.setters=setters
+local data={}
+local trace_initialize=false
+function setters.initialize(filename,name,values)
+ local setter=data[name]
+ if setter then
+ frozen=true
+ local data=setter.data
+ if data then
+ for key,newvalue in next,values do
+ local newvalue=is_boolean(newvalue,newvalue)
+ local functions=data[key]
+ if functions then
+ local oldvalue=functions.value
+ if functions.frozen then
+ if trace_initialize then
+ setter.report("%s: %a is %s to %a",filename,key,"frozen",oldvalue)
+ end
+ elseif #functions>0 and not oldvalue then
+ if trace_initialize then
+ setter.report("%s: %a is %s to %a",filename,key,"set",newvalue)
+ end
+ for i=1,#functions do
+ functions[i](newvalue)
+ end
+ functions.value=newvalue
+ functions.frozen=functions.frozen or frozen
+ else
+ if trace_initialize then
+ setter.report("%s: %a is %s as %a",filename,key,"kept",oldvalue)
+ end
+ end
else
- platform = "kfreebsd-i386"
+ functions={ default=newvalue,frozen=frozen }
+ data[key]=functions
+ if trace_initialize then
+ setter.report("%s: %a is %s to %a",filename,key,"defaulted",newvalue)
+ end
end
- os.setenv("MTX_PLATFORM",platform)
- os.platform = platform
- return platform
+ end
+ return true
end
-
-else
-
- -- platform = "linux"
- -- os.setenv("MTX_PLATFORM",platform)
- -- os.platform = platform
-
- function os.resolvers.platform(t,k)
- local platform = "linux"
- os.setenv("MTX_PLATFORM",platform)
- os.platform = platform
- return platform
- end
-
+ end
end
-
--- beware, we set the randomseed
-
--- from wikipedia: Version 4 UUIDs use a scheme relying only on random numbers. This algorithm sets the
--- version number as well as two reserved bits. All other bits are set using a random or pseudorandom
--- data source. Version 4 UUIDs have the form xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx with hexadecimal
--- digits x and hexadecimal digits 8, 9, A, or B for y. e.g. f47ac10b-58cc-4372-a567-0e02b2c3d479.
---
--- as we don't call this function too often there is not so much risk on repetition
-
-local t = { 8, 9, "a", "b" }
-
-function os.uuid()
- return format("%04x%04x-4%03x-%s%03x-%04x-%04x%04x%04x",
- random(0xFFFF),random(0xFFFF),
- random(0x0FFF),
- t[ceil(random(4))] or 8,random(0x0FFF),
- random(0xFFFF),
- random(0xFFFF),random(0xFFFF),random(0xFFFF)
- )
+local function set(t,what,newvalue)
+ local data=t.data
+ if not data.frozen then
+ local done=t.done
+ if type(what)=="string" then
+ what=settings_to_hash(what)
+ end
+ if type(what)~="table" then
+ return
+ end
+ if not done then
+ done={}
+ t.done=done
+ end
+ for w,value in next,what do
+ if value=="" then
+ value=newvalue
+ elseif not value then
+ value=false
+ else
+ value=is_boolean(value,value)
+ end
+ w=topattern(w,true,true)
+ for name,functions in next,data do
+ if done[name] then
+ elseif find(name,w) then
+ done[name]=true
+ for i=1,#functions do
+ functions[i](value)
+ end
+ functions.value=value
+ end
+ end
+ end
+ end
end
-
-local d
-
-function os.timezone(delta)
- d = d or tonumber(tonumber(os.date("%H")-os.date("!%H")))
- if delta then
- if d > 0 then
- return format("+%02i:00",d)
- else
- return format("-%02i:00",-d)
- end
+local function reset(t)
+ local data=t.data
+ if not data.frozen then
+ for name,functions in next,data do
+ for i=1,#functions do
+ functions[i](false)
+ end
+ functions.value=false
+ end
+ end
+end
+local function enable(t,what)
+ set(t,what,true)
+end
+local function disable(t,what)
+ local data=t.data
+ if not what or what=="" then
+ t.done={}
+ reset(t)
+ else
+ set(t,what,false)
+ end
+end
+function setters.register(t,what,...)
+ local data=t.data
+ what=lower(what)
+ local functions=data[what]
+ if not functions then
+ functions={}
+ data[what]=functions
+ if trace_initialize then
+ t.report("defining %a",what)
+ end
+ end
+ local default=functions.default
+ for i=1,select("#",...) do
+ local fnc=select(i,...)
+ local typ=type(fnc)
+ if typ=="string" then
+ if trace_initialize then
+ t.report("coupling %a to %a",what,fnc)
+ end
+ local s=fnc
+ fnc=function(value) set(t,s,value) end
+ elseif typ~="function" then
+ fnc=nil
+ end
+ if fnc then
+ functions[#functions+1]=fnc
+ local value=functions.value or default
+ if value~=nil then
+ fnc(value)
+ functions.value=value
+ end
+ end
+ end
+ return false
+end
+function setters.enable(t,what)
+ local e=t.enable
+ t.enable,t.done=enable,{}
+ enable(t,what)
+ t.enable,t.done=e,{}
+end
+function setters.disable(t,what)
+ local e=t.disable
+ t.disable,t.done=disable,{}
+ disable(t,what)
+ t.disable,t.done=e,{}
+end
+function setters.reset(t)
+ t.done={}
+ reset(t)
+end
+function setters.list(t)
+ local list=table.sortedkeys(t.data)
+ local user,system={},{}
+ for l=1,#list do
+ local what=list[l]
+ if find(what,"^%*") then
+ system[#system+1]=what
else
- return 1
+ user[#user+1]=what
end
+ end
+ return user,system
end
-
-local memory = { }
-
-local function which(filename)
- local fullname = memory[filename]
- if fullname == nil then
- local suffix = file.suffix(filename)
- local suffixes = suffix == "" and os.binsuffixes or { suffix }
- for directory in gmatch(os.getenv("PATH"),"[^" .. io.pathseparator .."]+") do
- local df = file.join(directory,filename)
- for i=1,#suffixes do
- local dfs = file.addsuffix(df,suffixes[i])
- if io.exists(dfs) then
- fullname = dfs
- break
- end
- end
- end
- if not fullname then
- fullname = false
- end
- memory[filename] = fullname
+function setters.show(t)
+ local category=t.name
+ local list=setters.list(t)
+ t.report()
+ for k=1,#list do
+ local name=list[k]
+ local functions=t.data[name]
+ if functions then
+ local value,default,modules=functions.value,functions.default,#functions
+ value=value==nil and "unset" or tostring(value)
+ default=default==nil and "unset" or tostring(default)
+ t.report("%-50s modules: %2i default: %-12s value: %-12s",name,modules,default,value)
+ end
+ end
+ t.report()
+end
+local enable,disable,register,list,show=setters.enable,setters.disable,setters.register,setters.list,setters.show
+function setters.report(setter,...)
+ print(format("%-15s : %s\n",setter.name,format(...)))
+end
+local function default(setter,name)
+ local d=setter.data[name]
+ return d and d.default
+end
+local function value(setter,name)
+ local d=setter.data[name]
+ return d and (d.value or d.default)
+end
+function setters.new(name)
+ local setter
+ setter={
+ data=allocate(),
+ name=name,
+ report=function(...) setters.report (setter,...) end,
+ enable=function(...) enable (setter,...) end,
+ disable=function(...) disable (setter,...) end,
+ register=function(...) register(setter,...) end,
+ list=function(...) list (setter,...) end,
+ show=function(...) show (setter,...) end,
+ default=function(...) return default (setter,...) end,
+ value=function(...) return value (setter,...) end,
+ }
+ data[name]=setter
+ return setter
+end
+trackers=setters.new("trackers")
+directives=setters.new("directives")
+experiments=setters.new("experiments")
+local t_enable,t_disable=trackers .enable,trackers .disable
+local d_enable,d_disable=directives .enable,directives .disable
+local e_enable,e_disable=experiments.enable,experiments.disable
+local trace_directives=false local trace_directives=false trackers.register("system.directives",function(v) trace_directives=v end)
+local trace_experiments=false local trace_experiments=false trackers.register("system.experiments",function(v) trace_experiments=v end)
+function directives.enable(...)
+ if trace_directives then
+ directives.report("enabling: % t",{...})
+ end
+ d_enable(...)
+end
+function directives.disable(...)
+ if trace_directives then
+ directives.report("disabling: % t",{...})
+ end
+ d_disable(...)
+end
+function experiments.enable(...)
+ if trace_experiments then
+ experiments.report("enabling: % t",{...})
+ end
+ e_enable(...)
+end
+function experiments.disable(...)
+ if trace_experiments then
+ experiments.report("disabling: % t",{...})
+ end
+ e_disable(...)
+end
+directives.register("system.nostatistics",function(v)
+ if statistics then
+ statistics.enable=not v
+ else
+ end
+end)
+directives.register("system.nolibraries",function(v)
+ if libraries then
+ libraries=nil
+ else
+ end
+end)
+if environment then
+ local engineflags=environment.engineflags
+ if engineflags then
+ local list=engineflags["c:trackers"] or engineflags["trackers"]
+ if type(list)=="string" then
+ setters.initialize("commandline flags","trackers",settings_to_hash(list))
end
- return fullname
+ local list=engineflags["c:directives"] or engineflags["directives"]
+ if type(list)=="string" then
+ setters.initialize("commandline flags","directives",settings_to_hash(list))
+ end
+ end
+end
+if texconfig then
+ local function set(k,v)
+ v=tonumber(v)
+ if v then
+ texconfig[k]=v
+ end
+ end
+ directives.register("luatex.expanddepth",function(v) set("expand_depth",v) end)
+ directives.register("luatex.hashextra",function(v) set("hash_extra",v) end)
+ directives.register("luatex.nestsize",function(v) set("nest_size",v) end)
+ directives.register("luatex.maxinopen",function(v) set("max_in_open",v) end)
+ directives.register("luatex.maxprintline",function(v) set("max_print_line",v) end)
+ directives.register("luatex.maxstrings",function(v) set("max_strings",v) end)
+ directives.register("luatex.paramsize",function(v) set("param_size",v) end)
+ directives.register("luatex.savesize",function(v) set("save_size",v) end)
+ directives.register("luatex.stacksize",function(v) set("stack_size",v) end)
end
-
-os.which = which
-os.where = which
-
--- print(os.which("inkscape.exe"))
--- print(os.which("inkscape"))
--- print(os.which("gs.exe"))
--- print(os.which("ps2pdf"))
end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-file'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- needs a cleanup
-
-file = file or { }
-local file = file
-
-local insert, concat = table.insert, table.concat
-local find, gmatch, match, gsub, sub, char, lower = string.find, string.gmatch, string.match, string.gsub, string.sub, string.char, string.lower
-local lpegmatch = lpeg.match
-local getcurrentdir, attributes = lfs.currentdir, lfs.attributes
+package.loaded["trac-log"] = package.loaded["trac-log"] or true
-local P, R, S, C, Cs, Cp, Cc = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Cs, lpeg.Cp, lpeg.Cc
+-- original size: 21795, stripped down to: 14194
-local function dirname(name,default)
- return match(name,"^(.+)[/\\].-$") or (default or "")
+if not modules then modules={} end modules ['trac-log']={
+ version=1.001,
+ comment="companion to trac-log.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local write_nl,write=texio and texio.write_nl or print,texio and texio.write or io.write
+local format,gmatch,find=string.format,string.gmatch,string.find
+local concat,insert,remove=table.concat,table.insert,table.remove
+local topattern=string.topattern
+local texcount=tex and tex.count
+local next,type,select=next,type,select
+local utfchar=utf.char
+local setmetatableindex=table.setmetatableindex
+local formatters=string.formatters
+logs=logs or {}
+local logs=logs
+local moreinfo=[[
+More information about ConTeXt and the tools that come with it can be found at:
+]].."\n"..[[
+maillist : ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+webpage : http://www.pragma-ade.nl / http://tex.aanhet.net
+wiki : http://contextgarden.net
+]]
+utilities.strings.formatters.add (
+ formatters,"unichr",
+ [["U+" .. format("%%05X",%s) .. " (" .. utfchar(%s) .. ")"]]
+)
+utilities.strings.formatters.add (
+ formatters,"chruni",
+ [[utfchar(%s) .. " (U+" .. format("%%05X",%s) .. ")"]]
+)
+local function ignore() end
+setmetatableindex(logs,function(t,k) t[k]=ignore;return ignore end)
+local report,subreport,status,settarget,setformats,settranslations
+local direct,subdirect,writer,pushtarget,poptarget
+if tex and (tex.jobname or tex.formatname) then
+ local valueiskey={ __index=function(t,k) t[k]=k return k end }
+ local target="term and log"
+ logs.flush=io.flush
+ local formats={} setmetatable(formats,valueiskey)
+ local translations={} setmetatable(translations,valueiskey)
+ writer=function(...)
+ write_nl(target,...)
+ end
+ newline=function()
+ write_nl(target,"\n")
+ end
+ local f_one=formatters["%-15s > %s\n"]
+ local f_two=formatters["%-15s >\n"]
+ report=function(a,b,c,...)
+ if c then
+ write_nl(target,f_one(translations[a],formatters[formats[b]](c,...)))
+ elseif b then
+ write_nl(target,f_one(translations[a],formats[b]))
+ elseif a then
+ write_nl(target,f_two(translations[a]))
+ else
+ write_nl(target,"\n")
+ end
+ end
+ local f_one=formatters["%-15s > %s"]
+ local f_two=formatters["%-15s >"]
+ direct=function(a,b,c,...)
+ if c then
+ return f_one(translations[a],formatters[formats[b]](c,...))
+ elseif b then
+ return f_one(translations[a],formats[b])
+ elseif a then
+ return f_two(translations[a])
+ else
+ return ""
+ end
+ end
+ local f_one=formatters["%-15s > %s > %s\n"]
+ local f_two=formatters["%-15s > %s >\n"]
+ subreport=function(a,s,b,c,...)
+ if c then
+ write_nl(target,f_one(translations[a],translations[s],formatters[formats[b]](c,...)))
+ elseif b then
+ write_nl(target,f_one(translations[a],translations[s],formats[b]))
+ elseif a then
+ write_nl(target,f_two(translations[a],translations[s]))
+ else
+ write_nl(target,"\n")
+ end
+ end
+ local f_one=formatters["%-15s > %s > %s"]
+ local f_two=formatters["%-15s > %s >"]
+ subdirect=function(a,s,b,c,...)
+ if c then
+ return f_one(translations[a],translations[s],formatters[formats[b]](c,...))
+ elseif b then
+ return f_one(translations[a],translations[s],formats[b])
+ elseif a then
+ return f_two(translations[a],translations[s])
+ else
+ return ""
+ end
+ end
+ local f_one=formatters["%-15s : %s\n"]
+ local f_two=formatters["%-15s :\n"]
+ status=function(a,b,c,...)
+ if c then
+ write_nl(target,f_one(translations[a],formatters[formats[b]](c,...)))
+ elseif b then
+ write_nl(target,f_one(translations[a],formats[b]))
+ elseif a then
+ write_nl(target,f_two(translations[a]))
+ else
+ write_nl(target,"\n")
+ end
+ end
+ local targets={
+ logfile="log",
+ log="log",
+ file="log",
+ console="term",
+ terminal="term",
+ both="term and log",
+ }
+ settarget=function(whereto)
+ target=targets[whereto or "both"] or targets.both
+ if target=="term" or target=="term and log" then
+ logs.flush=io.flush
+ else
+ logs.flush=ignore
+ end
+ end
+ local stack={}
+ pushtarget=function(newtarget)
+ insert(stack,target)
+ settarget(newtarget)
+ end
+ poptarget=function()
+ if #stack>0 then
+ settarget(remove(stack))
+ end
+ end
+ setformats=function(f)
+ formats=f
+ end
+ settranslations=function(t)
+ translations=t
+ end
+else
+ logs.flush=ignore
+ writer=write_nl
+ newline=function()
+ write_nl("\n")
+ end
+ local f_one=formatters["%-15s | %s"]
+ local f_two=formatters["%-15s |"]
+ report=function(a,b,c,...)
+ if c then
+ write_nl(f_one(a,formatters[b](c,...)))
+ elseif b then
+ write_nl(f_one(a,b))
+ elseif a then
+ write_nl(f_two(a))
+ else
+ write_nl("")
+ end
+ end
+ local f_one=formatters["%-15s | %s | %s"]
+ local f_two=formatters["%-15s | %s |"]
+ subreport=function(a,sub,b,c,...)
+ if c then
+ write_nl(f_one(a,sub,formatters[b](c,...)))
+ elseif b then
+ write_nl(f_one(a,sub,b))
+ elseif a then
+ write_nl(f_two(a,sub))
+ else
+ write_nl("")
+ end
+ end
+ local f_one=formatters["%-15s : %s\n"]
+ local f_two=formatters["%-15s :\n"]
+ status=function(a,b,c,...)
+ if c then
+ write_nl(f_one(a,formatters[b](c,...)))
+ elseif b then
+ write_nl(f_one(a,b))
+ elseif a then
+ write_nl(f_two(a))
+ else
+ write_nl("\n")
+ end
+ end
+ direct=ignore
+ subdirect=ignore
+ settarget=ignore
+ pushtarget=ignore
+ poptarget=ignore
+ setformats=ignore
+ settranslations=ignore
+end
+logs.report=report
+logs.subreport=subreport
+logs.status=status
+logs.settarget=settarget
+logs.pushtarget=pushtarget
+logs.poptarget=poptarget
+logs.setformats=setformats
+logs.settranslations=settranslations
+logs.direct=direct
+logs.subdirect=subdirect
+logs.writer=writer
+logs.newline=newline
+local data,states={},nil
+function logs.reporter(category,subcategory)
+ local logger=data[category]
+ if not logger then
+ local state=false
+ if states==true then
+ state=true
+ elseif type(states)=="table" then
+ for c,_ in next,states do
+ if find(category,c) then
+ state=true
+ break
+ end
+ end
+ end
+ logger={
+ reporters={},
+ state=state,
+ }
+ data[category]=logger
+ end
+ local reporter=logger.reporters[subcategory or "default"]
+ if not reporter then
+ if subcategory then
+ reporter=function(...)
+ if not logger.state then
+ subreport(category,subcategory,...)
+ end
+ end
+ logger.reporters[subcategory]=reporter
+ else
+ local tag=category
+ reporter=function(...)
+ if not logger.state then
+ report(category,...)
+ end
+ end
+ logger.reporters.default=reporter
+ end
+ end
+ return reporter
end
-
-local function basename(name)
- return match(name,"^.+[/\\](.-)$") or name
+logs.new=logs.reporter
+local ctxreport=logs.writer
+function logs.setmessenger(m)
+ ctxreport=m
end
-
--- local function nameonly(name)
--- return (gsub(match(name,"^.+[/\\](.-)$") or name,"%..*$",""))
--- end
-
-local function nameonly(name)
- return (gsub(match(name,"^.+[/\\](.-)$") or name,"%.[%a%d]+$",""))
+function logs.messenger(category,subcategory)
+ if subcategory then
+ return function(...)
+ ctxreport(subdirect(category,subcategory,...))
+ end
+ else
+ return function(...)
+ ctxreport(direct(category,...))
+ end
+ end
end
-
-local function extname(name,default)
- return match(name,"^.+%.([^/\\]-)$") or default or ""
+local function setblocked(category,value)
+ if category==true then
+ category,value="*",true
+ elseif category==false then
+ category,value="*",false
+ elseif value==nil then
+ value=true
+ end
+ if category=="*" then
+ states=value
+ for k,v in next,data do
+ v.state=value
+ end
+ else
+ states=utilities.parsers.settings_to_hash(category)
+ for c,_ in next,states do
+ if data[c] then
+ v.state=value
+ else
+ c=topattern(c,true,true)
+ for k,v in next,data do
+ if find(k,c) then
+ v.state=value
+ end
+ end
+ end
+ end
+ end
end
-
-local function splitname(name)
- local n, s = match(name,"^(.+)%.([^/\\]-)$")
- return n or name, s or ""
+function logs.disable(category,value)
+ setblocked(category,value==nil and true or value)
end
-
-file.basename = basename
-file.dirname = dirname
-file.nameonly = nameonly
-file.extname = extname
-file.suffix = extname
-
-function file.removesuffix(filename)
- return (gsub(filename,"%.[%a%d]+$",""))
+function logs.enable(category)
+ setblocked(category,false)
end
-
-function file.addsuffix(filename, suffix, criterium)
- if not suffix or suffix == "" then
- return filename
- elseif criterium == true then
- return filename .. "." .. suffix
- elseif not criterium then
- local n, s = splitname(filename)
- if not s or s == "" then
- return filename .. "." .. suffix
- else
- return filename
- end
+function logs.categories()
+ return table.sortedkeys(data)
+end
+function logs.show()
+ local n,c,s,max=0,0,0,0
+ for category,v in table.sortedpairs(data) do
+ n=n+1
+ local state=v.state
+ local reporters=v.reporters
+ local nc=#category
+ if nc>c then
+ c=nc
+ end
+ for subcategory,_ in next,reporters do
+ local ns=#subcategory
+ if ns>c then
+ s=ns
+ end
+ local m=nc+ns
+ if m>max then
+ max=m
+ end
+ end
+ local subcategories=concat(table.sortedkeys(reporters),", ")
+ if state==true then
+ state="disabled"
+ elseif state==false then
+ state="enabled"
else
- local n, s = splitname(filename)
- if s and s ~= "" then
- local t = type(criterium)
- if t == "table" then
- -- keep if in criterium
- for i=1,#criterium do
- if s == criterium[i] then
- return filename
- end
- end
- elseif t == "string" then
- -- keep if criterium
- if s == criterium then
- return filename
- end
- end
- end
- return n .. "." .. suffix
+ state="unknown"
end
+ report("logging","category %a, subcategories %a, state %a",category,subcategories,state)
+ end
+ report("logging","categories: %s, max category: %s, max subcategory: %s, max combined: %s",n,c,s,max)
end
-
-
-function file.replacesuffix(filename, suffix)
- return (gsub(filename,"%.[%a%d]+$","")) .. "." .. suffix
+local delayed_reporters={}
+setmetatableindex(delayed_reporters,function(t,k)
+ local v=logs.reporter(k.name)
+ t[k]=v
+ return v
+end)
+function utilities.setters.report(setter,...)
+ delayed_reporters[setter](...)
end
-
-
-local trick_1 = char(1)
-local trick_2 = "^" .. trick_1 .. "/+"
-
-function file.join(...) -- rather dirty
- local lst = { ... }
- local a, b = lst[1], lst[2]
- if not a or a == "" then -- not a added
- lst[1] = trick_1
- elseif b and find(a,"^/+$") and find(b,"^/") then
- lst[1] = ""
- lst[2] = gsub(b,"^/+","")
- end
- local pth = concat(lst,"/")
- pth = gsub(pth,"\\","/")
- local a, b = match(pth,"^(.*://)(.*)$")
- if a and b then
- return a .. gsub(b,"//+","/")
+directives.register("logs.blocked",function(v)
+ setblocked(v,true)
+end)
+directives.register("logs.target",function(v)
+ settarget(v)
+end)
+local report_pages=logs.reporter("pages")
+local real,user,sub
+function logs.start_page_number()
+ real,user,sub=texcount.realpageno,texcount.userpageno,texcount.subpageno
+end
+local timing=false
+local starttime=nil
+local lasttime=nil
+trackers.register("pages.timing",function(v)
+ starttime=os.clock()
+ timing=true
+end)
+function logs.stop_page_number()
+ if timing then
+ local elapsed,average
+ local stoptime=os.clock()
+ if not lasttime or real<2 then
+ elapsed=stoptime
+ average=stoptime
+ starttime=stoptime
+ else
+ elapsed=stoptime-lasttime
+ average=(stoptime-starttime)/(real-1)
+ end
+ lasttime=stoptime
+ if real<=0 then
+ report_pages("flushing page, time %0.04f / %0.04f",elapsed,average)
+ elseif user<=0 then
+ report_pages("flushing realpage %s, time %0.04f / %0.04f",real,elapsed,average)
+ elseif sub<=0 then
+ report_pages("flushing realpage %s, userpage %s, time %0.04f / %0.04f",real,user,elapsed,average)
+ else
+ report_pages("flushing realpage %s, userpage %s, subpage %s, time %0.04f / %0.04f",real,user,sub,elapsed,average)
+ end
+ else
+ if real<=0 then
+ report_pages("flushing page")
+ elseif user<=0 then
+ report_pages("flushing realpage %s",real)
+ elseif sub<=0 then
+ report_pages("flushing realpage %s, userpage %s",real,user)
+ else
+ report_pages("flushing realpage %s, userpage %s, subpage %s",real,user,sub)
end
- a, b = match(pth,"^(//)(.*)$")
- if a and b then
- return a .. gsub(b,"//+","/")
+ end
+ logs.flush()
+end
+local report_files=logs.reporter("files")
+local nesting=0
+local verbose=false
+local hasscheme=url.hasscheme
+function logs.show_open(name)
+end
+function logs.show_close(name)
+end
+function logs.show_load(name)
+end
+local simple=logs.reporter("comment")
+logs.simple=simple
+logs.simpleline=simple
+function logs.setprogram () end
+function logs.extendbanner() end
+function logs.reportlines () end
+function logs.reportbanner() end
+function logs.reportline () end
+function logs.simplelines () end
+function logs.help () end
+local Carg,C,lpegmatch=lpeg.Carg,lpeg.C,lpeg.match
+local p_newline=lpeg.patterns.newline
+local linewise=(
+ Carg(1)*C((1-p_newline)^1)/function(t,s) t.report(s) end+Carg(1)*p_newline^2/function(t) t.report() end+p_newline
+)^1
+local function reportlines(t,str)
+ if str then
+ lpegmatch(linewise,str,1,t)
+ end
+end
+local function reportbanner(t)
+ local banner=t.banner
+ if banner then
+ t.report(banner)
+ t.report()
+ end
+end
+local function reportversion(t)
+ local banner=t.banner
+ if banner then
+ t.report(banner)
+ end
+end
+local function reporthelp(t,...)
+ local helpinfo=t.helpinfo
+ if type(helpinfo)=="string" then
+ reportlines(t,helpinfo)
+ elseif type(helpinfo)=="table" then
+ for i=1,select("#",...) do
+ reportlines(t,t.helpinfo[select(i,...)])
+ if i %s => %s => %s\r"](os.date("%d/%m/%y %H:%m:%S"),process,jobname,category,format(...))
+ for i=1,10 do
+ local f=io.open(whereto,"a")
+ if f then
+ f:write(message)
+ f:close()
+ break
else
- local f = io.open(name,"ab")
- if f then
- f:close()
- os.remove(name)
- return true
- end
+ sleep(0.1)
end
- return false
+ end
end
-
-function file.is_readable(name)
- local a = attributes(name)
- return a and sub(a.permissions,1,1) == "r"
+local report_system=logs.reporter("system","logs")
+function logs.obsolete(old,new)
+ local o=loadstring("return "..new)()
+ if type(o)=="function" then
+ return function(...)
+ report_system("function %a is obsolete, use %a",old,new)
+ loadstring(old.."="..new.." return "..old)()(...)
+ end
+ elseif type(o)=="table" then
+ local t,m={},{}
+ m.__index=function(t,k)
+ report_system("table %a is obsolete, use %a",old,new)
+ m.__index,m.__newindex=o,o
+ return o[k]
+ end
+ m.__newindex=function(t,k,v)
+ report_system("table %a is obsolete, use %a",old,new)
+ m.__index,m.__newindex=o,o
+ o[k]=v
+ end
+ if libraries then
+ libraries.obsolete[old]=t
+ end
+ setmetatable(t,m)
+ return t
+ end
end
-
-file.isreadable = file.is_readable -- depricated
-file.iswritable = file.is_writable -- depricated
-
--- todo: lpeg \\ / .. does not save much
-
-local checkedsplit = string.checkedsplit
-
-function file.splitpath(str,separator) -- string
- str = gsub(str,"\\","/")
- return checkedsplit(str,separator or io.pathseparator)
+if utilities then
+ utilities.report=report_system
end
-
-function file.joinpath(tab,separator) -- table
- return concat(tab,separator or io.pathseparator) -- can have trailing //
+if tex and tex.error then
+ function logs.texerrormessage(...)
+ tex.error(format(...),{})
+ end
+else
+ function logs.texerrormessage(...)
+ print(format(...))
+ end
end
+io.stdout:setvbuf('no')
+io.stderr:setvbuf('no')
--- we can hash them weakly
+end -- of closure
-function file.collapsepath(str,anchor)
- if anchor and not find(str,"^/") and not find(str,"^%a:") then
- str = getcurrentdir() .. "/" .. str
- end
- if str == "" or str =="." then
- return "."
- elseif find(str,"^%.%.") then
- str = gsub(str,"\\","/")
- return str
- elseif not find(str,"%.") then
- str = gsub(str,"\\","/")
- return str
- end
- str = gsub(str,"\\","/")
- local starter, rest = match(str,"^(%a+:/*)(.-)$")
- if starter then
- str = rest
- end
- local oldelements = checkedsplit(str,"/")
- local newelements = { }
- local i = #oldelements
- while i > 0 do
- local element = oldelements[i]
- if element == '.' then
- -- do nothing
- elseif element == '..' then
- local n = i - 1
- while n > 0 do
- local element = oldelements[n]
- if element ~= '..' and element ~= '.' then
- oldelements[n] = '.'
- break
- else
- n = n - 1
- end
- end
- if n < 1 then
- insert(newelements,1,'..')
- end
- elseif element ~= "" then
- insert(newelements,1,element)
- end
- i = i - 1
- end
- if #newelements == 0 then
- return starter or "."
- elseif starter then
- return starter .. concat(newelements, '/')
- elseif find(str,"^/") then
- return "/" .. concat(newelements,'/')
- else
- return concat(newelements, '/')
- end
-end
+do -- create closure to overcome 200 locals limit
+package.loaded["trac-inf"] = package.loaded["trac-inf"] or true
-function file.robustname(str,strict)
- str = gsub(str,"[^%a%d%/%-%.\\]+","-")
- if strict then
- return lower(gsub(str,"^%-*(.-)%-*$","%1"))
- else
- return str
+-- original size: 5791, stripped down to: 4540
+
+if not modules then modules={} end modules ['trac-inf']={
+ version=1.001,
+ comment="companion to trac-inf.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local type,tonumber=type,tonumber
+local format,lower=string.format,string.lower
+local concat=table.concat
+local clock=os.gettimeofday or os.clock
+statistics=statistics or {}
+local statistics=statistics
+statistics.enable=true
+statistics.threshold=0.01
+local statusinfo,n,registered,timers={},0,{},{}
+table.setmetatableindex(timers,function(t,k)
+ local v={ timing=0,loadtime=0 }
+ t[k]=v
+ return v
+end)
+local function hastiming(instance)
+ return instance and timers[instance]
+end
+local function resettiming(instance)
+ timers[instance or "notimer"]={ timing=0,loadtime=0 }
+end
+local function starttiming(instance)
+ local timer=timers[instance or "notimer"]
+ local it=timer.timing or 0
+ if it==0 then
+ timer.starttime=clock()
+ if not timer.loadtime then
+ timer.loadtime=0
+ end
+ end
+ timer.timing=it+1
+end
+local function stoptiming(instance,report)
+ local timer=timers[instance or "notimer"]
+ local it=timer.timing
+ if it>1 then
+ timer.timing=it-1
+ else
+ local starttime=timer.starttime
+ if starttime then
+ local stoptime=clock()
+ local loadtime=stoptime-starttime
+ timer.stoptime=stoptime
+ timer.loadtime=timer.loadtime+loadtime
+ if report then
+ statistics.report("load time %0.3f",loadtime)
+ end
+ timer.timing=0
+ return loadtime
+ end
+ end
+ return 0
+end
+local function elapsed(instance)
+ if type(instance)=="number" then
+ return instance or 0
+ else
+ local timer=timers[instance or "notimer"]
+ return timer and timer.loadtime or 0
+ end
+end
+local function elapsedtime(instance)
+ return format("%0.3f",elapsed(instance))
+end
+local function elapsedindeed(instance)
+ return elapsed(instance)>statistics.threshold
+end
+local function elapsedseconds(instance,rest)
+ if elapsedindeed(instance) then
+ return format("%0.3f seconds %s",elapsed(instance),rest or "")
+ end
+end
+statistics.hastiming=hastiming
+statistics.resettiming=resettiming
+statistics.starttiming=starttiming
+statistics.stoptiming=stoptiming
+statistics.elapsed=elapsed
+statistics.elapsedtime=elapsedtime
+statistics.elapsedindeed=elapsedindeed
+statistics.elapsedseconds=elapsedseconds
+function statistics.register(tag,fnc)
+ if statistics.enable and type(fnc)=="function" then
+ local rt=registered[tag] or (#statusinfo+1)
+ statusinfo[rt]={ tag,fnc }
+ registered[tag]=rt
+ if #tag>n then n=#tag end
+ end
+end
+local report=logs.reporter("mkiv lua stats")
+function statistics.show()
+ if statistics.enable then
+ local register=statistics.register
+ register("luatex banner",function()
+ return lower(status.banner)
+ end)
+ register("control sequences",function()
+ return format("%s of %s + %s",status.cs_count,status.hash_size,status.hash_extra)
+ end)
+ register("callbacks",function()
+ local total,indirect=status.callbacks or 0,status.indirect_callbacks or 0
+ return format("%s direct, %s indirect, %s total",total-indirect,indirect,total)
+ end)
+ if jit then
+ local status={ jit.status() }
+ if status[1] then
+ register("luajit status",function()
+ return concat(status," ",2)
+ end)
+ end
+ end
+ register("current memory usage",statistics.memused)
+ register("runtime",statistics.runtime)
+ logs.newline()
+ for i=1,#statusinfo do
+ local s=statusinfo[i]
+ local r=s[2]()
+ if r then
+ report("%s: %s",s[1],r)
+ end
end
+ statistics.enable=false
+ end
end
-
-file.readdata = io.loaddata
-file.savedata = io.savedata
-
-function file.copy(oldname,newname)
- file.savedata(newname,io.loaddata(oldname))
+function statistics.memused()
+ local round=math.round or math.floor
+ return format("%s MB (ctx: %s MB)",round(collectgarbage("count")/1000),round(status.luastate_bytes/1000000))
+end
+starttiming(statistics)
+function statistics.formatruntime(runtime)
+ return format("%s seconds",runtime)
+end
+function statistics.runtime()
+ stoptiming(statistics)
+ return statistics.formatruntime(elapsedtime(statistics))
+end
+local report=logs.reporter("system")
+function statistics.timed(action)
+ starttiming("run")
+ action()
+ stoptiming("run")
+ report("total runtime: %s",elapsedtime("run"))
+end
+commands=commands or {}
+function commands.resettimer(name)
+ resettiming(name or "whatever")
+ starttiming(name or "whatever")
+end
+function commands.elapsedtime(name)
+ stoptiming(name or "whatever")
+ context(elapsedtime(name or "whatever"))
end
-
--- lpeg variants, slightly faster, not always
+end -- of closure
+do -- create closure to overcome 200 locals limit
+package.loaded["trac-pro"] = package.loaded["trac-pro"] or true
+-- original size: 5773, stripped down to: 3453
+if not modules then modules={} end modules ['trac-pro']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local getmetatable,setmetatable,rawset,type=getmetatable,setmetatable,rawset,type
+local trace_namespaces=false trackers.register("system.namespaces",function(v) trace_namespaces=v end)
+local report_system=logs.reporter("system","protection")
+namespaces=namespaces or {}
+local namespaces=namespaces
+local registered={}
+local function report_index(k,name)
+ if trace_namespaces then
+ report_system("reference to %a in protected namespace %a: %s",k,name,debug.traceback())
+ else
+ report_system("reference to %a in protected namespace %a",k,name)
+ end
+end
+local function report_newindex(k,name)
+ if trace_namespaces then
+ report_system("assignment to %a in protected namespace %a: %s",k,name,debug.traceback())
+ else
+ report_system("assignment to %a in protected namespace %a",k,name)
+ end
+end
+local function register(name)
+ local data=name=="global" and _G or _G[name]
+ if not data then
+ return
+ end
+ registered[name]=data
+ local m=getmetatable(data)
+ if not m then
+ m={}
+ setmetatable(data,m)
+ end
+ local index,newindex={},{}
+ m.__saved__index=m.__index
+ m.__no__index=function(t,k)
+ if not index[k] then
+ index[k]=true
+ report_index(k,name)
+ end
+ return nil
+ end
+ m.__saved__newindex=m.__newindex
+ m.__no__newindex=function(t,k,v)
+ if not newindex[k] then
+ newindex[k]=true
+ report_newindex(k,name)
+ end
+ rawset(t,k,v)
+ end
+ m.__protection__depth=0
+end
+local function private(name)
+ local data=registered[name]
+ if not data then
+ data=_G[name]
+ if not data then
+ data={}
+ _G[name]=data
+ end
+ register(name)
+ end
+ return data
+end
+local function protect(name)
+ local data=registered[name]
+ if not data then
+ return
+ end
+ local m=getmetatable(data)
+ local pd=m.__protection__depth
+ if pd>0 then
+ m.__protection__depth=pd+1
+ else
+ m.__save_d_index,m.__saved__newindex=m.__index,m.__newindex
+ m.__index,m.__newindex=m.__no__index,m.__no__newindex
+ m.__protection__depth=1
+ end
+end
+local function unprotect(name)
+ local data=registered[name]
+ if not data then
+ return
+ end
+ local m=getmetatable(data)
+ local pd=m.__protection__depth
+ if pd>1 then
+ m.__protection__depth=pd-1
+ else
+ m.__index,m.__newindex=m.__saved__index,m.__saved__newindex
+ m.__protection__depth=0
+ end
+end
+local function protectall()
+ for name,_ in next,registered do
+ if name~="global" then
+ protect(name)
+ end
+ end
+end
+local function unprotectall()
+ for name,_ in next,registered do
+ if name~="global" then
+ unprotect(name)
+ end
+ end
+end
+namespaces.register=register
+namespaces.private=private
+namespaces.protect=protect
+namespaces.unprotect=unprotect
+namespaces.protectall=protectall
+namespaces.unprotectall=unprotectall
+namespaces.private("namespaces") registered={} register("global")
+directives.register("system.protect",function(v)
+ if v then
+ protectall()
+ else
+ unprotectall()
+ end
+end)
+directives.register("system.checkglobals",function(v)
+ if v then
+ report_system("enabling global namespace guard")
+ protect("global")
+ else
+ report_system("disabling global namespace guard")
+ unprotect("global")
+ end
+end)
+end -- of closure
+do -- create closure to overcome 200 locals limit
+package.loaded["util-lua"] = package.loaded["util-lua"] or true
+-- original size: 12575, stripped down to: 8700
-
-
-
-
-
-
-
--- also rewrite previous
-
-local letter = R("az","AZ") + S("_-+")
-local separator = P("://")
-
-local qualified = P(".")^0 * P("/") + letter*P(":") + letter^1*separator + letter^1 * P("/")
-local rootbased = P("/") + letter*P(":")
-
-lpeg.patterns.qualified = qualified
-lpeg.patterns.rootbased = rootbased
-
--- ./name ../name /name c: :// name/name
-
-function file.is_qualified_path(filename)
- return lpegmatch(qualified,filename) ~= nil
+if not modules then modules={} end modules ['util-lua']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ comment="the strip code is written by Peter Cawley",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local rep,sub,byte,dump,format=string.rep,string.sub,string.byte,string.dump,string.format
+local load,loadfile,type=load,loadfile,type
+utilities=utilities or {}
+utilities.lua=utilities.lua or {}
+local luautilities=utilities.lua
+local report_lua=logs.reporter("system","lua")
+local tracestripping=false
+local forcestupidcompile=true
+luautilities.stripcode=true
+luautilities.alwaysstripcode=false
+luautilities.nofstrippedchunks=0
+luautilities.nofstrippedbytes=0
+local strippedchunks={}
+luautilities.strippedchunks=strippedchunks
+luautilities.suffixes={
+ tma="tma",
+ tmc=jit and "tmb" or "tmc",
+ lua="lua",
+ luc=jit and "lub" or "luc",
+ lui="lui",
+ luv="luv",
+ luj="luj",
+ tua="tua",
+ tuc="tuc",
+}
+if jit or status.luatex_version>=74 then
+ local function register(name)
+ if tracestripping then
+ report_lua("stripped bytecode from %a",name or "unknown")
+ end
+ strippedchunks[#strippedchunks+1]=name
+ luautilities.nofstrippedchunks=luautilities.nofstrippedchunks+1
+ end
+ local function stupidcompile(luafile,lucfile,strip)
+ local code=io.loaddata(luafile)
+ if code and code~="" then
+ code=load(code)
+ if code then
+ code=dump(code,strip and luautilities.stripcode or luautilities.alwaysstripcode)
+ if code and code~="" then
+ register(name)
+ io.savedata(lucfile,code)
+ return true,0
+ end
+ else
+ report_lua("fatal error %a in file %a",1,luafile)
+ end
+ else
+ report_lua("fatal error %a in file %a",2,luafile)
+ end
+ return false,0
+ end
+ function luautilities.loadedluacode(fullname,forcestrip,name)
+ name=name or fullname
+ local code=environment.loadpreprocessedfile and environment.loadpreprocessedfile(fullname) or loadfile(fullname)
+ if code then
+ code()
+ end
+ if forcestrip and luautilities.stripcode then
+ if type(forcestrip)=="function" then
+ forcestrip=forcestrip(fullname)
+ end
+ if forcestrip or luautilities.alwaysstripcode then
+ register(name)
+ return load(dump(code,true)),0
+ else
+ return code,0
+ end
+ elseif luautilities.alwaysstripcode then
+ register(name)
+ return load(dump(code,true)),0
+ else
+ return code,0
+ end
+ end
+ function luautilities.strippedloadstring(code,forcestrip,name)
+ if forcestrip and luautilities.stripcode or luautilities.alwaysstripcode then
+ code=load(code)
+ if not code then
+ report_lua("fatal error %a in file %a",3,name)
+ end
+ register(name)
+ code=dump(code,true)
+ end
+ return load(code),0
+ end
+ function luautilities.compile(luafile,lucfile,cleanup,strip,fallback)
+ report_lua("compiling %a into %a",luafile,lucfile)
+ os.remove(lucfile)
+ local done=stupidcompile(luafile,lucfile,strip~=false)
+ if done then
+ report_lua("dumping %a into %a stripped",luafile,lucfile)
+ if cleanup==true and lfs.isfile(lucfile) and lfs.isfile(luafile) then
+ report_lua("removing %a",luafile)
+ os.remove(luafile)
+ end
+ end
+ return done
+ end
+ function luautilities.loadstripped(...)
+ local l=load(...)
+ if l then
+ return load(dump(l,true))
+ end
+ end
+else
+ local function register(name,before,after)
+ local delta=before-after
+ if tracestripping then
+ report_lua("bytecodes stripped from %a, # before %s, # after %s, delta %s",name,before,after,delta)
+ end
+ strippedchunks[#strippedchunks+1]=name
+ luautilities.nofstrippedchunks=luautilities.nofstrippedchunks+1
+ luautilities.nofstrippedbytes=luautilities.nofstrippedbytes+delta
+ return delta
+ end
+ local strip_code_pc
+ if _MAJORVERSION==5 and _MINORVERSION==1 then
+ strip_code_pc=function(dump,name)
+ local before=#dump
+ local version,format,endian,int,size,ins,num=byte(dump,5,11)
+ local subint
+ if endian==1 then
+ subint=function(dump,i,l)
+ local val=0
+ for n=l,1,-1 do
+ val=val*256+byte(dump,i+n-1)
+ end
+ return val,i+l
+ end
+ else
+ subint=function(dump,i,l)
+ local val=0
+ for n=1,l,1 do
+ val=val*256+byte(dump,i+n-1)
+ end
+ return val,i+l
+ end
+ end
+ local strip_function
+ strip_function=function(dump)
+ local count,offset=subint(dump,1,size)
+ local stripped,dirty=rep("\0",size),offset+count
+ offset=offset+count+int*2+4
+ offset=offset+int+subint(dump,offset,int)*ins
+ count,offset=subint(dump,offset,int)
+ for n=1,count do
+ local t
+ t,offset=subint(dump,offset,1)
+ if t==1 then
+ offset=offset+1
+ elseif t==4 then
+ offset=offset+size+subint(dump,offset,size)
+ elseif t==3 then
+ offset=offset+num
+ end
+ end
+ count,offset=subint(dump,offset,int)
+ stripped=stripped..sub(dump,dirty,offset-1)
+ for n=1,count do
+ local proto,off=strip_function(sub(dump,offset,-1))
+ stripped,offset=stripped..proto,offset+off-1
+ end
+ offset=offset+subint(dump,offset,int)*int+int
+ count,offset=subint(dump,offset,int)
+ for n=1,count do
+ offset=offset+subint(dump,offset,size)+size+int*2
+ end
+ count,offset=subint(dump,offset,int)
+ for n=1,count do
+ offset=offset+subint(dump,offset,size)+size
+ end
+ stripped=stripped..rep("\0",int*3)
+ return stripped,offset
+ end
+ dump=sub(dump,1,12)..strip_function(sub(dump,13,-1))
+ local after=#dump
+ local delta=register(name,before,after)
+ return dump,delta
+ end
+ else
+ strip_code_pc=function(dump,name)
+ return dump,0
+ end
+ end
+ function luautilities.loadedluacode(fullname,forcestrip,name)
+ local code=environment.loadpreprocessedfile and environment.preprocessedloadfile(fullname) or loadfile(fullname)
+ if code then
+ code()
+ end
+ if forcestrip and luautilities.stripcode then
+ if type(forcestrip)=="function" then
+ forcestrip=forcestrip(fullname)
+ end
+ if forcestrip then
+ local code,n=strip_code_pc(dump(code),name)
+ return load(code),n
+ elseif luautilities.alwaysstripcode then
+ return load(strip_code_pc(dump(code),name))
+ else
+ return code,0
+ end
+ elseif luautilities.alwaysstripcode then
+ return load(strip_code_pc(dump(code),name))
+ else
+ return code,0
+ end
+ end
+ function luautilities.strippedloadstring(code,forcestrip,name)
+ local n=0
+ if (forcestrip and luautilities.stripcode) or luautilities.alwaysstripcode then
+ code=load(code)
+ if not code then
+ report_lua("fatal error in file %a",name)
+ end
+ code,n=strip_code_pc(dump(code),name)
+ end
+ return load(code),n
+ end
+ local function stupidcompile(luafile,lucfile,strip)
+ local code=io.loaddata(luafile)
+ local n=0
+ if code and code~="" then
+ code=load(code)
+ if not code then
+ report_lua("fatal error in file %a",luafile)
+ end
+ code=dump(code)
+ if strip then
+ code,n=strip_code_pc(code,luautilities.stripcode or luautilities.alwaysstripcode,luafile)
+ end
+ if code and code~="" then
+ io.savedata(lucfile,code)
+ end
+ end
+ return n
+ end
+ local luac_normal="texluac -o %q %q"
+ local luac_strip="texluac -s -o %q %q"
+ function luautilities.compile(luafile,lucfile,cleanup,strip,fallback)
+ report_lua("compiling %a into %a",luafile,lucfile)
+ os.remove(lucfile)
+ local done=false
+ if strip~=false then
+ strip=true
+ end
+ if forcestupidcompile then
+ fallback=true
+ elseif strip then
+ done=os.spawn(format(luac_strip,lucfile,luafile))==0
+ else
+ done=os.spawn(format(luac_normal,lucfile,luafile))==0
+ end
+ if not done and fallback then
+ local n=stupidcompile(luafile,lucfile,strip)
+ if n>0 then
+ report_lua("%a dumped into %a (%i bytes stripped)",luafile,lucfile,n)
+ else
+ report_lua("%a dumped into %a (unstripped)",luafile,lucfile)
+ end
+ cleanup=false
+ done=true
+ end
+ if done and cleanup==true and lfs.isfile(lucfile) and lfs.isfile(luafile) then
+ report_lua("removing %a",luafile)
+ os.remove(luafile)
+ end
+ return done
+ end
+ luautilities.loadstripped=loadstring
end
-function file.is_rootbased_path(filename)
- return lpegmatch(rootbased,filename) ~= nil
-end
--- actually these are schemes
+end -- of closure
-local slash = S("\\/")
-local period = P(".")
-local drive = C(R("az","AZ")) * P(":")
-local path = C(((1-slash)^0 * slash)^0)
-local suffix = period * C(P(1-period)^0 * P(-1))
-local base = C((1-suffix)^0)
+do -- create closure to overcome 200 locals limit
-drive = drive + Cc("")
-path = path + Cc("")
-base = base + Cc("")
-suffix = suffix + Cc("")
+package.loaded["util-deb"] = package.loaded["util-deb"] or true
-local pattern_a = drive * path * base * suffix
-local pattern_b = path * base * suffix
-local pattern_c = C(drive * path) * C(base * suffix)
+-- original size: 3708, stripped down to: 2568
-function file.splitname(str,splitdrive)
- if splitdrive then
- return lpegmatch(pattern_a,str) -- returns drive, path, base, suffix
+if not modules then modules={} end modules ['util-deb']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local debug=require "debug"
+local getinfo=debug.getinfo
+local type,next,tostring=type,next,tostring
+local format,find=string.format,string.find
+local is_boolean=string.is_boolean
+utilities=utilities or {}
+local debugger=utilities.debugger or {}
+utilities.debugger=debugger
+local counters={}
+local names={}
+local report=logs.reporter("debugger")
+local function hook()
+ local f=getinfo(2)
+ if f then
+ local n="unknown"
+ if f.what=="C" then
+ n=f.name or ''
+ if not names[n] then
+ names[n]=format("%42s",n)
+ end
else
- return lpegmatch(pattern_b,str) -- returns path, base, suffix
- end
+ n=f.name or f.namewhat or f.what
+ if not n or n=="" then
+ n="?"
+ end
+ if not names[n] then
+ names[n]=format("%42s : % 5i : %s",n,f.linedefined or 0,f.short_src or "unknown source")
+ end
+ end
+ counters[n]=(counters[n] or 0)+1
+ end
+end
+function debugger.showstats(printer,threshold)
+ printer=printer or report
+ threshold=threshold or 0
+ local total,grandtotal,functions=0,0,0
+ local dataset={}
+ for name,count in next,counters do
+ dataset[#dataset+1]={ name,count }
+ end
+ table.sort(dataset,function(a,b) return a[2]==b[2] and b[1]>a[1] or a[2]>b[2] end)
+ for i=1,#dataset do
+ local d=dataset[i]
+ local name=d[1]
+ local count=d[2]
+ if count>threshold and not find(name,"for generator") then
+ printer(format("%8i %s\n",count,names[name]))
+ total=total+count
+ end
+ grandtotal=grandtotal+count
+ functions=functions+1
+ end
+ printer("\n")
+ printer(format("functions : % 10i\n",functions))
+ printer(format("total : % 10i\n",total))
+ printer(format("grand total: % 10i\n",grandtotal))
+ printer(format("threshold : % 10i\n",threshold))
end
-
-function file.nametotable(str,splitdrive) -- returns table
- local path, drive, subpath, name, base, suffix = lpegmatch(pattern_c,str)
- if splitdrive then
- return {
- path = path,
- drive = drive,
- subpath = subpath,
- name = name,
- base = base,
- suffix = suffix,
- }
+function debugger.savestats(filename,threshold)
+ local f=io.open(filename,'w')
+ if f then
+ debugger.showstats(function(str) f:write(str) end,threshold)
+ f:close()
+ end
+end
+function debugger.enable()
+ debug.sethook(hook,"c")
+end
+function debugger.disable()
+ debug.sethook()
+end
+function traceback()
+ local level=1
+ while true do
+ local info=debug.getinfo(level,"Sl")
+ if not info then
+ break
+ elseif info.what=="C" then
+ print(format("%3i : C function",level))
else
- return {
- path = path,
- name = name,
- base = base,
- suffix = suffix,
- }
+ print(format("%3i : [%s]:%d",level,info.short_src,info.currentline))
end
-end
-
--- function test(t) for k, v in next, t do print(v, "=>", file.splitname(v)) end end
---
--- test { "c:", "c:/aa", "c:/aa/bb", "c:/aa/bb/cc", "c:/aa/bb/cc.dd", "c:/aa/bb/cc.dd.ee" }
--- test { "c:", "c:aa", "c:aa/bb", "c:aa/bb/cc", "c:aa/bb/cc.dd", "c:aa/bb/cc.dd.ee" }
--- test { "/aa", "/aa/bb", "/aa/bb/cc", "/aa/bb/cc.dd", "/aa/bb/cc.dd.ee" }
--- test { "aa", "aa/bb", "aa/bb/cc", "aa/bb/cc.dd", "aa/bb/cc.dd.ee" }
-
-
--- for myself:
-
-function file.strip(name,dir)
- local b, a = match(name,"^(.-)" .. dir .. "(.*)$")
- return a ~= "" and a or name
+ level=level+1
+ end
end
@@ -3060,64 +7388,292 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-md5'] = {
- version = 1.001,
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
+package.loaded["util-mrg"] = package.loaded["util-mrg"] or true
+
+-- original size: 7294, stripped down to: 5798
+
+if not modules then modules={} end modules ['util-mrg']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
}
+local gsub,format=string.gsub,string.format
+local concat=table.concat
+local type,next=type,next
+local P,R,S,V,Ct,C,Cs,Cc,Cp,Cmt,Cb,Cg=lpeg.P,lpeg.R,lpeg.S,lpeg.V,lpeg.Ct,lpeg.C,lpeg.Cs,lpeg.Cc,lpeg.Cp,lpeg.Cmt,lpeg.Cb,lpeg.Cg
+local lpegmatch,patterns=lpeg.match,lpeg.patterns
+utilities=utilities or {}
+local merger=utilities.merger or {}
+utilities.merger=merger
+merger.strip_comment=true
+local report=logs.reporter("system","merge")
+utilities.report=report
+local m_begin_merge="begin library merge"
+local m_end_merge="end library merge"
+local m_begin_closure="do -- create closure to overcome 200 locals limit"
+local m_end_closure="end -- of closure"
+local m_pattern="%c+".."%-%-%s+"..m_begin_merge.."%c+(.-)%c+".."%-%-%s+"..m_end_merge.."%c+"
+local m_format="\n\n-- "..m_begin_merge.."\n%s\n".."-- "..m_end_merge.."\n\n"
+local m_faked="-- ".."created merged file".."\n\n".."-- "..m_begin_merge.."\n\n".."-- "..m_end_merge.."\n\n"
+local m_report=[[
+-- used libraries : %s
+-- skipped libraries : %s
+-- original bytes : %s
+-- stripped bytes : %s
+]]
+local m_preloaded=[[package.loaded[%q] = package.loaded[%q] or true]]
+local function self_fake()
+ return m_faked
+end
+local function self_nothing()
+ return ""
+end
+local function self_load(name)
+ local data=io.loaddata(name) or ""
+ if data=="" then
+ report("unknown file %a",name)
+ else
+ report("inserting file %a",name)
+ end
+ return data or ""
+end
+local space=patterns.space
+local eol=patterns.newline
+local equals=P("=")^0
+local open=P("[")*Cg(equals,"init")*P("[")*P("\n")^-1
+local close=P("]")*C(equals)*P("]")
+local closeeq=Cmt(close*Cb("init"),function(s,i,a,b) return a==b end)
+local longstring=open*(1-closeeq)^0*close
+local quoted=patterns.quoted
+local emptyline=space^0*eol
+local operator1=P("<=")+P(">=")+P("~=")+P("..")+S("/^<>=*+%%")
+local operator2=S("*+/")
+local operator3=S("-")
+local separator=S(",;")
+local ignore=(P("]")*space^1*P("=")*space^1*P("]"))/"]=["+(P("=")*space^1*P("{"))/"={"+(P("(")*space^1)/"("+(P("{")*(space+eol)^1*P("}"))/"{}"
+local strings=quoted
+local longcmt=(emptyline^0*P("--")*longstring*emptyline^0)/""
+local longstr=longstring
+local comment=emptyline^0*P("--")*P("-")^0*(1-eol)^0*emptyline^1/"\n"
+local pack=((eol+space)^0/"")*operator1*((eol+space)^0/"")+((eol+space)^0/"")*operator2*((space)^0/"")+((eol+space)^1/"")*operator3*((space)^1/"")+((space)^0/"")*separator*((space)^0/"")
+local lines=emptyline^2/"\n"
+local spaces=(space*space)/" "
+local compact=Cs ((
+ ignore+strings+longcmt+longstr+comment+pack+lines+spaces+1
+)^1 )
+local strip=Cs((emptyline^2/"\n"+1)^0)
+local stripreturn=Cs((1-P("return")*space^1*P(1-space-eol)^1*(space+eol)^0*P(-1))^1)
+function merger.compact(data)
+ return lpegmatch(strip,lpegmatch(compact,data))
+end
+local function self_compact(data)
+ local delta=0
+ if merger.strip_comment then
+ local before=#data
+ data=lpegmatch(compact,data)
+ data=lpegmatch(strip,data)
+ local after=#data
+ delta=before-after
+ report("original size %s, compacted to %s, stripped %s",before,after,delta)
+ data=format("-- original size: %s, stripped down to: %s\n\n%s",before,after,data)
+ end
+ return lpegmatch(stripreturn,data) or data,delta
+end
+local function self_save(name,data)
+ if data~="" then
+ io.savedata(name,data)
+ report("saving %s with size %s",name,#data)
+ end
+end
+local function self_swap(data,code)
+ return data~="" and (gsub(data,m_pattern,function() return format(m_format,code) end,1)) or ""
+end
+local function self_libs(libs,list)
+ local result,f,frozen,foundpath={},nil,false,nil
+ result[#result+1]="\n"
+ if type(libs)=='string' then libs={ libs } end
+ if type(list)=='string' then list={ list } end
+ for i=1,#libs do
+ local lib=libs[i]
+ for j=1,#list do
+ local pth=gsub(list[j],"\\","/")
+ report("checking library path %a",pth)
+ local name=pth.."/"..lib
+ if lfs.isfile(name) then
+ foundpath=pth
+ end
+ end
+ if foundpath then break end
+ end
+ if foundpath then
+ report("using library path %a",foundpath)
+ local right,wrong,original,stripped={},{},0,0
+ for i=1,#libs do
+ local lib=libs[i]
+ local fullname=foundpath.."/"..lib
+ if lfs.isfile(fullname) then
+ report("using library %a",fullname)
+ local preloaded=file.nameonly(lib)
+ local data=io.loaddata(fullname,true)
+ original=original+#data
+ local data,delta=self_compact(data)
+ right[#right+1]=lib
+ result[#result+1]=m_begin_closure
+ result[#result+1]=format(m_preloaded,preloaded,preloaded)
+ result[#result+1]=data
+ result[#result+1]=m_end_closure
+ stripped=stripped+delta
+ else
+ report("skipping library %a",fullname)
+ wrong[#wrong+1]=lib
+ end
+ end
+ right=#right>0 and concat(right," ") or "-"
+ wrong=#wrong>0 and concat(wrong," ") or "-"
+ report("used libraries: %a",right)
+ report("skipped libraries: %a",wrong)
+ report("original bytes: %a",original)
+ report("stripped bytes: %a",stripped)
+ result[#result+1]=format(m_report,right,wrong,original,stripped)
+ else
+ report("no valid library path found")
+ end
+ return concat(result,"\n\n")
+end
+function merger.selfcreate(libs,list,target)
+ if target then
+ self_save(target,self_swap(self_fake(),self_libs(libs,list)))
+ end
+end
+function merger.selfmerge(name,libs,list,target)
+ self_save(target or name,self_swap(self_load(name),self_libs(libs,list)))
+end
+function merger.selfclean(name)
+ self_save(name,self_swap(self_load(name),self_nothing()))
+end
--- This also provides file checksums and checkers.
-local md5, file = md5, file
-local gsub, format, byte = string.gsub, string.format, string.byte
+end -- of closure
-local function convert(str,fmt)
- return (gsub(md5.sum(str),".",function(chr) return format(fmt,byte(chr)) end))
-end
+do -- create closure to overcome 200 locals limit
-if not md5.HEX then function md5.HEX(str) return convert(str,"%02X") end end
-if not md5.hex then function md5.hex(str) return convert(str,"%02x") end end
-if not md5.dec then function md5.dec(str) return convert(str,"%03i") end end
+package.loaded["util-tpl"] = package.loaded["util-tpl"] or true
+-- original size: 5655, stripped down to: 3242
-function file.needs_updating(oldname,newname,threshold) -- size modification access change
- local oldtime = lfs.attributes(oldname, modification)
- local newtime = lfs.attributes(newname, modification)
- if newtime >= oldtime then
- return false
- elseif oldtime - newtime < (threshold or 1) then
- return false
- else
- return true
+if not modules then modules={} end modules ['util-tpl']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+utilities.templates=utilities.templates or {}
+local templates=utilities.templates
+local trace_template=false trackers.register("templates.trace",function(v) trace_template=v end)
+local report_template=logs.reporter("template")
+local tostring=tostring
+local format,sub=string.format,string.sub
+local P,C,Cs,Carg,lpegmatch=lpeg.P,lpeg.C,lpeg.Cs,lpeg.Carg,lpeg.match
+local replacer
+local function replacekey(k,t,how,recursive)
+ local v=t[k]
+ if not v then
+ if trace_template then
+ report_template("unknown key %a",k)
end
-end
-
-function file.checksum(name)
- if md5 then
- local data = io.loaddata(name)
- if data then
- return md5.HEX(data)
- end
+ return ""
+ else
+ v=tostring(v)
+ if trace_template then
+ report_template("setting key %a to value %a",k,v)
end
- return nil
-end
-
-function file.loadchecksum(name)
- if md5 then
- local data = io.loaddata(name .. ".md5")
- return data and (gsub(data,"%s",""))
+ if recursive then
+ return lpegmatch(replacer,v,1,t,how,recursive)
+ else
+ return v
end
- return nil
+ end
end
-
-function file.savechecksum(name, checksum)
- if not checksum then checksum = file.checksum(name) end
- if checksum then
- io.savedata(name .. ".md5",checksum)
- return checksum
- end
- return nil
+local sqlescape=lpeg.replacer {
+ { "'","''" },
+ { "\\","\\\\" },
+ { "\r\n","\\n" },
+ { "\r","\\n" },
+}
+local sqlquotedescape=lpeg.Cs(lpeg.Cc("'")*sqlescape*lpeg.Cc("'"))
+local escapers={
+ lua=function(s)
+ return sub(format("%q",s),2,-2)
+ end,
+ sql=function(s)
+ return lpegmatch(sqlescape,s)
+ end,
+}
+local quotedescapers={
+ lua=function(s)
+ return format("%q",s)
+ end,
+ sql=function(s)
+ return lpegmatch(sqlquotedescape,s)
+ end,
+}
+lpeg.patterns.sqlescape=sqlescape
+lpeg.patterns.sqlescape=sqlquotedescape
+local luaescaper=escapers.lua
+local quotedluaescaper=quotedescapers.lua
+local function replacekeyunquoted(s,t,how,recurse)
+ local escaper=how and escapers[how] or luaescaper
+ return escaper(replacekey(s,t,how,recurse))
+end
+local function replacekeyquoted(s,t,how,recurse)
+ local escaper=how and quotedescapers[how] or quotedluaescaper
+ return escaper(replacekey(s,t,how,recurse))
+end
+local single=P("%")
+local double=P("%%")
+local lquoted=P("%[")
+local rquoted=P("]%")
+local lquotedq=P("%(")
+local rquotedq=P(")%")
+local escape=double/'%%'
+local nosingle=single/''
+local nodouble=double/''
+local nolquoted=lquoted/''
+local norquoted=rquoted/''
+local nolquotedq=lquotedq/''
+local norquotedq=rquotedq/''
+local key=nosingle*((C((1-nosingle )^1)*Carg(1)*Carg(2)*Carg(3))/replacekey )*nosingle
+local quoted=nolquotedq*((C((1-norquotedq)^1)*Carg(1)*Carg(2)*Carg(3))/replacekeyquoted )*norquotedq
+local unquoted=nolquoted*((C((1-norquoted )^1)*Carg(1)*Carg(2)*Carg(3))/replacekeyunquoted)*norquoted
+local any=P(1)
+ replacer=Cs((unquoted+quoted+escape+key+any)^0)
+local function replace(str,mapping,how,recurse)
+ if mapping and str then
+ return lpegmatch(replacer,str,1,mapping,how or "lua",recurse or false) or str
+ else
+ return str
+ end
+end
+templates.replace=replace
+function templates.load(filename,mapping,how,recurse)
+ local data=io.loaddata(filename) or ""
+ if mapping and next(mapping) then
+ return replace(data,mapping,how,recurse)
+ else
+ return data
+ end
+end
+function templates.resolve(t,mapping,how,recurse)
+ if not mapping then
+ mapping=t
+ end
+ for k,v in next,t do
+ t[k]=replace(v,mapping,how,recurse)
+ end
+ return t
end
@@ -3125,1225 +7681,1316 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-url'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local char, gmatch, gsub, format, byte, find = string.char, string.gmatch, string.gsub, string.format, string.byte, string.find
-local concat = table.concat
-local tonumber, type = tonumber, type
-local P, C, R, S, Cs, Cc, Ct = lpeg.P, lpeg.C, lpeg.R, lpeg.S, lpeg.Cs, lpeg.Cc, lpeg.Ct
-local lpegmatch, lpegpatterns, replacer = lpeg.match, lpeg.patterns, lpeg.replacer
+package.loaded["util-env"] = package.loaded["util-env"] or true
--- from wikipedia:
---
--- foo://username:password@example.com:8042/over/there/index.dtb?type=animal;name=narwhal#nose
--- \_/ \_______________/ \_________/ \__/ \___/ \_/ \______________________/ \__/
--- | | | | | | | |
--- | userinfo hostname port | | query fragment
--- | \________________________________/\_____________|____|/
--- scheme | | | |
--- | authority path | |
--- | | |
--- | path interpretable as filename
--- | ___________|____________ |
--- / \ / \ |
--- urn:example:animal:ferret:nose interpretable as extension
-
-url = url or { }
-local url = url
-
-local tochar = function(s) return char(tonumber(s,16)) end
-
-local colon = P(":")
-local qmark = P("?")
-local hash = P("#")
-local slash = P("/")
-local percent = P("%")
-local endofstring = P(-1)
-
-local hexdigit = R("09","AF","af")
-local plus = P("+")
-local nothing = Cc("")
-local escaped = (plus / " ") + (percent * C(hexdigit * hexdigit) / tochar)
-
--- we assume schemes with more than 1 character (in order to avoid problems with windows disks)
--- we also assume that when we have a scheme, we also have an authority
-
-local schemestr = Cs((escaped+(1-colon-slash-qmark-hash))^2)
-local authoritystr = Cs((escaped+(1- slash-qmark-hash))^0)
-local pathstr = Cs((escaped+(1- qmark-hash))^0)
-local querystr = Cs((escaped+(1- hash))^0)
-local fragmentstr = Cs((escaped+(1- endofstring))^0)
-
-local scheme = schemestr * colon + nothing
-local authority = slash * slash * authoritystr + nothing
-local path = slash * pathstr + nothing
-local query = qmark * querystr + nothing
-local fragment = hash * fragmentstr + nothing
-
-local validurl = scheme * authority * path * query * fragment
-local parser = Ct(validurl)
-
-lpegpatterns.url = validurl
-lpegpatterns.urlsplitter = parser
-
-local escapes = { } ; for i=0,255 do escapes[i] = format("%%%02X",i) end
-
-local escaper = Cs((R("09","AZ","az") + S("-./_") + P(1) / escapes)^0)
-
-lpegpatterns.urlescaper = escaper
-
--- todo: reconsider Ct as we can as well have five return values (saves a table)
--- so we can have two parsers, one with and one without
+-- original size: 7702, stripped down to: 4701
-local function split(str)
- return (type(str) == "string" and lpegmatch(parser,str)) or str
+if not modules then modules={} end modules ['util-env']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local allocate,mark=utilities.storage.allocate,utilities.storage.mark
+local format,sub,match,gsub,find=string.format,string.sub,string.match,string.gsub,string.find
+local unquoted,quoted=string.unquoted,string.quoted
+local concat,insert,remove=table.concat,table.insert,table.remove
+environment=environment or {}
+local environment=environment
+os.setlocale(nil,nil)
+function os.setlocale()
end
-
-local isscheme = schemestr * colon * slash * slash -- this test also assumes authority
-
-local function hasscheme(str)
- local scheme = lpegmatch(isscheme,str) -- at least one character
- return scheme ~= "" and scheme or false
-end
-
-
--- todo: cache them
-
-local rootletter = R("az","AZ")
- + S("_-+")
-local separator = P("://")
-local qualified = P(".")^0 * P("/")
- + rootletter * P(":")
- + rootletter^1 * separator
- + rootletter^1 * P("/")
-local rootbased = P("/")
- + rootletter * P(":")
-
-local barswapper = replacer("|",":")
-local backslashswapper = replacer("\\","/")
-
-local function hashed(str) -- not yet ok (/test?test)
- local s = split(str)
- local somescheme = s[1] ~= ""
- local somequery = s[4] ~= ""
- if not somescheme and not somequery then
- s = {
- scheme = "file",
- authority = "",
- path = str,
- query = "",
- fragment = "",
- original = str,
- noscheme = true,
- filename = str,
- }
- else -- not always a filename but handy anyway
- local authority, path, filename = s[2], s[3]
- if authority == "" then
- filename = path
+local validengines=allocate {
+ ["luatex"]=true,
+ ["luajittex"]=true,
+}
+local basicengines=allocate {
+ ["luatex"]="luatex",
+ ["texlua"]="luatex",
+ ["texluac"]="luatex",
+ ["luajittex"]="luajittex",
+ ["texluajit"]="luajittex",
+}
+local luaengines=allocate {
+ ["lua"]=true,
+ ["luajit"]=true,
+}
+environment.validengines=validengines
+environment.basicengines=basicengines
+if not arg then
+elseif luaengines[file.removesuffix(arg[-1])] then
+elseif validengines[file.removesuffix(arg[0])] then
+ if arg[1]=="--luaonly" then
+ arg[-1]=arg[0]
+ arg[ 0]=arg[2]
+ for k=3,#arg do
+ arg[k-2]=arg[k]
+ end
+ remove(arg)
+ remove(arg)
+ else
+ end
+ local originalzero=file.basename(arg[0])
+ local specialmapping={ luatools=="base" }
+ if originalzero~="mtxrun" and originalzero~="mtxrun.lua" then
+ arg[0]=specialmapping[originalzero] or originalzero
+ insert(arg,0,"--script")
+ insert(arg,0,"mtxrun")
+ end
+end
+environment.arguments=allocate()
+environment.files=allocate()
+environment.sortedflags=nil
+function environment.initializearguments(arg)
+ local arguments,files={},{}
+ environment.arguments,environment.files,environment.sortedflags=arguments,files,nil
+ for index=1,#arg do
+ local argument=arg[index]
+ if index>0 then
+ local flag,value=match(argument,"^%-+(.-)=(.-)$")
+ if flag then
+ flag=gsub(flag,"^c:","")
+ arguments[flag]=unquoted(value or "")
+ else
+ flag=match(argument,"^%-+(.+)")
+ if flag then
+ flag=gsub(flag,"^c:","")
+ arguments[flag]=true
else
- filename = authority .. "/" .. path
+ files[#files+1]=argument
end
- s = {
- scheme = s[1],
- authority = authority,
- path = path,
- query = s[4],
- fragment = s[5],
- original = str,
- noscheme = false,
- filename = filename,
- }
+ end
end
- return s
+ end
+ environment.ownname=file.reslash(environment.ownname or arg[0] or 'unknown.lua')
end
-
--- Here we assume:
---
--- files: /// = relative
--- files: //// = absolute (!)
-
-
-
-url.split = split
-url.hasscheme = hasscheme
-url.hashed = hashed
-
-function url.addscheme(str,scheme) -- no authority
- if hasscheme(str) then
- return str
- elseif not scheme then
- return "file:///" .. str
+function environment.setargument(name,value)
+ environment.arguments[name]=value
+end
+function environment.getargument(name,partial)
+ local arguments,sortedflags=environment.arguments,environment.sortedflags
+ if arguments[name] then
+ return arguments[name]
+ elseif partial then
+ if not sortedflags then
+ sortedflags=allocate(table.sortedkeys(arguments))
+ for k=1,#sortedflags do
+ sortedflags[k]="^"..sortedflags[k]
+ end
+ environment.sortedflags=sortedflags
+ end
+ for k=1,#sortedflags do
+ local v=sortedflags[k]
+ if find(name,v) then
+ return arguments[sub(v,2,#v)]
+ end
+ end
+ end
+ return nil
+end
+environment.argument=environment.getargument
+function environment.splitarguments(separator)
+ local done,before,after=false,{},{}
+ local originalarguments=environment.originalarguments
+ for k=1,#originalarguments do
+ local v=originalarguments[k]
+ if not done and v==separator then
+ done=true
+ elseif done then
+ after[#after+1]=v
else
- return scheme .. ":///" .. str
- end
-end
-
-function url.construct(hash) -- dodo: we need to escape !
- local fullurl, f = { }, 0
- local scheme, authority, path, query, fragment = hash.scheme, hash.authority, hash.path, hash.query, hash.fragment
- if scheme and scheme ~= "" then
- f = f + 1 ; fullurl[f] = scheme .. "://"
- end
- if authority and authority ~= "" then
- f = f + 1 ; fullurl[f] = authority
- end
- if path and path ~= "" then
- f = f + 1 ; fullurl[f] = "/" .. path
- end
- if query and query ~= "" then
- f = f + 1 ; fullurl[f] = "?".. query
+ before[#before+1]=v
end
- if fragment and fragment ~= "" then
- f = f + 1 ; fullurl[f] = "#".. fragment
- end
- return lpegmatch(escaper,concat(fullurl))
+ end
+ return before,after
end
-
-function url.filename(filename)
- local t = hashed(filename)
- return (t.scheme == "file" and (gsub(t.path,"^/([a-zA-Z])([:|])/)","%1:"))) or filename
+function environment.reconstructcommandline(arg,noquote)
+ arg=arg or environment.originalarguments
+ if noquote and #arg==1 then
+ local a=arg[1]
+ a=resolvers.resolve(a)
+ a=unquoted(a)
+ return a
+ elseif #arg>0 then
+ local result={}
+ for i=1,#arg do
+ local a=arg[i]
+ a=resolvers.resolve(a)
+ a=unquoted(a)
+ a=gsub(a,'"','\\"')
+ if find(a," ") then
+ result[#result+1]=quoted(a)
+ else
+ result[#result+1]=a
+ end
+ end
+ return concat(result," ")
+ else
+ return ""
+ end
end
-
-function url.query(str)
- if type(str) == "string" then
- local t = { }
- for k, v in gmatch(str,"([^&=]*)=([^&=]*)") do
- t[k] = v
- end
- return t
+if arg then
+ local newarg,instring={},false
+ for index=1,#arg do
+ local argument=arg[index]
+ if find(argument,"^\"") then
+ newarg[#newarg+1]=gsub(argument,"^\"","")
+ if not find(argument,"\"$") then
+ instring=true
+ end
+ elseif find(argument,"\"$") then
+ newarg[#newarg]=newarg[#newarg].." "..gsub(argument,"\"$","")
+ instring=false
+ elseif instring then
+ newarg[#newarg]=newarg[#newarg].." "..argument
else
- return str
+ newarg[#newarg+1]=argument
end
+ end
+ for i=1,-5,-1 do
+ newarg[i]=arg[i]
+ end
+ environment.initializearguments(newarg)
+ environment.originalarguments=mark(newarg)
+ environment.rawarguments=mark(arg)
+ arg={}
end
-
-
-
-
-
-
-
-
end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-dir'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- dir.expandname will be merged with cleanpath and collapsepath
-
-local type = type
-local find, gmatch, match, gsub = string.find, string.gmatch, string.match, string.gsub
-local concat, insert, remove = table.concat, table.insert, table.remove
-local lpegmatch = lpeg.match
-
-local P, S, R, C, Cc, Cs, Ct, Cv, V = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.Cc, lpeg.Cs, lpeg.Ct, lpeg.Cv, lpeg.V
+package.loaded["luat-env"] = package.loaded["luat-env"] or true
-dir = dir or { }
-local dir = dir
-local lfs = lfs
+-- original size: 5874, stripped down to: 4184
-local attributes = lfs.attributes
-local walkdir = lfs.dir
-local isdir = lfs.isdir
-local isfile = lfs.isfile
-local currentdir = lfs.currentdir
-
--- handy
-
-function dir.current()
- return (gsub(currentdir(),"\\","/"))
-end
-
--- optimizing for no find (*) does not save time
-
-
-local lfsisdir = isdir
-
-local function isdir(path)
- path = gsub(path,"[/\\]+$","")
- return lfsisdir(path)
+ if not modules then modules={} end modules ['luat-env']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local rawset,rawget,loadfile,assert=rawset,rawget,loadfile,assert
+local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end)
+local report_lua=logs.reporter("resolvers","lua")
+local luautilities=utilities.lua
+local luasuffixes=luautilities.suffixes
+environment=environment or {}
+local environment=environment
+local mt={
+ __index=function(_,k)
+ if k=="version" then
+ local version=tex.toks and tex.toks.contextversiontoks
+ if version and version~="" then
+ rawset(environment,"version",version)
+ return version
+ else
+ return "unknown"
+ end
+ elseif k=="kind" then
+ local kind=tex.toks and tex.toks.contextkindtoks
+ if kind and kind~="" then
+ rawset(environment,"kind",kind)
+ return kind
+ else
+ return "unknown"
+ end
+ elseif k=="jobname" or k=="formatname" then
+ local name=tex and tex[k]
+ if name or name=="" then
+ rawset(environment,k,name)
+ return name
+ else
+ return "unknown"
+ end
+ elseif k=="outputfilename" then
+ local name=environment.jobname
+ rawset(environment,k,name)
+ return name
+ end
+ end
+}
+setmetatable(environment,mt)
+function environment.texfile(filename)
+ return resolvers.findfile(filename,'tex')
+end
+function environment.luafile(filename)
+ local resolved=resolvers.findfile(filename,'tex') or ""
+ if resolved~="" then
+ return resolved
+ end
+ resolved=resolvers.findfile(filename,'texmfscripts') or ""
+ if resolved~="" then
+ return resolved
+ end
+ return resolvers.findfile(filename,'luatexlibs') or ""
+end
+local stripindeed=false directives.register("system.compile.strip",function(v) stripindeed=v end)
+local function strippable(filename)
+ if stripindeed then
+ local modu=modules[file.nameonly(filename)]
+ return modu and modu.dataonly
+ else
+ return false
+ end
end
-
-lfs.isdir = isdir
-
-local function globpattern(path,patt,recurse,action)
- if path == "/" then
- path = path .. "."
- elseif not find(path,"/$") then
- path = path .. '/'
- end
- if isdir(path) then -- lfs.isdir does not like trailing /
- for name in walkdir(path) do -- lfs.dir accepts trailing /
- local full = path .. name
- local mode = attributes(full,'mode')
- if mode == 'file' then
- if find(full,patt) then
- action(full)
- end
- elseif recurse and (mode == "directory") and (name ~= '.') and (name ~= "..") then
- globpattern(full,patt,recurse,action)
- end
- end
+function environment.luafilechunk(filename,silent)
+ filename=file.replacesuffix(filename,"lua")
+ local fullname=environment.luafile(filename)
+ if fullname and fullname~="" then
+ local data=luautilities.loadedluacode(fullname,strippable,filename)
+ if trace_locating then
+ report_lua("loading file %a %s",fullname,not data and "failed" or "succeeded")
+ elseif not silent then
+ texio.write("<",data and "+ " or "- ",fullname,">")
end
-end
-
-dir.globpattern = globpattern
-
-local function collectpattern(path,patt,recurse,result)
- local ok, scanner
- result = result or { }
- if path == "/" then
- ok, scanner, first = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe
- else
- ok, scanner, first = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
- end
- if ok and type(scanner) == "function" then
- if not find(path,"/$") then path = path .. '/' end
- for name in scanner, first do
- local full = path .. name
- local attr = attributes(full)
- local mode = attr.mode
- if mode == 'file' then
- if find(full,patt) then
- result[name] = attr
- end
- elseif recurse and (mode == "directory") and (name ~= '.') and (name ~= "..") then
- attr.list = collectpattern(full,patt,recurse)
- result[name] = attr
- end
- end
+ return data
+ else
+ if trace_locating then
+ report_lua("unknown file %a",filename)
end
- return result
-end
-
-dir.collectpattern = collectpattern
-
-local pattern = Ct {
- [1] = (C(P(".") + P("/")^1) + C(R("az","AZ") * P(":") * P("/")^0) + Cc("./")) * V(2) * V(3),
- [2] = C(((1-S("*?/"))^0 * P("/"))^0),
- [3] = C(P(1)^0)
-}
-
-local filter = Cs ( (
- P("**") / ".*" +
- P("*") / "[^/]*" +
- P("?") / "[^/]" +
- P(".") / "%%." +
- P("+") / "%%+" +
- P("-") / "%%-" +
- P(1)
-)^0 )
-
-local function glob(str,t)
- if type(t) == "function" then
- if type(str) == "table" then
- for s=1,#str do
- glob(str[s],t)
- end
- elseif isfile(str) then
- t(str)
- else
- local split = lpegmatch(pattern,str) -- we could use the file splitter
- if split then
- local root, path, base = split[1], split[2], split[3]
- local recurse = find(base,"%*%*")
- local start = root .. path
- local result = lpegmatch(filter,start .. base)
- globpattern(start,result,recurse,t)
- end
+ return nil
+ end
+end
+function environment.loadluafile(filename,version)
+ local lucname,luaname,chunk
+ local basename=file.removesuffix(filename)
+ if basename==filename then
+ luaname=file.addsuffix(basename,luasuffixes.lua)
+ lucname=file.addsuffix(basename,luasuffixes.luc)
+ else
+ luaname=basename
+ lucname=nil
+ end
+ local fullname=(lucname and environment.luafile(lucname)) or ""
+ if fullname~="" then
+ if trace_locating then
+ report_lua("loading %a",fullname)
+ end
+ chunk=loadfile(fullname)
+ end
+ if chunk then
+ assert(chunk)()
+ if version then
+ local v=version
+ if modules and modules[filename] then
+ v=modules[filename].version
+ elseif versions and versions[filename] then
+ v=versions[filename]
+ end
+ if v==version then
+ return true
+ else
+ if trace_locating then
+ report_lua("version mismatch for %a, lua version %a, luc version %a",filename,v,version)
end
+ environment.loadluafile(filename)
+ end
else
- if type(str) == "table" then
- local t = t or { }
- for s=1,#str do
- glob(str[s],t)
- end
- return t
- elseif isfile(str) then
- if t then
- t[#t+1] = str
- return t
- else
- return { str }
- end
- else
- local split = lpegmatch(pattern,str) -- we could use the file splitter
- if split then
- local t = t or { }
- local action = action or function(name) t[#t+1] = name end
- local root, path, base = split[1], split[2], split[3]
- local recurse = find(base,"%*%*")
- local start = root .. path
- local result = lpegmatch(filter,start .. base)
- globpattern(start,result,recurse,action)
- return t
- else
- return { }
- end
- end
+ return true
end
-end
-
-dir.glob = glob
-
-
-local function globfiles(path,recurse,func,files) -- func == pattern or function
- if type(func) == "string" then
- local s = func
- func = function(name) return find(name,s) end
+ end
+ fullname=(luaname and environment.luafile(luaname)) or ""
+ if fullname~="" then
+ if trace_locating then
+ report_lua("loading %a",fullname)
end
- files = files or { }
- local noffiles = #files
- for name in walkdir(path) do
- if find(name,"^%.") then
- --- skip
- else
- local mode = attributes(name,'mode')
- if mode == "directory" then
- if recurse then
- globfiles(path .. "/" .. name,recurse,func,files)
- end
- elseif mode == "file" then
- if not func or func(name) then
- noffiles = noffiles + 1
- files[noffiles] = path .. "/" .. name
- end
- end
- end
+ chunk=loadfile(fullname)
+ if not chunk then
+ if trace_locating then
+ report_lua("unknown file %a",filename)
+ end
+ else
+ assert(chunk)()
+ return true
end
- return files
+ end
+ return false
end
-dir.globfiles = globfiles
-
--- t = dir.glob("c:/data/develop/context/sources/**/????-*.tex")
--- t = dir.glob("c:/data/develop/tex/texmf/**/*.tex")
--- t = dir.glob("c:/data/develop/context/texmf/**/*.tex")
--- t = dir.glob("f:/minimal/tex/**/*")
--- print(dir.ls("f:/minimal/tex/**/*"))
--- print(dir.ls("*.tex"))
-
-function dir.ls(pattern)
- return concat(glob(pattern),"\n")
-end
+end -- of closure
-local make_indeed = true -- false
+do -- create closure to overcome 200 locals limit
-local onwindows = os.type == "windows" or find(os.getenv("PATH"),";")
+package.loaded["lxml-tab"] = package.loaded["lxml-tab"] or true
-if onwindows then
+-- original size: 42495, stripped down to: 26647
- function dir.mkdirs(...)
- local str, pth, t = "", "", { ... }
- for i=1,#t do
- local s = t[i]
- if s ~= "" then
- if str ~= "" then
- str = str .. "/" .. s
- else
- str = s
- end
- end
- end
- local first, middle, last
- local drive = false
- first, middle, last = match(str,"^(//)(//*)(.*)$")
- if first then
- -- empty network path == local path
- else
- first, last = match(str,"^(//)/*(.-)$")
- if first then
- middle, last = match(str,"([^/]+)/+(.-)$")
- if middle then
- pth = "//" .. middle
- else
- pth = "//" .. last
- last = ""
- end
- else
- first, middle, last = match(str,"^([a-zA-Z]:)(/*)(.-)$")
- if first then
- pth, drive = first .. middle, true
- else
- middle, last = match(str,"^(/*)(.-)$")
- if not middle then
- last = str
- end
- end
- end
- end
- for s in gmatch(last,"[^/]+") do
- if pth == "" then
- pth = s
- elseif drive then
- pth, drive = pth .. s, false
- else
- pth = pth .. "/" .. s
- end
- if make_indeed and not isdir(pth) then
- lfs.mkdir(pth)
- end
- end
- return pth, (isdir(pth) == true)
- end
-
-
-else
-
- function dir.mkdirs(...)
- local str, pth, t = "", "", { ... }
- for i=1,#t do
- local s = t[i]
- if s and s ~= "" then -- we catch nil and false
- if str ~= "" then
- str = str .. "/" .. s
- else
- str = s
- end
- end
- end
- str = gsub(str,"/+","/")
- if find(str,"^/") then
- pth = "/"
- for s in gmatch(str,"[^/]+") do
- local first = (pth == "/")
- if first then
- pth = pth .. s
- else
- pth = pth .. "/" .. s
- end
- if make_indeed and not first and not isdir(pth) then
- lfs.mkdir(pth)
- end
- end
- else
- pth = "."
- for s in gmatch(str,"[^/]+") do
- pth = pth .. "/" .. s
- if make_indeed and not isdir(pth) then
- lfs.mkdir(pth)
- end
- end
- end
- return pth, (isdir(pth) == true)
- end
-
-
+if not modules then modules={} end modules ['lxml-tab']={
+ version=1.001,
+ comment="this module is the basis for the lxml-* ones",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local trace_entities=false trackers.register("xml.entities",function(v) trace_entities=v end)
+local report_xml=logs and logs.reporter("xml","core") or function(...) print(string.format(...)) end
+xml=xml or {}
+local xml=xml
+local concat,remove,insert=table.concat,table.remove,table.insert
+local type,next,setmetatable,getmetatable,tonumber=type,next,setmetatable,getmetatable,tonumber
+local lower,find,match,gsub=string.lower,string.find,string.match,string.gsub
+local utfchar=utf.char
+local lpegmatch=lpeg.match
+local P,S,R,C,V,C,Cs=lpeg.P,lpeg.S,lpeg.R,lpeg.C,lpeg.V,lpeg.C,lpeg.Cs
+local formatters=string.formatters
+xml.xmlns=xml.xmlns or {}
+local check=P(false)
+local parse=check
+function xml.registerns(namespace,pattern)
+ check=check+C(P(lower(pattern)))/namespace
+ parse=P { P(check)+1*V(1) }
end
-
-dir.makedirs = dir.mkdirs
-
--- we can only define it here as it uses dir.current
-
-if onwindows then
-
- function dir.expandname(str) -- will be merged with cleanpath and collapsepath
- local first, nothing, last = match(str,"^(//)(//*)(.*)$")
- if first then
- first = dir.current() .. "/"
- end
- if not first then
- first, last = match(str,"^(//)/*(.*)$")
- end
- if not first then
- first, last = match(str,"^([a-zA-Z]:)(.*)$")
- if first and not find(last,"^/") then
- local d = currentdir()
- if lfs.chdir(first) then
- first = dir.current()
- end
- lfs.chdir(d)
- end
- end
- if not first then
- first, last = dir.current(), str
- end
- last = gsub(last,"//","/")
- last = gsub(last,"/%./","/")
- last = gsub(last,"^/*","")
- first = gsub(first,"/*$","")
- if last == "" or last == "." then
- return first
- else
- return first .. "/" .. last
- end
- end
-
-else
-
- function dir.expandname(str) -- will be merged with cleanpath and collapsepath
- if not find(str,"^/") then
- str = currentdir() .. "/" .. str
- end
- str = gsub(str,"//","/")
- str = gsub(str,"/%./","/")
- str = gsub(str,"(.)/%.$","%1")
- return str
- end
-
+function xml.checkns(namespace,url)
+ local ns=lpegmatch(parse,lower(url))
+ if ns and namespace~=ns then
+ xml.xmlns[namespace]=ns
+ end
end
-
-file.expandname = dir.expandname -- for convenience
-
-local stack = { }
-
-function dir.push(newdir)
- insert(stack,lfs.currentdir())
+function xml.resolvens(url)
+ return lpegmatch(parse,lower(url)) or ""
+end
+local nsremap,resolvens=xml.xmlns,xml.resolvens
+local stack={}
+local top={}
+local dt={}
+local at={}
+local xmlns={}
+local errorstr=nil
+local entities={}
+local strip=false
+local cleanup=false
+local utfize=false
+local resolve_predefined=false
+local unify_predefined=false
+local dcache={}
+local hcache={}
+local acache={}
+local mt={}
+local function initialize_mt(root)
+ mt={ __index=root }
end
-
-function dir.pop()
- local d = remove(stack)
- if d then
- lfs.chdir(d)
- end
- return d
+function xml.setproperty(root,k,v)
+ getmetatable(root).__index[k]=v
end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['l-boolean'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
+function xml.checkerror(top,toclose)
+ return ""
+end
+local function add_attribute(namespace,tag,value)
+ if cleanup and #value>0 then
+ value=cleanup(value)
+ end
+ if tag=="xmlns" then
+ xmlns[#xmlns+1]=resolvens(value)
+ at[tag]=value
+ elseif namespace=="" then
+ at[tag]=value
+ elseif namespace=="xmlns" then
+ xml.checkns(tag,value)
+ at["xmlns:"..tag]=value
+ else
+ at[namespace..":"..tag]=value
+ end
+end
+local function add_empty(spacing,namespace,tag)
+ if #spacing>0 then
+ dt[#dt+1]=spacing
+ end
+ local resolved=namespace=="" and xmlns[#xmlns] or nsremap[namespace] or namespace
+ top=stack[#stack]
+ dt=top.dt
+ local t={ ns=namespace or "",rn=resolved,tg=tag,at=at,dt={},__p__=top }
+ dt[#dt+1]=t
+ setmetatable(t,mt)
+ if at.xmlns then
+ remove(xmlns)
+ end
+ at={}
+end
+local function add_begin(spacing,namespace,tag)
+ if #spacing>0 then
+ dt[#dt+1]=spacing
+ end
+ local resolved=namespace=="" and xmlns[#xmlns] or nsremap[namespace] or namespace
+ top={ ns=namespace or "",rn=resolved,tg=tag,at=at,dt={},__p__=stack[#stack] }
+ setmetatable(top,mt)
+ dt=top.dt
+ stack[#stack+1]=top
+ at={}
+end
+local function add_end(spacing,namespace,tag)
+ if #spacing>0 then
+ dt[#dt+1]=spacing
+ end
+ local toclose=remove(stack)
+ top=stack[#stack]
+ if #stack<1 then
+ errorstr=formatters["unable to close %s %s"](tag,xml.checkerror(top,toclose) or "")
+ elseif toclose.tg~=tag then
+ errorstr=formatters["unable to close %s with %s %s"](toclose.tg,tag,xml.checkerror(top,toclose) or "")
+ end
+ dt=top.dt
+ dt[#dt+1]=toclose
+ if toclose.at.xmlns then
+ remove(xmlns)
+ end
+end
+local function add_text(text)
+ if cleanup and #text>0 then
+ dt[#dt+1]=cleanup(text)
+ else
+ dt[#dt+1]=text
+ end
+end
+local function add_special(what,spacing,text)
+ if #spacing>0 then
+ dt[#dt+1]=spacing
+ end
+ if strip and (what=="@cm@" or what=="@dt@") then
+ else
+ dt[#dt+1]={ special=true,ns="",tg=what,dt={ text } }
+ end
+end
+local function set_message(txt)
+ errorstr="garbage at the end of the file: "..gsub(txt,"([ \n\r\t]*)","")
+end
+local reported_attribute_errors={}
+local function attribute_value_error(str)
+ if not reported_attribute_errors[str] then
+ report_xml("invalid attribute value %a",str)
+ reported_attribute_errors[str]=true
+ at._error_=str
+ end
+ return str
+end
+local function attribute_specification_error(str)
+ if not reported_attribute_errors[str] then
+ report_xml("invalid attribute specification %a",str)
+ reported_attribute_errors[str]=true
+ at._error_=str
+ end
+ return str
+end
+xml.placeholders={
+ unknown_dec_entity=function(str) return str=="" and "&error;" or formatters["&%s;"](str) end,
+ unknown_hex_entity=function(str) return formatters["%s;"](str) end,
+ unknown_any_entity=function(str) return formatters["%s;"](str) end,
}
-
-local type, tonumber = type, tonumber
-
-boolean = boolean or { }
-local boolean = boolean
-
-function boolean.tonumber(b)
- if b then return 1 else return 0 end -- test and return or return
+local placeholders=xml.placeholders
+local function fromhex(s)
+ local n=tonumber(s,16)
+ if n then
+ return utfchar(n)
+ else
+ return formatters["h:%s"](s),true
+ end
end
-
-function toboolean(str,tolerant)
- if tolerant then
- local tstr = type(str)
- if tstr == "string" then
- return str == "true" or str == "yes" or str == "on" or str == "1" or str == "t"
- elseif tstr == "number" then
- return tonumber(str) ~= 0
- elseif tstr == "nil" then
- return false
- else
- return str
- end
- elseif str == "true" then
- return true
- elseif str == "false" then
- return false
+local function fromdec(s)
+ local n=tonumber(s)
+ if n then
+ return utfchar(n)
+ else
+ return formatters["d:%s"](s),true
+ end
+end
+local rest=(1-P(";"))^0
+local many=P(1)^0
+local parsedentity=P("&")*(P("#x")*(rest/fromhex)+P("#")*(rest/fromdec))*P(";")*P(-1)+(P("#x")*(many/fromhex)+P("#")*(many/fromdec))
+local predefined_unified={
+ [38]="&",
+ [42]=""",
+ [47]="'",
+ [74]="<",
+ [76]=">",
+}
+local predefined_simplified={
+ [38]="&",amp="&",
+ [42]='"',quot='"',
+ [47]="'",apos="'",
+ [74]="<",lt="<",
+ [76]=">",gt=">",
+}
+local nofprivates=0xF0000
+local privates_u={
+ [ [[&]] ]="&",
+ [ [["]] ]=""",
+ [ [[']] ]="'",
+ [ [[<]] ]="<",
+ [ [[>]] ]=">",
+}
+local privates_p={}
+local privates_n={
+}
+local escaped=utf.remapper(privates_u)
+local function unescaped(s)
+ local p=privates_n[s]
+ if not p then
+ nofprivates=nofprivates+1
+ p=utfchar(nofprivates)
+ privates_n[s]=p
+ s="&"..s..";"
+ privates_u[p]=s
+ privates_p[p]=s
+ end
+ return p
+end
+local unprivatized=utf.remapper(privates_p)
+xml.privatetoken=unescaped
+xml.unprivatized=unprivatized
+xml.privatecodes=privates_n
+local function handle_hex_entity(str)
+ local h=hcache[str]
+ if not h then
+ local n=tonumber(str,16)
+ h=unify_predefined and predefined_unified[n]
+ if h then
+ if trace_entities then
+ report_xml("utfize, converting hex entity %s; into %a",str,h)
+ end
+ elseif utfize then
+ h=(n and utfchar(n)) or xml.unknown_hex_entity(str) or ""
+ if not n then
+ report_xml("utfize, ignoring hex entity %s;",str)
+ elseif trace_entities then
+ report_xml("utfize, converting hex entity %s; into %a",str,h)
+ end
else
- return str
+ if trace_entities then
+ report_xml("found entity %s;",str)
+ end
+ h=""..str..";"
end
+ hcache[str]=h
+ end
+ return h
end
-
-string.toboolean = toboolean
-
-function string.is_boolean(str,default)
- if type(str) == "string" then
- if str == "true" or str == "yes" or str == "on" or str == "t" then
- return true
- elseif str == "false" or str == "no" or str == "off" or str == "f" then
- return false
- end
+local function handle_dec_entity(str)
+ local d=dcache[str]
+ if not d then
+ local n=tonumber(str)
+ d=unify_predefined and predefined_unified[n]
+ if d then
+ if trace_entities then
+ report_xml("utfize, converting dec entity %s; into %a",str,d)
+ end
+ elseif utfize then
+ d=(n and utfchar(n)) or placeholders.unknown_dec_entity(str) or ""
+ if not n then
+ report_xml("utfize, ignoring dec entity %s;",str)
+ elseif trace_entities then
+ report_xml("utfize, converting dec entity %s; into %a",str,d)
+ end
+ else
+ if trace_entities then
+ report_xml("found entity %s;",str)
+ end
+ d=""..str..";"
end
- return default
+ dcache[str]=d
+ end
+ return d
end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['l-unicode'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-if not unicode then
-
- unicode = { utf8 = { } }
-
- local floor, char = math.floor, string.char
-
- function unicode.utf8.utfchar(n)
- if n < 0x80 then
- return char(n)
- elseif n < 0x800 then
- return char(
- 0xC0 + floor(n/0x40),
- 0x80 + (n % 0x40)
- )
- elseif n < 0x10000 then
- return char(
- 0xE0 + floor(n/0x1000),
- 0x80 + (floor(n/0x40) % 0x40),
- 0x80 + (n % 0x40)
- )
- elseif n < 0x40000 then
- return char(
- 0xF0 + floor(n/0x40000),
- 0x80 + floor(n/0x1000),
- 0x80 + (floor(n/0x40) % 0x40),
- 0x80 + (n % 0x40)
- )
+xml.parsedentitylpeg=parsedentity
+local function handle_any_entity(str)
+ if resolve then
+ local a=acache[str]
+ if not a then
+ a=resolve_predefined and predefined_simplified[str]
+ if a then
+ if trace_entities then
+ report_xml("resolving entity &%s; to predefined %a",str,a)
+ end
+ else
+ if type(resolve)=="function" then
+ a=resolve(str) or entities[str]
else
- -- return char(
- -- 0xF1 + floor(n/0x1000000),
- -- 0x80 + floor(n/0x40000),
- -- 0x80 + floor(n/0x1000),
- -- 0x80 + (floor(n/0x40) % 0x40),
- -- 0x80 + (n % 0x40)
- -- )
- return "?"
+ a=entities[str]
end
- end
-
+ if a then
+ if type(a)=="function" then
+ if trace_entities then
+ report_xml("expanding entity &%s; to function call",str)
+ end
+ a=a(str) or ""
+ end
+ a=lpegmatch(parsedentity,a) or a
+ if trace_entities then
+ report_xml("resolving entity &%s; to internal %a",str,a)
+ end
+ else
+ local unknown_any_entity=placeholders.unknown_any_entity
+ if unknown_any_entity then
+ a=unknown_any_entity(str) or ""
+ end
+ if a then
+ if trace_entities then
+ report_xml("resolving entity &%s; to external %s",str,a)
+ end
+ else
+ if trace_entities then
+ report_xml("keeping entity &%s;",str)
+ end
+ if str=="" then
+ a="&error;"
+ else
+ a="&"..str..";"
+ end
+ end
+ end
+ end
+ acache[str]=a
+ elseif trace_entities then
+ if not acache[str] then
+ report_xml("converting entity &%s; to %a",str,a)
+ acache[str]=a
+ end
+ end
+ return a
+ else
+ local a=acache[str]
+ if not a then
+ a=resolve_predefined and predefined_simplified[str]
+ if a then
+ acache[str]=a
+ if trace_entities then
+ report_xml("entity &%s; becomes %a",str,a)
+ end
+ elseif str=="" then
+ if trace_entities then
+ report_xml("invalid entity &%s;",str)
+ end
+ a="&error;"
+ acache[str]=a
+ else
+ if trace_entities then
+ report_xml("entity &%s; is made private",str)
+ end
+ a=unescaped(str)
+ acache[str]=a
+ end
+ end
+ return a
+ end
end
-
-local unicode = unicode
-
-utf = utf or unicode.utf8
-
-local concat = table.concat
-local utfchar, utfbyte, utfgsub = utf.char, utf.byte, utf.gsub
-local char, byte, find, bytepairs, utfvalues, format = string.char, string.byte, string.find, string.bytepairs, string.utfvalues, string.format
-local type = type
-
-local utfsplitlines = string.utfsplitlines
-
--- 0 EF BB BF UTF-8
--- 1 FF FE UTF-16-little-endian
--- 2 FE FF UTF-16-big-endian
--- 3 FF FE 00 00 UTF-32-little-endian
--- 4 00 00 FE FF UTF-32-big-endian
-
-unicode.utfname = {
- [0] = 'utf-8',
- [1] = 'utf-16-le',
- [2] = 'utf-16-be',
- [3] = 'utf-32-le',
- [4] = 'utf-32-be'
+local function handle_end_entity(chr)
+ report_xml("error in entity, %a found instead of %a",chr,";")
+end
+local space=S(' \r\n\t')
+local open=P('<')
+local close=P('>')
+local squote=S("'")
+local dquote=S('"')
+local equal=P('=')
+local slash=P('/')
+local colon=P(':')
+local semicolon=P(';')
+local ampersand=P('&')
+local valid=R('az','AZ','09')+S('_-.')
+local name_yes=C(valid^1)*colon*C(valid^1)
+local name_nop=C(P(true))*C(valid^1)
+local name=name_yes+name_nop
+local utfbom=lpeg.patterns.utfbom
+local spacing=C(space^0)
+local anyentitycontent=(1-open-semicolon-space-close)^0
+local hexentitycontent=R("AF","af","09")^0
+local decentitycontent=R("09")^0
+local parsedentity=P("#")/""*(
+ P("x")/""*(hexentitycontent/handle_hex_entity)+(decentitycontent/handle_dec_entity)
+ )+(anyentitycontent/handle_any_entity)
+local entity=ampersand/""*parsedentity*((semicolon/"")+#(P(1)/handle_end_entity))
+local text_unparsed=C((1-open)^1)
+local text_parsed=Cs(((1-open-ampersand)^1+entity)^1)
+local somespace=space^1
+local optionalspace=space^0
+local value=(squote*Cs((entity+(1-squote))^0)*squote)+(dquote*Cs((entity+(1-dquote))^0)*dquote)
+local endofattributes=slash*close+close
+local whatever=space*name*optionalspace*equal
+local wrongvalue=Cs(P(entity+(1-space-endofattributes))^1)/attribute_value_error
+local attributevalue=value+wrongvalue
+local attribute=(somespace*name*optionalspace*equal*optionalspace*attributevalue)/add_attribute
+local attributes=(attribute+somespace^-1*(((1-endofattributes)^1)/attribute_specification_error))^0
+local parsedtext=text_parsed/add_text
+local unparsedtext=text_unparsed/add_text
+local balanced=P { "["*((1-S"[]")+V(1))^0*"]" }
+local emptyelement=(spacing*open*name*attributes*optionalspace*slash*close)/add_empty
+local beginelement=(spacing*open*name*attributes*optionalspace*close)/add_begin
+local endelement=(spacing*open*slash*name*optionalspace*close)/add_end
+local begincomment=open*P("!--")
+local endcomment=P("--")*close
+local begininstruction=open*P("?")
+local endinstruction=P("?")*close
+local begincdata=open*P("![CDATA[")
+local endcdata=P("]]")*close
+local someinstruction=C((1-endinstruction)^0)
+local somecomment=C((1-endcomment )^0)
+local somecdata=C((1-endcdata )^0)
+local function normalentity(k,v ) entities[k]=v end
+local function systementity(k,v,n) entities[k]=v end
+local function publicentity(k,v,n) entities[k]=v end
+local begindoctype=open*P("!DOCTYPE")
+local enddoctype=close
+local beginset=P("[")
+local endset=P("]")
+local doctypename=C((1-somespace-close)^0)
+local elementdoctype=optionalspace*P("=5.1 where %z is depricated
-
-function unicode.utftype(f)
- local str = f:read(4)
- if not str then
- f:seek('set')
- return 0
- -- elseif find(str,"^%z%z\254\255") then -- depricated
- -- elseif find(str,"^\000\000\254\255") then -- not permitted and bugged
- elseif find(str,"\000\000\254\255",1,true) then -- seems to work okay (TH)
- return 4
- -- elseif find(str,"^\255\254%z%z") then -- depricated
- -- elseif find(str,"^\255\254\000\000") then -- not permitted and bugged
- elseif find(str,"\255\254\000\000",1,true) then -- seems to work okay (TH)
- return 3
- elseif find(str,"^\254\255") then
- f:seek('set',2)
- return 2
- elseif find(str,"^\255\254") then
- f:seek('set',2)
- return 1
- elseif find(str,"^\239\187\191") then
- f:seek('set',3)
- return 0
+local grammar_unparsed_text=P { "preamble",
+ preamble=utfbom^0*instruction^0*(doctype+comment+instruction)^0*V("parent")*trailer,
+ parent=beginelement*V("children")^0*endelement,
+ children=unparsedtext+V("parent")+emptyelement+comment+cdata+instruction,
+}
+local function _xmlconvert_(data,settings)
+ settings=settings or {}
+ strip=settings.strip_cm_and_dt
+ utfize=settings.utfize_entities
+ resolve=settings.resolve_entities
+ resolve_predefined=settings.resolve_predefined_entities
+ unify_predefined=settings.unify_predefined_entities
+ cleanup=settings.text_cleanup
+ entities=settings.entities or {}
+ if utfize==nil then
+ settings.utfize_entities=true
+ utfize=true
+ end
+ if resolve_predefined==nil then
+ settings.resolve_predefined_entities=true
+ resolve_predefined=true
+ end
+ stack,top,at,xmlns,errorstr={},{},{},{},nil
+ acache,hcache,dcache={},{},{}
+ reported_attribute_errors={}
+ if settings.parent_root then
+ mt=getmetatable(settings.parent_root)
+ else
+ initialize_mt(top)
+ end
+ stack[#stack+1]=top
+ top.dt={}
+ dt=top.dt
+ if not data or data=="" then
+ errorstr="empty xml file"
+ elseif utfize or resolve then
+ if lpegmatch(grammar_parsed_text,data) then
+ errorstr=""
else
- f:seek('set')
- return 0
+ errorstr="invalid xml file - parsed text"
end
+ elseif type(data)=="string" then
+ if lpegmatch(grammar_unparsed_text,data) then
+ errorstr=""
+ else
+ errorstr="invalid xml file - unparsed text"
+ end
+ else
+ errorstr="invalid xml file - no text at all"
+ end
+ local result
+ if errorstr and errorstr~="" then
+ result={ dt={ { ns="",tg="error",dt={ errorstr },at={},er=true } } }
+ setmetatable(stack,mt)
+ local errorhandler=settings.error_handler
+ if errorhandler==false then
+ else
+ errorhandler=errorhandler or xml.errorhandler
+ if errorhandler then
+ local currentresource=settings.currentresource
+ if currentresource and currentresource~="" then
+ xml.errorhandler(formatters["load error in [%s]: %s"](currentresource,errorstr))
+ else
+ xml.errorhandler(formatters["load error: %s"](errorstr))
+ end
+ end
+ end
+ else
+ result=stack[1]
+ end
+ if not settings.no_root then
+ result={ special=true,ns="",tg='@rt@',dt=result.dt,at={},entities=entities,settings=settings }
+ setmetatable(result,mt)
+ local rdt=result.dt
+ for k=1,#rdt do
+ local v=rdt[k]
+ if type(v)=="table" and not v.special then
+ result.ri=k
+ v.__p__=result
+ break
+ end
+ end
+ end
+ if errorstr and errorstr~="" then
+ result.error=true
+ end
+ result.statistics={
+ entities={
+ decimals=dcache,
+ hexadecimals=hcache,
+ names=acache,
+ }
+ }
+ strip,utfize,resolve,resolve_predefined=nil,nil,nil,nil
+ unify_predefined,cleanup,entities=nil,nil,nil
+ stack,top,at,xmlns,errorstr=nil,nil,nil,nil,nil
+ acache,hcache,dcache=nil,nil,nil
+ reported_attribute_errors,mt,errorhandler=nil,nil,nil
+ return result
end
-
-
-
-local function utf16_to_utf8_be(t)
- if type(t) == "string" then
- t = utfsplitlines(str)
- end
- local result = { } -- we reuse result
- for i=1,#t do
- local r, more = 0, 0
- for left, right in bytepairs(t[i]) do
- if right then
- local now = 256*left + right
- if more > 0 then
- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
- more = 0
- r = r + 1
- result[r] = utfchar(now)
- elseif now >= 0xD800 and now <= 0xDBFF then
- more = now
- else
- r = r + 1
- result[r] = utfchar(now)
- end
- end
- end
- t[i] = concat(result,"",1,r) -- we reused tmp, hence t
- end
- return t
+function xmlconvert(data,settings)
+ local ok,result=pcall(function() return _xmlconvert_(data,settings) end)
+ if ok then
+ return result
+ else
+ return _xmlconvert_("",settings)
+ end
+end
+xml.convert=xmlconvert
+function xml.inheritedconvert(data,xmldata)
+ local settings=xmldata.settings
+ if settings then
+ settings.parent_root=xmldata
+ end
+ local xc=xmlconvert(data,settings)
+ return xc
end
-
-local function utf16_to_utf8_le(t)
- if type(t) == "string" then
- t = utfsplitlines(str)
- end
- local result = { } -- we reuse result
- for i=1,#t do
- local r, more = 0, 0
- for left, right in bytepairs(t[i]) do
- if right then
- local now = 256*right + left
- if more > 0 then
- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
- more = 0
- r = r + 1
- result[r] = utfchar(now)
- elseif now >= 0xD800 and now <= 0xDBFF then
- more = now
- else
- r = r + 1
- result[r] = utfchar(now)
- end
- end
- end
- t[i] = concat(result,"",1,r) -- we reused tmp, hence t
- end
- return t
+function xml.is_valid(root)
+ return root and root.dt and root.dt[1] and type(root.dt[1])=="table" and not root.dt[1].er
end
-
-local function utf32_to_utf8_be(t)
- if type(t) == "string" then
- t = utfsplitlines(t)
+function xml.package(tag,attributes,data)
+ local ns,tg=match(tag,"^(.-):?([^:]+)$")
+ local t={ ns=ns,tg=tg,dt=data or "",at=attributes or {} }
+ setmetatable(t,mt)
+ return t
+end
+function xml.is_valid(root)
+ return root and not root.error
+end
+xml.errorhandler=report_xml
+function xml.load(filename,settings)
+ local data=""
+ if type(filename)=="string" then
+ local f=io.open(filename,'r')
+ if f then
+ data=f:read("*all")
+ f:close()
+ end
+ elseif filename then
+ data=filename:read("*all")
+ end
+ if settings then
+ settings.currentresource=filename
+ local result=xmlconvert(data,settings)
+ settings.currentresource=nil
+ return result
+ else
+ return xmlconvert(data,{ currentresource=filename })
+ end
+end
+local no_root={ no_root=true }
+function xml.toxml(data)
+ if type(data)=="string" then
+ local root={ xmlconvert(data,no_root) }
+ return (#root>1 and root) or root[1]
+ else
+ return data
+ end
+end
+local function copy(old,tables)
+ if old then
+ tables=tables or {}
+ local new={}
+ if not tables[old] then
+ tables[old]=new
end
- local result = { } -- we reuse result
- for i=1,#t do
- local r, more = 0, -1
- for a,b in bytepairs(t[i]) do
- if a and b then
- if more < 0 then
- more = 256*256*256*a + 256*256*b
- else
- r = r + 1
- result[t] = utfchar(more + 256*a + b)
- more = -1
- end
- else
- break
- end
- end
- t[i] = concat(result,"",1,r)
+ for k,v in next,old do
+ new[k]=(type(v)=="table" and (tables[v] or copy(v,tables))) or v
end
- return t
-end
-
-local function utf32_to_utf8_le(t)
- if type(t) == "string" then
- t = utfsplitlines(t)
+ local mt=getmetatable(old)
+ if mt then
+ setmetatable(new,mt)
end
- local result = { } -- we reuse result
- for i=1,#t do
- local r, more = 0, -1
- for a,b in bytepairs(t[i]) do
- if a and b then
- if more < 0 then
- more = 256*b + a
- else
- r = r + 1
- result[t] = utfchar(more + 256*256*256*b + 256*256*a)
- more = -1
- end
- else
- break
- end
+ return new
+ else
+ return {}
+ end
+end
+xml.copy=copy
+function xml.checkbom(root)
+ if root.ri then
+ local dt=root.dt
+ for k=1,#dt do
+ local v=dt[k]
+ if type(v)=="table" and v.special and v.tg=="@pi@" and find(v.dt[1],"xml.*version=") then
+ return
+ end
+ end
+ insert(dt,1,{ special=true,ns="",tg="@pi@",dt={ "xml version='1.0' standalone='yes'" } } )
+ insert(dt,2,"\n" )
+ end
+end
+local function verbose_element(e,handlers)
+ local handle=handlers.handle
+ local serialize=handlers.serialize
+ local ens,etg,eat,edt,ern=e.ns,e.tg,e.at,e.dt,e.rn
+ local ats=eat and next(eat) and {}
+ if ats then
+ for k,v in next,eat do
+ ats[#ats+1]=formatters['%s=%q'](k,escaped(v))
+ end
+ end
+ if ern and trace_entities and ern~=ens then
+ ens=ern
+ end
+ if ens~="" then
+ if edt and #edt>0 then
+ if ats then
+ handle("<",ens,":",etg," ",concat(ats," "),">")
+ else
+ handle("<",ens,":",etg,">")
+ end
+ for i=1,#edt do
+ local e=edt[i]
+ if type(e)=="string" then
+ handle(escaped(e))
+ else
+ serialize(e,handlers)
+ end
+ end
+ handle("",ens,":",etg,">")
+ else
+ if ats then
+ handle("<",ens,":",etg," ",concat(ats," "),"/>")
+ else
+ handle("<",ens,":",etg,"/>")
+ end
+ end
+ else
+ if edt and #edt>0 then
+ if ats then
+ handle("<",etg," ",concat(ats," "),">")
+ else
+ handle("<",etg,">")
+ end
+ for i=1,#edt do
+ local e=edt[i]
+ if type(e)=="string" then
+ handle(escaped(e))
+ else
+ serialize(e,handlers)
end
- t[i] = concat(result,"",1,r)
+ end
+ handle("",etg,">")
+ else
+ if ats then
+ handle("<",etg," ",concat(ats," "),"/>")
+ else
+ handle("<",etg,"/>")
+ end
end
- return t
+ end
end
-
-unicode.utf32_to_utf8_be = utf32_to_utf8_be
-unicode.utf32_to_utf8_le = utf32_to_utf8_le
-unicode.utf16_to_utf8_be = utf16_to_utf8_be
-unicode.utf16_to_utf8_le = utf16_to_utf8_le
-
-function unicode.utf8_to_utf8(t)
- return type(t) == "string" and utfsplitlines(t) or t
+local function verbose_pi(e,handlers)
+ handlers.handle("",e.dt[1],"?>")
end
-
-function unicode.utf16_to_utf8(t,endian)
- return endian and utf16_to_utf8_be(t) or utf16_to_utf8_le(t) or t
+local function verbose_comment(e,handlers)
+ handlers.handle("")
end
-
-function unicode.utf32_to_utf8(t,endian)
- return endian and utf32_to_utf8_be(t) or utf32_to_utf8_le(t) or t
+local function verbose_cdata(e,handlers)
+ handlers.handle("")
end
-
-local function little(c)
- local b = byte(c)
- if b < 0x10000 then
- return char(b%256,b/256)
- else
- b = b - 0x10000
- local b1, b2 = b/1024 + 0xD800, b%1024 + 0xDC00
- return char(b1%256,b1/256,b2%256,b2/256)
- end
+local function verbose_doctype(e,handlers)
+ handlers.handle("")
end
-
-local function big(c)
- local b = byte(c)
- if b < 0x10000 then
- return char(b/256,b%256)
- else
- b = b - 0x10000
- local b1, b2 = b/1024 + 0xD800, b%1024 + 0xDC00
- return char(b1/256,b1%256,b2/256,b2%256)
- end
+local function verbose_root(e,handlers)
+ handlers.serialize(e.dt,handlers)
end
-
-function unicode.utf8_to_utf16(str,littleendian)
- if littleendian then
- return char(255,254) .. utfgsub(str,".",little)
+local function verbose_text(e,handlers)
+ handlers.handle(escaped(e))
+end
+local function verbose_document(e,handlers)
+ local serialize=handlers.serialize
+ local functions=handlers.functions
+ for i=1,#e do
+ local ei=e[i]
+ if type(ei)=="string" then
+ functions["@tx@"](ei,handlers)
else
- return char(254,255) .. utfgsub(str,".",big)
+ serialize(ei,handlers)
end
+ end
end
-
-function unicode.utfcodes(str)
- local t, n = { }, 0
- for u in utfvalues(str) do
- n = n + 1
- t[n] = format("0x%04X",u)
- end
- return concat(t,separator or " ")
+local function serialize(e,handlers,...)
+ local initialize=handlers.initialize
+ local finalize=handlers.finalize
+ local functions=handlers.functions
+ if initialize then
+ local state=initialize(...)
+ if not state==true then
+ return state
+ end
+ end
+ local etg=e.tg
+ if etg then
+ (functions[etg] or functions["@el@"])(e,handlers)
+ else
+ functions["@dc@"](e,handlers)
+ end
+ if finalize then
+ return finalize()
+ end
end
-
-function unicode.ustring(s)
- return format("U+%05X",type(s) == "number" and s or utfbyte(s))
+local function xserialize(e,handlers)
+ local functions=handlers.functions
+ local etg=e.tg
+ if etg then
+ (functions[etg] or functions["@el@"])(e,handlers)
+ else
+ functions["@dc@"](e,handlers)
+ end
+end
+local handlers={}
+local function newhandlers(settings)
+ local t=table.copy(handlers[settings and settings.parent or "verbose"] or {})
+ if settings then
+ for k,v in next,settings do
+ if type(v)=="table" then
+ local tk=t[k] if not tk then tk={} t[k]=tk end
+ for kk,vv in next,v do
+ tk[kk]=vv
+ end
+ else
+ t[k]=v
+ end
+ end
+ if settings.name then
+ handlers[settings.name]=t
+ end
+ end
+ utilities.storage.mark(t)
+ return t
+end
+local nofunction=function() end
+function xml.sethandlersfunction(handler,name,fnc)
+ handler.functions[name]=fnc or nofunction
end
-
-function unicode.xstring(s)
- return format("0x%05X",type(s) == "number" and s or utfbyte(s))
+function xml.gethandlersfunction(handler,name)
+ return handler.functions[name]
end
-
-
-local lpegmatch = lpeg.match
-local patterns = lpeg.patterns
-local utftype = patterns.utftype
-
-function unicode.filetype(data)
- return data and lpegmatch(utftype,data) or "unknown"
+function xml.gethandlers(name)
+ return handlers[name]
end
-
-local toentities = lpeg.Cs (
- (
- patterns.utf8one
- + (
- patterns.utf8two
- + patterns.utf8three
- + patterns.utf8four
- ) / function(s) local b = utfbyte(s) if b < 127 then return s else return format("%X;",b) end end
- )^0
-)
-
-patterns.toentities = toentities
-
-function utf.toentities(str)
- return lpegmatch(toentities,str)
-end
-
-
-
-
-local P, C, R, Cs = lpeg.P, lpeg.C, lpeg.R, lpeg.Cs
-
-local one = P(1)
-local two = C(1) * C(1)
-local four = C(R(utfchar(0xD8),utfchar(0xFF))) * C(1) * C(1) * C(1)
-
--- actually one of them is already utf ... sort of useless this one
-
-local pattern = P("\254\255") * Cs( (
- four / function(a,b,c,d)
- local ab = 0xFF * byte(a) + byte(b)
- local cd = 0xFF * byte(c) + byte(d)
- return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000)
- end
- + two / function(a,b)
- return utfchar(byte(a)*256 + byte(b))
- end
- + one
- )^1 )
- + P("\255\254") * Cs( (
- four / function(b,a,d,c)
- local ab = 0xFF * byte(a) + byte(b)
- local cd = 0xFF * byte(c) + byte(d)
- return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000)
- end
- + two / function(b,a)
- return utfchar(byte(a)*256 + byte(b))
- end
- + one
- )^1 )
-
-function string.toutf(s)
- return lpegmatch(pattern,s) or s -- todo: utf32
-end
-
-local validatedutf = Cs (
- (
- patterns.utf8one
- + patterns.utf8two
- + patterns.utf8three
- + patterns.utf8four
- + P(1) / "�"
- )^0
-)
-
-patterns.validatedutf = validatedutf
-
-function string.validutf(str)
- return lpegmatch(validatedutf,str)
-end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['l-math'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
+newhandlers {
+ name="verbose",
+ initialize=false,
+ finalize=false,
+ serialize=xserialize,
+ handle=print,
+ functions={
+ ["@dc@"]=verbose_document,
+ ["@dt@"]=verbose_doctype,
+ ["@rt@"]=verbose_root,
+ ["@el@"]=verbose_element,
+ ["@pi@"]=verbose_pi,
+ ["@cm@"]=verbose_comment,
+ ["@cd@"]=verbose_cdata,
+ ["@tx@"]=verbose_text,
+ }
}
-
-local floor, sin, cos, tan = math.floor, math.sin, math.cos, math.tan
-
-if not math.round then
- function math.round(x) return floor(x + 0.5) end
-end
-
-if not math.div then
- function math.div(n,m) return floor(n/m) end
+local result
+local xmlfilehandler=newhandlers {
+ name="file",
+ initialize=function(name)
+ result=io.open(name,"wb")
+ return result
+ end,
+ finalize=function()
+ result:close()
+ return true
+ end,
+ handle=function(...)
+ result:write(...)
+ end,
+}
+function xml.save(root,name)
+ serialize(root,xmlfilehandler,name)
end
-
-if not math.mod then
- function math.mod(n,m) return n % m end
+local result
+local xmlstringhandler=newhandlers {
+ name="string",
+ initialize=function()
+ result={}
+ return result
+ end,
+ finalize=function()
+ return concat(result)
+ end,
+ handle=function(...)
+ result[#result+1]=concat {... }
+ end,
+}
+local function xmltostring(root)
+ if not root then
+ return ""
+ elseif type(root)=="string" then
+ return root
+ else
+ return serialize(root,xmlstringhandler) or ""
+ end
end
-
-local pipi = 2*math.pi/360
-
-if not math.sind then
- function math.sind(d) return sin(d*pipi) end
- function math.cosd(d) return cos(d*pipi) end
- function math.tand(d) return tan(d*pipi) end
+local function __tostring(root)
+ return (root and xmltostring(root)) or ""
end
-
-if not math.odd then
- function math.odd (n) return n % 2 ~= 0 end
- function math.even(n) return n % 2 == 0 end
+initialize_mt=function(root)
+ mt={ __tostring=__tostring,__index=root }
end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['util-tab'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-utilities = utilities or {}
-utilities.tables = utilities.tables or { }
-local tables = utilities.tables
-
-local format, gmatch, rep = string.format, string.gmatch, string.rep
-local concat, insert, remove = table.concat, table.insert, table.remove
-local setmetatable, getmetatable, tonumber, tostring = setmetatable, getmetatable, tonumber, tostring
-local type, next, rawset, tonumber = type, next, rawset, tonumber
-
-function tables.definetable(target) -- defines undefined tables
- local composed, t, n = nil, { }, 0
- for name in gmatch(target,"([^%.]+)") do
- n = n + 1
- if composed then
- composed = composed .. "." .. name
- else
- composed = name
- end
- t[n] = format("%s = %s or { }",composed,composed)
+xml.defaulthandlers=handlers
+xml.newhandlers=newhandlers
+xml.serialize=serialize
+xml.tostring=xmltostring
+local function xmlstring(e,handle)
+ if not handle or (e.special and e.tg~="@rt@") then
+ elseif e.tg then
+ local edt=e.dt
+ if edt then
+ for i=1,#edt do
+ xmlstring(edt[i],handle)
+ end
end
- return concat(t,"\n")
+ else
+ handle(e)
+ end
end
-
-function tables.accesstable(target,root)
- local t = root or _G
- for name in gmatch(target,"([^%.]+)") do
- t = t[name]
- if not t then
- return
- end
+xml.string=xmlstring
+function xml.settings(e)
+ while e do
+ local s=e.settings
+ if s then
+ return s
+ else
+ e=e.__p__
end
- return t
+ end
+ return nil
end
-
-function tables.migratetable(target,v,root)
- local t = root or _G
- local names = string.split(target,".")
- for i=1,#names-1 do
- local name = names[i]
- t[name] = t[name] or { }
- t = t[name]
- if not t then
- return
- end
+function xml.root(e)
+ local r=e
+ while e do
+ e=e.__p__
+ if e then
+ r=e
end
- t[names[#names]] = v
+ end
+ return r
end
-
-function tables.removevalue(t,value) -- todo: n
- if value then
- for i=1,#t do
- if t[i] == value then
- remove(t,i)
- -- remove all, so no: return
- end
- end
- end
+function xml.parent(root)
+ return root.__p__
end
-
-function tables.insertbeforevalue(t,value,extra)
- for i=1,#t do
- if t[i] == extra then
- remove(t,i)
- end
- end
- for i=1,#t do
- if t[i] == value then
- insert(t,i,extra)
- return
- end
- end
- insert(t,1,extra)
+function xml.body(root)
+ return root.ri and root.dt[root.ri] or root
end
-
-function tables.insertaftervalue(t,value,extra)
- for i=1,#t do
- if t[i] == extra then
- remove(t,i)
- end
- end
- for i=1,#t do
- if t[i] == value then
- insert(t,i+1,extra)
- return
- end
- end
- insert(t,#t+1,extra)
+function xml.name(root)
+ if not root then
+ return ""
+ end
+ local ns=root.ns
+ local tg=root.tg
+ if ns=="" then
+ return tg
+ else
+ return ns..":"..tg
+ end
end
-
--- experimental
-
-local function toxml(t,d,result,step)
- for k, v in table.sortedpairs(t) do
- if type(v) == "table" then
- if type(k) == "number" then
- result[#result+1] = format("%s",d,k)
- toxml(v,d..step,result,step)
- result[#result+1] = format("%s ",d,k)
- else
- result[#result+1] = format("%s<%s>",d,k)
- toxml(v,d..step,result,step)
- result[#result+1] = format("%s%s>",d,k)
- end
- elseif type(k) == "number" then
- result[#result+1] = format("%s%s ",d,k,v,k)
- else
- result[#result+1] = format("%s<%s>%s%s>",d,k,tostring(v),k)
- end
- end
+function xml.erase(dt,k)
+ if dt then
+ if k then
+ dt[k]=""
+ else for k=1,#dt do
+ dt[1]={ "" }
+ end end
+ end
end
-
-function table.toxml(t,name,nobanner,indent,spaces)
- local noroot = name == false
- local result = (nobanner or noroot) and { } or { "" }
- local indent = rep(" ",indent or 0)
- local spaces = rep(" ",spaces or 1)
- if noroot then
- toxml( t, inndent, result, spaces)
- else
- toxml( { [name or "root"] = t }, indent, result, spaces)
- end
- return concat(result,"\n")
+function xml.assign(dt,k,root)
+ if dt and k then
+ dt[k]=type(root)=="table" and xml.body(root) or root
+ return dt[k]
+ else
+ return xml.body(root)
+ end
+end
+function xml.tocdata(e,wrapper)
+ local whatever=type(e)=="table" and xmltostring(e.dt) or e or ""
+ if wrapper then
+ whatever=formatters["<%s>%s%s>"](wrapper,whatever,wrapper)
+ end
+ local t={ special=true,ns="",tg="@cd@",at={},rn="",dt={ whatever },__p__=e }
+ setmetatable(t,getmetatable(e))
+ e.dt={ t }
end
-
--- also experimental
-
--- encapsulate(table,utilities.tables)
--- encapsulate(table,utilities.tables,true)
--- encapsulate(table,true)
-
-function tables.encapsulate(core,capsule,protect)
- if type(capsule) ~= "table" then
- protect = true
- capsule = { }
- end
- for key, value in next, core do
- if capsule[key] then
- print(format("\ninvalid inheritance '%s' in '%s': %s",key,tostring(core)))
- os.exit()
- else
- capsule[key] = value
- end
- end
- if protect then
- for key, value in next, core do
- core[key] = nil
+function xml.makestandalone(root)
+ if root.ri then
+ local dt=root.dt
+ for k=1,#dt do
+ local v=dt[k]
+ if type(v)=="table" and v.special and v.tg=="@pi@" then
+ local txt=v.dt[1]
+ if find(txt,"xml.*version=") then
+ v.dt[1]=txt.." standalone='yes'"
+ break
end
- setmetatable(core, {
- __index = capsule,
- __newindex = function(t,key,value)
- if capsule[key] then
- print(format("\ninvalid overload '%s' in '%s'",key,tostring(core)))
- os.exit()
- else
- rawset(t,key,value)
- end
- end
- } )
+ end
end
+ end
+ return root
+end
+function xml.kind(e)
+ local dt=e and e.dt
+ if dt then
+ local n=#dt
+ if n==1 then
+ local d=dt[1]
+ if d.special then
+ local tg=d.tg
+ if tg=="@cd@" then
+ return "cdata"
+ elseif tg=="@cm" then
+ return "comment"
+ elseif tg=="@pi@" then
+ return "instruction"
+ elseif tg=="@dt@" then
+ return "declaration"
+ end
+ elseif type(d)=="string" then
+ return "text"
+ end
+ return "element"
+ elseif n>0 then
+ return "mixed"
+ end
+ end
+ return "empty"
end
@@ -4351,9885 +8998,3514 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['util-sto'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local setmetatable, getmetatable = setmetatable, getmetatable
-
-utilities = utilities or { }
-utilities.storage = utilities.storage or { }
-local storage = utilities.storage
-
-function storage.mark(t)
- if not t then
- texio.write_nl("fatal error: storage cannot be marked")
- return -- os.exit()
- end
- local m = getmetatable(t)
- if not m then
- m = { }
- setmetatable(t,m)
- end
- m.__storage__ = true
- return t
-end
-
-function storage.allocate(t)
- t = t or { }
- local m = getmetatable(t)
- if not m then
- m = { }
- setmetatable(t,m)
- end
- m.__storage__ = true
- return t
-end
-
-function storage.marked(t)
- local m = getmetatable(t)
- return m and m.__storage__
-end
-
-function storage.checked(t)
- if not t then
- texio.write_nl("fatal error: storage has not been allocated")
- return -- os.exit()
- end
- return t
-end
+package.loaded["lxml-lpt"] = package.loaded["lxml-lpt"] or true
+-- original size: 48956, stripped down to: 30516
-function storage.setinitializer(data,initialize)
- local m = getmetatable(data) or { }
- m.__index = function(data,k)
- m.__index = nil -- so that we can access the entries during initializing
- initialize()
- return data[k]
- end
- setmetatable(data, m)
+if not modules then modules={} end modules ['lxml-lpt']={
+ version=1.001,
+ comment="this module is the basis for the lxml-* ones",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local concat,remove,insert=table.concat,table.remove,table.insert
+local type,next,tonumber,tostring,setmetatable,load,select=type,next,tonumber,tostring,setmetatable,load,select
+local format,upper,lower,gmatch,gsub,find,rep=string.format,string.upper,string.lower,string.gmatch,string.gsub,string.find,string.rep
+local lpegmatch,lpegpatterns=lpeg.match,lpeg.patterns
+local setmetatableindex=table.setmetatableindex
+local formatters=string.formatters
+local trace_lpath=false if trackers then trackers.register("xml.path",function(v) trace_lpath=v end) end
+local trace_lparse=false if trackers then trackers.register("xml.parse",function(v) trace_lparse=v end) end
+local trace_lprofile=false if trackers then trackers.register("xml.profile",function(v) trace_lpath=v trace_lparse=v trace_lprofile=v end) end
+local report_lpath=logs.reporter("xml","lpath")
+local xml=xml
+local lpathcalls=0 function xml.lpathcalls () return lpathcalls end
+local lpathcached=0 function xml.lpathcached() return lpathcached end
+xml.functions=xml.functions or {}
+local functions=xml.functions
+xml.expressions=xml.expressions or {}
+local expressions=xml.expressions
+xml.finalizers=xml.finalizers or {}
+local finalizers=xml.finalizers
+xml.specialhandler=xml.specialhandler or {}
+local specialhandler=xml.specialhandler
+lpegpatterns.xml=lpegpatterns.xml or {}
+local xmlpatterns=lpegpatterns.xml
+finalizers.xml=finalizers.xml or {}
+finalizers.tex=finalizers.tex or {}
+local function fallback (t,name)
+ local fn=finalizers[name]
+ if fn then
+ t[name]=fn
+ else
+ report_lpath("unknown sub finalizer %a",name)
+ fn=function() end
+ end
+ return fn
+end
+setmetatableindex(finalizers.xml,fallback)
+setmetatableindex(finalizers.tex,fallback)
+xml.defaultprotocol="xml"
+local apply_axis={}
+apply_axis['root']=function(list)
+ local collected={}
+ for l=1,#list do
+ local ll=list[l]
+ local rt=ll
+ while ll do
+ ll=ll.__p__
+ if ll then
+ rt=ll
+ end
+ end
+ collected[l]=rt
+ end
+ return collected
+end
+apply_axis['self']=function(list)
+ return list
+end
+apply_axis['child']=function(list)
+ local collected,c={},0
+ for l=1,#list do
+ local ll=list[l]
+ local dt=ll.dt
+ if dt then
+ local en=0
+ for k=1,#dt do
+ local dk=dt[k]
+ if dk.tg then
+ c=c+1
+ collected[c]=dk
+ dk.ni=k
+ en=en+1
+ dk.ei=en
+ end
+ end
+ ll.en=en
+ end
+ end
+ return collected
end
-
-local keyisvalue = { __index = function(t,k)
- t[k] = k
- return k
-end }
-
-function storage.sparse(t)
- t = t or { }
- setmetatable(t,keyisvalue)
- return t
+local function collect(list,collected,c)
+ local dt=list.dt
+ if dt then
+ local en=0
+ for k=1,#dt do
+ local dk=dt[k]
+ if dk.tg then
+ c=c+1
+ collected[c]=dk
+ dk.ni=k
+ en=en+1
+ dk.ei=en
+ c=collect(dk,collected,c)
+ end
+ end
+ list.en=en
+ end
+ return c
+end
+apply_axis['descendant']=function(list)
+ local collected,c={},0
+ for l=1,#list do
+ c=collect(list[l],collected,c)
+ end
+ return collected
end
-
--- table namespace ?
-
-local function f_empty () return "" end -- t,k
-local function f_self (t,k) t[k] = k return k end
-local function f_ignore() end -- t,k,v
-
-local t_empty = { __index = f_empty }
-local t_self = { __index = f_self }
-local t_ignore = { __newindex = f_ignore }
-
-function table.setmetatableindex(t,f)
- local m = getmetatable(t)
- if m then
- if f == "empty" then
- m.__index = f_empty
- elseif f == "key" then
- m.__index = f_self
- else
- m.__index = f
- end
+local function collect(list,collected,c)
+ local dt=list.dt
+ if dt then
+ local en=0
+ for k=1,#dt do
+ local dk=dt[k]
+ if dk.tg then
+ c=c+1
+ collected[c]=dk
+ dk.ni=k
+ en=en+1
+ dk.ei=en
+ c=collect(dk,collected,c)
+ end
+ end
+ list.en=en
+ end
+ return c
+end
+apply_axis['descendant-or-self']=function(list)
+ local collected,c={},0
+ for l=1,#list do
+ local ll=list[l]
+ if ll.special~=true then
+ c=c+1
+ collected[c]=ll
+ end
+ c=collect(ll,collected,c)
+ end
+ return collected
+end
+apply_axis['ancestor']=function(list)
+ local collected,c={},0
+ for l=1,#list do
+ local ll=list[l]
+ while ll do
+ ll=ll.__p__
+ if ll then
+ c=c+1
+ collected[c]=ll
+ end
+ end
+ end
+ return collected
+end
+apply_axis['ancestor-or-self']=function(list)
+ local collected,c={},0
+ for l=1,#list do
+ local ll=list[l]
+ c=c+1
+ collected[c]=ll
+ while ll do
+ ll=ll.__p__
+ if ll then
+ c=c+1
+ collected[c]=ll
+ end
+ end
+ end
+ return collected
+end
+apply_axis['parent']=function(list)
+ local collected,c={},0
+ for l=1,#list do
+ local pl=list[l].__p__
+ if pl then
+ c=c+1
+ collected[c]=pl
+ end
+ end
+ return collected
+end
+apply_axis['attribute']=function(list)
+ return {}
+end
+apply_axis['namespace']=function(list)
+ return {}
+end
+apply_axis['following']=function(list)
+ return {}
+end
+apply_axis['preceding']=function(list)
+ return {}
+end
+apply_axis['following-sibling']=function(list)
+ local collected,c={},0
+ for l=1,#list do
+ local ll=list[l]
+ local p=ll.__p__
+ local d=p.dt
+ for i=ll.ni+1,#d do
+ local di=d[i]
+ if type(di)=="table" then
+ c=c+1
+ collected[c]=di
+ end
+ end
+ end
+ return collected
+end
+apply_axis['preceding-sibling']=function(list)
+ local collected,c={},0
+ for l=1,#list do
+ local ll=list[l]
+ local p=ll.__p__
+ local d=p.dt
+ for i=1,ll.ni-1 do
+ local di=d[i]
+ if type(di)=="table" then
+ c=c+1
+ collected[c]=di
+ end
+ end
+ end
+ return collected
+end
+apply_axis['reverse-sibling']=function(list)
+ local collected,c={},0
+ for l=1,#list do
+ local ll=list[l]
+ local p=ll.__p__
+ local d=p.dt
+ for i=ll.ni-1,1,-1 do
+ local di=d[i]
+ if type(di)=="table" then
+ c=c+1
+ collected[c]=di
+ end
+ end
+ end
+ return collected
+end
+apply_axis['auto-descendant-or-self']=apply_axis['descendant-or-self']
+apply_axis['auto-descendant']=apply_axis['descendant']
+apply_axis['auto-child']=apply_axis['child']
+apply_axis['auto-self']=apply_axis['self']
+apply_axis['initial-child']=apply_axis['child']
+local function apply_nodes(list,directive,nodes)
+ local maxn=#nodes
+ if maxn==3 then
+ local nns,ntg=nodes[2],nodes[3]
+ if not nns and not ntg then
+ if directive then
+ return list
+ else
+ return {}
+ end
else
- if f == "empty" then
- setmetatable(t, t_empty)
- elseif f == "key" then
- setmetatable(t, t_self)
- else
- setmetatable(t,{ __index = f })
- end
- end
- return t
-end
-
-function table.setmetatablenewindex(t,f)
- local m = getmetatable(t)
- if m then
- if f == "ignore" then
- m.__newindex = f_ignore
- else
- m.__newindex = f
+ local collected,c,m,p={},0,0,nil
+ if not nns then
+ for l=1,#list do
+ local ll=list[l]
+ local ltg=ll.tg
+ if ltg then
+ if directive then
+ if ntg==ltg then
+ local llp=ll.__p__;if llp~=p then p,m=llp,1 else m=m+1 end
+ c=c+1
+ collected[c],ll.mi=ll,m
+ end
+ elseif ntg~=ltg then
+ local llp=ll.__p__;if llp~=p then p,m=llp,1 else m=m+1 end
+ c=c+1
+ collected[c],ll.mi=ll,m
+ end
+ end
+ end
+ elseif not ntg then
+ for l=1,#list do
+ local ll=list[l]
+ local lns=ll.rn or ll.ns
+ if lns then
+ if directive then
+ if lns==nns then
+ local llp=ll.__p__;if llp~=p then p,m=llp,1 else m=m+1 end
+ c=c+1
+ collected[c],ll.mi=ll,m
+ end
+ elseif lns~=nns then
+ local llp=ll.__p__;if llp~=p then p,m=llp,1 else m=m+1 end
+ c=c+1
+ collected[c],ll.mi=ll,m
+ end
+ end
+ end
+ else
+ for l=1,#list do
+ local ll=list[l]
+ local ltg=ll.tg
+ if ltg then
+ local lns=ll.rn or ll.ns
+ local ok=ltg==ntg and lns==nns
+ if directive then
+ if ok then
+ local llp=ll.__p__;if llp~=p then p,m=llp,1 else m=m+1 end
+ c=c+1
+ collected[c],ll.mi=ll,m
+ end
+ elseif not ok then
+ local llp=ll.__p__;if llp~=p then p,m=llp,1 else m=m+1 end
+ c=c+1
+ collected[c],ll.mi=ll,m
+ end
+ end
+ end
+ end
+ return collected
+ end
+ else
+ local collected,c,m,p={},0,0,nil
+ for l=1,#list do
+ local ll=list[l]
+ local ltg=ll.tg
+ if ltg then
+ local lns=ll.rn or ll.ns
+ local ok=false
+ for n=1,maxn,3 do
+ local nns,ntg=nodes[n+1],nodes[n+2]
+ ok=(not ntg or ltg==ntg) and (not nns or lns==nns)
+ if ok then
+ break
+ end
end
- else
- if f == "ignore" then
- setmetatable(t, t_ignore)
- else
- setmetatable(t,{ __newindex = f })
+ if directive then
+ if ok then
+ local llp=ll.__p__;if llp~=p then p,m=llp,1 else m=m+1 end
+ c=c+1
+ collected[c],ll.mi=ll,m
+ end
+ elseif not ok then
+ local llp=ll.__p__;if llp~=p then p,m=llp,1 else m=m+1 end
+ c=c+1
+ collected[c],ll.mi=ll,m
end
+ end
end
- return t
+ return collected
+ end
end
-
-function table.setmetatablecall(t,f)
- local m = getmetatable(t)
- if m then
- m.__call = f
+local quit_expression=false
+local function apply_expression(list,expression,order)
+ local collected,c={},0
+ quit_expression=false
+ for l=1,#list do
+ local ll=list[l]
+ if expression(list,ll,l,order) then
+ c=c+1
+ collected[c]=ll
+ end
+ if quit_expression then
+ break
+ end
+ end
+ return collected
+end
+local P,V,C,Cs,Cc,Ct,R,S,Cg,Cb=lpeg.P,lpeg.V,lpeg.C,lpeg.Cs,lpeg.Cc,lpeg.Ct,lpeg.R,lpeg.S,lpeg.Cg,lpeg.Cb
+local spaces=S(" \n\r\t\f")^0
+local lp_space=S(" \n\r\t\f")
+local lp_any=P(1)
+local lp_noequal=P("!=")/"~="+P("<=")+P(">=")+P("==")
+local lp_doequal=P("=")/"=="
+local lp_or=P("|")/" or "
+local lp_and=P("&")/" and "
+local lp_builtin=P (
+ P("text")/"(ll.dt[1] or '')"+
+ P("content")/"ll.dt"+
+ P("name")/"((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)"+P("tag")/"ll.tg"+P("position")/"l"+
+ P("firstindex")/"1"+P("lastindex")/"(#ll.__p__.dt or 1)"+P("firstelement")/"1"+P("lastelement")/"(ll.__p__.en or 1)"+P("first")/"1"+P("last")/"#list"+P("rootposition")/"order"+P("order")/"order"+P("element")/"(ll.ei or 1)"+P("index")/"(ll.ni or 1)"+P("match")/"(ll.mi or 1)"+
+ P("ns")/"ll.ns"
+ )*((spaces*P("(")*spaces*P(")"))/"")
+local lp_attribute=(P("@")+P("attribute::"))/""*Cc("(ll.at and ll.at['")*((R("az","AZ")+S("-_:"))^1)*Cc("'])")
+lp_fastpos_p=P("+")^0*R("09")^1*P(-1)/"l==%0"
+lp_fastpos_n=P("-")*R("09")^1*P(-1)/"(%0<0 and (#list+%0==l))"
+local lp_fastpos=lp_fastpos_n+lp_fastpos_p
+local lp_reserved=C("and")+C("or")+C("not")+C("div")+C("mod")+C("true")+C("false")
+local lp_lua_function=Cs((R("az","AZ","__")^1*(P(".")*R("az","AZ","__")^1)^1)*("("))/"%0"
+local lp_function=C(R("az","AZ","__")^1)*P("(")/function(t)
+ if expressions[t] then
+ return "expr."..t.."("
+ else
+ return "expr.error("
+ end
+end
+local lparent=P("(")
+local rparent=P(")")
+local noparent=1-(lparent+rparent)
+local nested=P{lparent*(noparent+V(1))^0*rparent}
+local value=P(lparent*C((noparent+nested)^0)*rparent)
+local lp_child=Cc("expr.child(ll,'")*R("az","AZ","--","__")^1*Cc("')")
+local lp_number=S("+-")*R("09")^1
+local lp_string=Cc("'")*R("az","AZ","--","__")^1*Cc("'")
+local lp_content=(P("'")*(1-P("'"))^0*P("'")+P('"')*(1-P('"'))^0*P('"'))
+local cleaner
+local lp_special=(C(P("name")+P("text")+P("tag")+P("count")+P("child")))*value/function(t,s)
+ if expressions[t] then
+ s=s and s~="" and lpegmatch(cleaner,s)
+ if s and s~="" then
+ return "expr."..t.."(ll,"..s..")"
else
- setmetatable(t,{ __call = f })
+ return "expr."..t.."(ll)"
end
- return t
+ else
+ return "expr.error("..t..")"
+ end
end
-
-function table.setmetatablekey(t,key,value)
- local m = getmetatable(t)
- if not m then
- m = { }
- setmetatable(t,m)
+local content=lp_builtin+lp_attribute+lp_special+lp_noequal+lp_doequal+lp_or+lp_and+lp_reserved+lp_lua_function+lp_function+lp_content+
+ lp_child+lp_any
+local converter=Cs (
+ lp_fastpos+(P { lparent*(V(1))^0*rparent+content } )^0
+)
+cleaner=Cs ((
+ lp_reserved+lp_number+lp_string+1 )^1 )
+local template_e=[[
+ local expr = xml.expressions
+ return function(list,ll,l,order)
+ return %s
end
- m[key] = value
- return t
+]]
+local template_f_y=[[
+ local finalizer = xml.finalizers['%s']['%s']
+ return function(collection)
+ return finalizer(collection,%s)
+ end
+]]
+local template_f_n=[[
+ return xml.finalizers['%s']['%s']
+]]
+local register_self={ kind="axis",axis="self" }
+local register_parent={ kind="axis",axis="parent" }
+local register_descendant={ kind="axis",axis="descendant" }
+local register_child={ kind="axis",axis="child" }
+local register_descendant_or_self={ kind="axis",axis="descendant-or-self" }
+local register_root={ kind="axis",axis="root" }
+local register_ancestor={ kind="axis",axis="ancestor" }
+local register_ancestor_or_self={ kind="axis",axis="ancestor-or-self" }
+local register_attribute={ kind="axis",axis="attribute" }
+local register_namespace={ kind="axis",axis="namespace" }
+local register_following={ kind="axis",axis="following" }
+local register_following_sibling={ kind="axis",axis="following-sibling" }
+local register_preceding={ kind="axis",axis="preceding" }
+local register_preceding_sibling={ kind="axis",axis="preceding-sibling" }
+local register_reverse_sibling={ kind="axis",axis="reverse-sibling" }
+local register_auto_descendant_or_self={ kind="axis",axis="auto-descendant-or-self" }
+local register_auto_descendant={ kind="axis",axis="auto-descendant" }
+local register_auto_self={ kind="axis",axis="auto-self" }
+local register_auto_child={ kind="axis",axis="auto-child" }
+local register_initial_child={ kind="axis",axis="initial-child" }
+local register_all_nodes={ kind="nodes",nodetest=true,nodes={ true,false,false } }
+local skip={}
+local function errorrunner_e(str,cnv)
+ if not skip[str] then
+ report_lpath("error in expression: %s => %s",str,cnv)
+ skip[str]=cnv or str
+ end
+ return false
end
-
-function table.getmetatablekey(t,key,value)
- local m = getmetatable(t)
- return m and m[key]
+local function errorrunner_f(str,arg)
+ report_lpath("error in finalizer: %s(%s)",str,arg or "")
+ return false
end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['util-mrg'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- hm, quite unreadable
-
-local gsub, format = string.gsub, string.format
-local concat = table.concat
-local type, next = type, next
-
-utilities = utilities or {}
-utilities.merger = utilities.merger or { } -- maybe mergers
-utilities.report = logs and logs.reporter("system") or print
-
-local merger = utilities.merger
-
-merger.strip_comment = true
-
-local m_begin_merge = "begin library merge"
-local m_end_merge = "end library merge"
-local m_begin_closure = "do -- create closure to overcome 200 locals limit"
-local m_end_closure = "end -- of closure"
-
-local m_pattern =
- "%c+" ..
- "%-%-%s+" .. m_begin_merge ..
- "%c+(.-)%c+" ..
- "%-%-%s+" .. m_end_merge ..
- "%c+"
-
-local m_format =
- "\n\n-- " .. m_begin_merge ..
- "\n%s\n" ..
- "-- " .. m_end_merge .. "\n\n"
-
-local m_faked =
- "-- " .. "created merged file" .. "\n\n" ..
- "-- " .. m_begin_merge .. "\n\n" ..
- "-- " .. m_end_merge .. "\n\n"
-
-local function self_fake()
- return m_faked
+local function register_nodes(nodetest,nodes)
+ return { kind="nodes",nodetest=nodetest,nodes=nodes }
end
-
-local function self_nothing()
- return ""
-end
-
-local function self_load(name)
- local data = io.loaddata(name) or ""
- if data == "" then
- utilities.report("merge: unknown file %s",name)
- else
- utilities.report("merge: inserting %s",name)
- end
- return data or ""
-end
-
-local function self_save(name, data)
- if data ~= "" then
- if merger.strip_comment then
- -- saves some 20K
- local n = #data
- data = gsub(data,"%-%-~[^\n\r]*[\r\n]","")
- utilities.report("merge: %s bytes of comment stripped, %s bytes of code left",n-#data,#data)
- end
- io.savedata(name,data)
- utilities.report("merge: saving %s",name)
- end
-end
-
-local function self_swap(data,code)
- return data ~= "" and (gsub(data,m_pattern, function() return format(m_format,code) end, 1)) or ""
-end
-
-local function self_libs(libs,list)
- local result, f, frozen, foundpath = { }, nil, false, nil
- result[#result+1] = "\n"
- if type(libs) == 'string' then libs = { libs } end
- if type(list) == 'string' then list = { list } end
- for i=1,#libs do
- local lib = libs[i]
- for j=1,#list do
- local pth = gsub(list[j],"\\","/") -- file.clean_path
- utilities.report("merge: checking library path %s",pth)
- local name = pth .. "/" .. lib
- if lfs.isfile(name) then
- foundpath = pth
- end
- end
- if foundpath then break end
- end
- if foundpath then
- utilities.report("merge: using library path %s",foundpath)
- local right, wrong = { }, { }
- for i=1,#libs do
- local lib = libs[i]
- local fullname = foundpath .. "/" .. lib
- if lfs.isfile(fullname) then
- utilities.report("merge: using library %s",fullname)
- right[#right+1] = lib
- result[#result+1] = m_begin_closure
- result[#result+1] = io.loaddata(fullname,true)
- result[#result+1] = m_end_closure
- else
- utilities.report("merge: skipping library %s",fullname)
- wrong[#wrong+1] = lib
- end
- end
- if #right > 0 then
- utilities.report("merge: used libraries: %s",concat(right," "))
- end
- if #wrong > 0 then
- utilities.report("merge: skipped libraries: %s",concat(wrong," "))
- end
- else
- utilities.report("merge: no valid library path found")
- end
- return concat(result, "\n\n")
-end
-
-function merger.selfcreate(libs,list,target)
- if target then
- self_save(target,self_swap(self_fake(),self_libs(libs,list)))
- end
-end
-
-function merger.selfmerge(name,libs,list,target)
- self_save(target or name,self_swap(self_load(name),self_libs(libs,list)))
-end
-
-function merger.selfclean(name)
- self_save(name,self_swap(self_load(name),self_nothing()))
-end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['util-lua'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-utilities = utilities or {}
-utilities.lua = utilities.lua or { }
-utilities.report = logs and logs.reporter("system") or print
-
-local function stupidcompile(luafile,lucfile)
- local data = io.loaddata(luafile)
- if data and data ~= "" then
- data = string.dump(data)
- if data and data ~= "" then
- io.savedata(lucfile,data)
- end
- end
-end
-
-function utilities.lua.compile(luafile,lucfile,cleanup,strip,fallback) -- defaults: cleanup=false strip=true
- utilities.report("lua: compiling %s into %s",luafile,lucfile)
- os.remove(lucfile)
- local command = "-o " .. string.quoted(lucfile) .. " " .. string.quoted(luafile)
- if strip ~= false then
- command = "-s " .. command
- end
- local done = os.spawn("texluac " .. command) == 0 -- or os.spawn("luac " .. command) == 0
- if not done and fallback then
- utilities.report("lua: dumping %s into %s (unstripped)",luafile,lucfile)
- stupidcompile(luafile,lucfile) -- maybe use the stripper we have elsewhere
- cleanup = false -- better see how worse it is
- end
- if done and cleanup == true and lfs.isfile(lucfile) and lfs.isfile(luafile) then
- utilities.report("lua: removing %s",luafile)
- os.remove(luafile)
- end
- return done
+local function register_expression(expression)
+ local converted=lpegmatch(converter,expression)
+ local runner=load(format(template_e,converted))
+ runner=(runner and runner()) or function() errorrunner_e(expression,converted) end
+ return { kind="expression",expression=expression,converted=converted,evaluator=runner }
end
-
-
-
-
-
-
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['util-prs'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local P, R, V, C, Ct, Cs, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Carg
-local lpegmatch = lpeg.match
-local concat, format, gmatch, find = table.concat, string.format, string.gmatch, string.find
-local tostring, type, next = tostring, type, next
-
-utilities = utilities or {}
-utilities.parsers = utilities.parsers or { }
-local parsers = utilities.parsers
-parsers.patterns = parsers.patterns or { }
-
-local setmetatableindex = table.setmetatableindex
-local sortedhash = table.sortedhash
-
--- we could use a Cf Cg construct
-
-local escape, left, right = P("\\"), P('{'), P('}')
-
-lpeg.patterns.balanced = P {
- [1] = ((escape * (left+right)) + (1 - (left+right)) + V(2))^0,
- [2] = left * V(1) * right
+local function register_finalizer(protocol,name,arguments)
+ local runner
+ if arguments and arguments~="" then
+ runner=load(format(template_f_y,protocol or xml.defaultprotocol,name,arguments))
+ else
+ runner=load(format(template_f_n,protocol or xml.defaultprotocol,name))
+ end
+ runner=(runner and runner()) or function() errorrunner_f(name,arguments) end
+ return { kind="finalizer",name=name,arguments=arguments,finalizer=runner }
+end
+local expression=P { "ex",
+ ex="["*C((V("sq")+V("dq")+(1-S("[]"))+V("ex"))^0)*"]",
+ sq="'"*(1-S("'"))^0*"'",
+ dq='"'*(1-S('"'))^0*'"',
}
-
-local space = P(' ')
-local equal = P("=")
-local comma = P(",")
-local lbrace = P("{")
-local rbrace = P("}")
-local nobrace = 1 - (lbrace+rbrace)
-local nested = P { lbrace * (nobrace + V(1))^0 * rbrace }
-local spaces = space^0
-local argument = Cs((lbrace/"") * ((nobrace + nested)^0) * (rbrace/""))
-local content = (1-P(-1))^0
-
-lpeg.patterns.nested = nested -- no capture
-lpeg.patterns.argument = argument -- argument after e.g. =
-lpeg.patterns.content = content -- rest after e.g =
-
-local value = P(lbrace * C((nobrace + nested)^0) * rbrace) + C((nested + (1-comma))^0)
-
-local key = C((1-equal-comma)^1)
-local pattern_a = (space+comma)^0 * (key * equal * value + key * C(""))
-local pattern_c = (space+comma)^0 * (key * equal * value)
-
-local key = C((1-space-equal-comma)^1)
-local pattern_b = spaces * comma^0 * spaces * (key * ((spaces * equal * spaces * value) + C("")))
-
--- "a=1, b=2, c=3, d={a{b,c}d}, e=12345, f=xx{a{b,c}d}xx, g={}" : outer {} removes, leading spaces ignored
-
-local hash = { }
-
-local function set(key,value)
- hash[key] = value
-end
-
-local function set(key,value)
- hash[key] = value
-end
-
-local pattern_a_s = (pattern_a/set)^1
-local pattern_b_s = (pattern_b/set)^1
-local pattern_c_s = (pattern_c/set)^1
-
-parsers.patterns.settings_to_hash_a = pattern_a_s
-parsers.patterns.settings_to_hash_b = pattern_b_s
-parsers.patterns.settings_to_hash_c = pattern_c_s
-
-function parsers.make_settings_to_hash_pattern(set,how)
- if how == "strict" then
- return (pattern_c/set)^1
- elseif how == "tolerant" then
- return (pattern_b/set)^1
- else
- return (pattern_a/set)^1
- end
-end
-
-function parsers.settings_to_hash(str,existing)
- if str and str ~= "" then
- hash = existing or { }
- lpegmatch(pattern_a_s,str)
- return hash
- else
- return { }
- end
-end
-
-function parsers.settings_to_hash_tolerant(str,existing)
- if str and str ~= "" then
- hash = existing or { }
- lpegmatch(pattern_b_s,str)
- return hash
- else
- return { }
- end
-end
-
-function parsers.settings_to_hash_strict(str,existing)
- if str and str ~= "" then
- hash = existing or { }
- lpegmatch(pattern_c_s,str)
- return next(hash) and hash
- else
- return nil
- end
-end
-
-local separator = comma * space^0
-local value = P(lbrace * C((nobrace + nested)^0) * rbrace) + C((nested + (1-comma))^0)
-local pattern = Ct(value*(separator*value)^0)
-
--- "aap, {noot}, mies" : outer {} removes, leading spaces ignored
-
-parsers.patterns.settings_to_array = pattern
-
--- we could use a weak table as cache
-
-function parsers.settings_to_array(str,strict)
- if not str or str == "" then
- return { }
- elseif strict then
- if find(str,"{") then
- return lpegmatch(pattern,str)
- else
- return { str }
- end
- else
- return lpegmatch(pattern,str)
- end
-end
-
-local function set(t,v)
- t[#t+1] = v
-end
-
-local value = P(Carg(1)*value) / set
-local pattern = value*(separator*value)^0 * Carg(1)
-
-function parsers.add_settings_to_array(t,str)
- return lpegmatch(pattern,str,nil,t)
-end
-
-function parsers.hash_to_string(h,separator,yes,no,strict,omit)
- if h then
- local t, tn, s = { }, 0, table.sortedkeys(h)
- omit = omit and table.tohash(omit)
- for i=1,#s do
- local key = s[i]
- if not omit or not omit[key] then
- local value = h[key]
- if type(value) == "boolean" then
- if yes and no then
- if value then
- tn = tn + 1
- t[tn] = key .. '=' .. yes
- elseif not strict then
- tn = tn + 1
- t[tn] = key .. '=' .. no
- end
- elseif value or not strict then
- tn = tn + 1
- t[tn] = key .. '=' .. tostring(value)
- end
- else
- tn = tn + 1
- t[tn] = key .. '=' .. value
- end
- end
- end
- return concat(t,separator or ",")
- else
- return ""
- end
-end
-
-function parsers.array_to_string(a,separator)
- if a then
- return concat(a,separator or ",")
- else
- return ""
- end
-end
-
-function parsers.settings_to_set(str,t) -- tohash? -- todo: lpeg -- duplicate anyway
- t = t or { }
--- for s in gmatch(str,"%s*([^, ]+)") do -- space added
- for s in gmatch(str,"[^, ]+") do -- space added
- t[s] = true
- end
- return t
-end
-
-function parsers.simple_hash_to_string(h, separator)
- local t, tn = { }, 0
- for k, v in sortedhash(h) do
- if v then
- tn = tn + 1
- t[tn] = k
- end
- end
- return concat(t,separator or ",")
-end
-
-local value = lbrace * C((nobrace + nested)^0) * rbrace
-local pattern = Ct((space + value)^0)
-
-function parsers.arguments_to_table(str)
- return lpegmatch(pattern,str)
-end
-
--- temporary here (unoptimized)
-
-function parsers.getparameters(self,class,parentclass,settings)
- local sc = self[class]
- if not sc then
- sc = { }
- self[class] = sc
- if parentclass then
- local sp = self[parentclass]
- if not sp then
- sp = { }
- self[parentclass] = sp
- end
- setmetatableindex(sc,sp)
- end
- end
- parsers.settings_to_hash(settings,sc)
-end
-
-function parsers.listitem(str)
- return gmatch(str,"[^, ]+")
-end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['util-fmt'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
+local arguments=P { "ar",
+ ar="("*Cs((V("sq")+V("dq")+V("nq")+P(1-P(")")))^0)*")",
+ nq=((1-S("),'\""))^1)/function(s) return format("%q",s) end,
+ sq=P("'")*(1-P("'"))^0*P("'"),
+ dq=P('"')*(1-P('"'))^0*P('"'),
}
-
-utilities = utilities or { }
-utilities.formatters = utilities.formatters or { }
-local formatters = utilities.formatters
-
-local concat, format = table.concat, string.format
-local tostring, type = tostring, type
-local strip = string.strip
-
-local P, R, Cs = lpeg.P, lpeg.R, lpeg.Cs
-local lpegmatch = lpeg.match
-
--- temporary here
-
-local digit = R("09")
-local period = P(".")
-local zero = P("0")
-local trailingzeros = zero^0 * -digit -- suggested by Roberto R
-local case_1 = period * trailingzeros / ""
-local case_2 = period * (digit - trailingzeros)^1 * (trailingzeros / "")
-local number = digit^1 * (case_1 + case_2)
-local stripper = Cs((number + 1)^0)
-
-
-lpeg.patterns.stripzeros = stripper
-
-function formatters.stripzeros(str)
- return lpegmatch(stripper,str)
-end
-
-function formatters.formatcolumns(result,between)
- if result and #result > 0 then
- between = between or " "
- local widths, numbers = { }, { }
- local first = result[1]
- local n = #first
- for i=1,n do
- widths[i] = 0
- end
- for i=1,#result do
- local r = result[i]
- for j=1,n do
- local rj = r[j]
- local tj = type(rj)
- if tj == "number" then
- numbers[j] = true
- end
- if tj ~= "string" then
- rj = tostring(rj)
- r[j] = rj
- end
- local w = #rj
- if w > widths[j] then
- widths[j] = w
- end
- end
- end
- for i=1,n do
- local w = widths[i]
- if numbers[i] then
- if w > 80 then
- widths[i] = "%s" .. between
- else
- widths[i] = "%0" .. w .. "i" .. between
- end
- else
- if w > 80 then
- widths[i] = "%s" .. between
- elseif w > 0 then
- widths[i] = "%-" .. w .. "s" .. between
- else
- widths[i] = "%s"
- end
- end
- end
- local template = strip(concat(widths))
- for i=1,#result do
- local str = format(template,unpack(result[i]))
- result[i] = strip(str)
- end
- end
- return result
-end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['util.deb'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
+local function register_error(str)
+ return { kind="error",error=format("unparsed: %s",str) }
+end
+local special_1=P("*")*Cc(register_auto_descendant)*Cc(register_all_nodes)
+local special_2=P("/")*Cc(register_auto_self)
+local special_3=P("")*Cc(register_auto_self)
+local no_nextcolon=P(-1)+#(1-P(":"))
+local no_nextlparent=P(-1)+#(1-P("("))
+local pathparser=Ct { "patterns",
+ patterns=spaces*V("protocol")*spaces*(
+ (V("special")*spaces*P(-1) )+(V("initial")*spaces*V("step")*spaces*(P("/")*spaces*V("step")*spaces)^0 )
+ ),
+ protocol=Cg(V("letters"),"protocol")*P("://")+Cg(Cc(nil),"protocol"),
+ step=((V("shortcuts")+P("/")+V("axis"))*spaces*V("nodes")^0+V("error"))*spaces*V("expressions")^0*spaces*V("finalizer")^0,
+ axis=V("descendant")+V("child")+V("parent")+V("self")+V("root")+V("ancestor")+V("descendant_or_self")+V("following_sibling")+V("following")+V("reverse_sibling")+V("preceding_sibling")+V("preceding")+V("ancestor_or_self")+#(1-P(-1))*Cc(register_auto_child),
+ special=special_1+special_2+special_3,
+ initial=(P("/")*spaces*Cc(register_initial_child))^-1,
+ error=(P(1)^1)/register_error,
+ shortcuts_a=V("s_descendant_or_self")+V("s_descendant")+V("s_child")+V("s_parent")+V("s_self")+V("s_root")+V("s_ancestor"),
+ shortcuts=V("shortcuts_a")*(spaces*"/"*spaces*V("shortcuts_a"))^0,
+ s_descendant_or_self=(P("***/")+P("/"))*Cc(register_descendant_or_self),
+ s_descendant=P("**")*Cc(register_descendant),
+ s_child=P("*")*no_nextcolon*Cc(register_child ),
+ s_parent=P("..")*Cc(register_parent ),
+ s_self=P("." )*Cc(register_self ),
+ s_root=P("^^")*Cc(register_root ),
+ s_ancestor=P("^")*Cc(register_ancestor ),
+ descendant=P("descendant::")*Cc(register_descendant ),
+ child=P("child::")*Cc(register_child ),
+ parent=P("parent::")*Cc(register_parent ),
+ self=P("self::")*Cc(register_self ),
+ root=P('root::')*Cc(register_root ),
+ ancestor=P('ancestor::')*Cc(register_ancestor ),
+ descendant_or_self=P('descendant-or-self::')*Cc(register_descendant_or_self ),
+ ancestor_or_self=P('ancestor-or-self::')*Cc(register_ancestor_or_self ),
+ following=P('following::')*Cc(register_following ),
+ following_sibling=P('following-sibling::')*Cc(register_following_sibling ),
+ preceding=P('preceding::')*Cc(register_preceding ),
+ preceding_sibling=P('preceding-sibling::')*Cc(register_preceding_sibling ),
+ reverse_sibling=P('reverse-sibling::')*Cc(register_reverse_sibling ),
+ nodes=(V("nodefunction")*spaces*P("(")*V("nodeset")*P(")")+V("nodetest")*V("nodeset"))/register_nodes,
+ expressions=expression/register_expression,
+ letters=R("az")^1,
+ name=(1-S("/[]()|:*!"))^1,
+ negate=P("!")*Cc(false),
+ nodefunction=V("negate")+P("not")*Cc(false)+Cc(true),
+ nodetest=V("negate")+Cc(true),
+ nodename=(V("negate")+Cc(true))*spaces*((V("wildnodename")*P(":")*V("wildnodename"))+(Cc(false)*V("wildnodename"))),
+ wildnodename=(C(V("name"))+P("*")*Cc(false))*no_nextlparent,
+ nodeset=spaces*Ct(V("nodename")*(spaces*P("|")*spaces*V("nodename"))^0)*spaces,
+ finalizer=(Cb("protocol")*P("/")^-1*C(V("name"))*arguments*P(-1))/register_finalizer,
}
-
--- the tag is kind of generic and used for functions that are not
--- bound to a variable, like node.new, node.copy etc (contrary to for instance
--- node.has_attribute which is bound to a has_attribute local variable in mkiv)
-
-local debug = require "debug"
-
-local getinfo = debug.getinfo
-local type, next, tostring = type, next, tostring
-local format, find = string.format, string.find
-local is_boolean = string.is_boolean
-
-utilities = utilities or { }
-utilities.debugger = utilities.debugger or { }
-local debugger = utilities.debugger
-
-local counters = { }
-local names = { }
-
--- one
-
-local function hook()
- local f = getinfo(2) -- "nS"
- if f then
- local n = "unknown"
- if f.what == "C" then
- n = f.name or ''
- if not names[n] then
- names[n] = format("%42s",n)
- end
- else
- -- source short_src linedefined what name namewhat nups func
- n = f.name or f.namewhat or f.what
- if not n or n == "" then
- n = "?"
- end
- if not names[n] then
- names[n] = format("%42s : % 5i : %s",n,f.linedefined or 0,f.short_src or "unknown source")
- end
- end
- counters[n] = (counters[n] or 0) + 1
- end
-end
-
-function debugger.showstats(printer,threshold) -- hm, something has changed, rubish now
- printer = printer or texio.write or print
- threshold = threshold or 0
- local total, grandtotal, functions = 0, 0, 0
- local dataset = { }
- for name, count in next, counters do
- dataset[#dataset+1] = { name, count }
- end
- table.sort(dataset,function(a,b) return a[2] == b[2] and b[1] > a[1] or a[2] > b[2] end)
- for i=1,#dataset do
- local d = dataset[i]
- local name = d[1]
- local count = d[2]
- if count > threshold and not find(name,"for generator") then -- move up
- printer(format("%8i %s\n", count, names[name]))
- total = total + count
- end
- grandtotal = grandtotal + count
- functions = functions + 1
- end
- printer("\n")
- printer(format("functions : % 10i\n", functions))
- printer(format("total : % 10i\n", total))
- printer(format("grand total: % 10i\n", grandtotal))
- printer(format("threshold : % 10i\n", threshold))
+xmlpatterns.pathparser=pathparser
+local cache={}
+local function nodesettostring(set,nodetest)
+ local t={}
+ for i=1,#set,3 do
+ local directive,ns,tg=set[i],set[i+1],set[i+2]
+ if not ns or ns=="" then ns="*" end
+ if not tg or tg=="" then tg="*" end
+ tg=(tg=="@rt@" and "[root]") or format("%s:%s",ns,tg)
+ t[i]=(directive and tg) or format("not(%s)",tg)
+ end
+ if nodetest==false then
+ return format("not(%s)",concat(t,"|"))
+ else
+ return concat(t,"|")
+ end
end
-
-function debugger.savestats(filename,threshold)
- local f = io.open(filename,'w')
- if f then
- debugger.showstats(function(str) f:write(str) end,threshold)
- f:close()
- end
-end
-
-function debugger.enable()
- debug.sethook(hook,"c")
-end
-
-function debugger.disable()
- debug.sethook()
-end
-
-
-
-
-
-local is_node = node and node.is_node
-local is_lpeg = lpeg and lpeg.type
-
-function inspect(i) -- global function
- local ti = type(i)
- if ti == "table" then
- table.print(i,"table")
- elseif is_node and is_node(i) then
- table.print(nodes.astable(i),tostring(i))
- elseif is_lpeg and is_lpeg(i) then
- lpeg.print(i)
- else
- print(tostring(i))
- end
-end
-
--- from the lua book:
-
-function traceback()
- local level = 1
- while true do
- local info = debug.getinfo(level, "Sl")
- if not info then
- break
- elseif info.what == "C" then
- print(format("%3i : C function",level))
- else
- print(format("%3i : [%s]:%d",level,info.short_src,info.currentline))
- end
- level = level + 1
- end
-end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['trac-inf'] = {
- version = 1.001,
- comment = "companion to trac-inf.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- As we want to protect the global tables, we no longer store the timing
--- in the tables themselves but in a hidden timers table so that we don't
--- get warnings about assignments. This is more efficient than using rawset
--- and rawget.
-
-local format, lower = string.format, string.lower
-local clock = os.gettimeofday or os.clock -- should go in environment
-local write_nl = texio.write_nl
-
-statistics = statistics or { }
-local statistics = statistics
-
-statistics.enable = true
-statistics.threshold = 0.05
-
-local statusinfo, n, registered, timers = { }, 0, { }, { }
-
-local function hastiming(instance)
- return instance and timers[instance]
-end
-
-local function resettiming(instance)
- timers[instance or "notimer"] = { timing = 0, loadtime = 0 }
-end
-
-local function starttiming(instance)
- local timer = timers[instance or "notimer"]
- if not timer then
- timer = { }
- timers[instance or "notimer"] = timer
- end
- local it = timer.timing
- if not it then
- it = 0
- end
- if it == 0 then
- timer.starttime = clock()
- if not timer.loadtime then
- timer.loadtime = 0
- end
- end
- timer.timing = it + 1
-end
-
-local function stoptiming(instance, report)
- local timer = timers[instance or "notimer"]
- local it = timer.timing
- if it > 1 then
- timer.timing = it - 1
- else
- local starttime = timer.starttime
- if starttime then
- local stoptime = clock()
- local loadtime = stoptime - starttime
- timer.stoptime = stoptime
- timer.loadtime = timer.loadtime + loadtime
- if report then
- statistics.report("load time %0.3f",loadtime)
- end
- timer.timing = 0
- return loadtime
- end
- end
- return 0
-end
-
-local function elapsedtime(instance)
- local timer = timers[instance or "notimer"]
- return format("%0.3f",timer and timer.loadtime or 0)
-end
-
-local function elapsedindeed(instance)
- local timer = timers[instance or "notimer"]
- return (timer and timer.loadtime or 0) > statistics.threshold
-end
-
-local function elapsedseconds(instance,rest) -- returns nil if 0 seconds
- if elapsedindeed(instance) then
- return format("%s seconds %s", elapsedtime(instance),rest or "")
- end
-end
-
-statistics.hastiming = hastiming
-statistics.resettiming = resettiming
-statistics.starttiming = starttiming
-statistics.stoptiming = stoptiming
-statistics.elapsedtime = elapsedtime
-statistics.elapsedindeed = elapsedindeed
-statistics.elapsedseconds = elapsedseconds
-
--- general function
-
-function statistics.register(tag,fnc)
- if statistics.enable and type(fnc) == "function" then
- local rt = registered[tag] or (#statusinfo + 1)
- statusinfo[rt] = { tag, fnc }
- registered[tag] = rt
- if #tag > n then n = #tag end
- end
-end
-
-function statistics.show(reporter)
- if statistics.enable then
- if not reporter then reporter = function(tag,data,n) write_nl(tag .. " " .. data) end end
- -- this code will move
- local register = statistics.register
- register("luatex banner", function()
- return lower(status.banner)
- end)
- register("control sequences", function()
- return format("%s of %s + %s", status.cs_count, status.hash_size,status.hash_extra)
- end)
- register("callbacks", function()
- local total, indirect = status.callbacks or 0, status.indirect_callbacks or 0
- return format("%s direct, %s indirect, %s total", total-indirect, indirect, total)
- end)
- collectgarbage("collect")
- register("current memory usage", statistics.memused)
- register("runtime",statistics.runtime)
- for i=1,#statusinfo do
- local s = statusinfo[i]
- local r = s[2]()
- if r then
- reporter(s[1],r,n)
- end
- end
- write_nl("") -- final newline
- statistics.enable = false
- end
-end
-
-local template, report_statistics, nn = nil, nil, 0 -- we only calcute it once
-
-function statistics.showjobstat(tag,data,n)
- if not logs then
- -- sorry
- elseif type(data) == "table" then
- for i=1,#data do
- statistics.showjobstat(tag,data[i],n)
- end
- else
- if not template or n > nn then
- template, n = format("%%-%ss - %%s",n), nn
- report_statistics = logs.reporter("mkiv lua stats")
- end
- report_statistics(format(template,tag,data))
- end
-end
-
-function statistics.memused() -- no math.round yet -)
- local round = math.round or math.floor
- return format("%s MB (ctx: %s MB)",round(collectgarbage("count")/1000), round(status.luastate_bytes/1000000))
-end
-
-starttiming(statistics)
-
-function statistics.formatruntime(runtime) -- indirect so it can be overloaded and
- return format("%s seconds", runtime) -- indeed that happens in cure-uti.lua
-end
-
-function statistics.runtime()
- stoptiming(statistics)
- return statistics.formatruntime(elapsedtime(statistics))
-end
-
-function statistics.timed(action,report)
- report = report or logs.reporter("system")
- starttiming("run")
- action()
- stoptiming("run")
- report("total runtime: %s",elapsedtime("run"))
-end
-
--- where, not really the best spot for this:
-
-commands = commands or { }
-
-function commands.resettimer(name)
- resettiming(name or "whatever")
- starttiming(name or "whatever")
-end
-
-function commands.elapsedtime(name)
- stoptiming(name or "whatever")
- context(elapsedtime(name or "whatever"))
-end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['trac-set'] = { -- might become util-set.lua
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local type, next, tostring = type, next, tostring
-local concat = table.concat
-local format, find, lower, gsub, escapedpattern = string.format, string.find, string.lower, string.gsub, string.escapedpattern
-local is_boolean = string.is_boolean
-local settings_to_hash = utilities.parsers.settings_to_hash
-local allocate = utilities.storage.allocate
-
-utilities = utilities or { }
-local utilities = utilities
-utilities.setters = utilities.setters or { }
-local setters = utilities.setters
-
-local data = { } -- maybe just local
-
--- We can initialize from the cnf file. This is sort of tricky as
--- later defined setters also need to be initialized then. If set
--- this way, we need to ensure that they are not reset later on.
-
-local trace_initialize = false -- only for testing during development
-
-function setters.initialize(filename,name,values) -- filename only for diagnostics
- local setter = data[name]
- if setter then
- local data = setter.data
- if data then
- for key, value in next, values do
- -- key = gsub(key,"_",".")
- value = is_boolean(value,value)
- local functions = data[key]
- if functions then
- if #functions > 0 and not functions.value then
- if trace_initialize then
- setter.report("executing %s (%s -> %s)",key,filename,tostring(value))
- end
- for i=1,#functions do
- functions[i](value)
- end
- functions.value = value
- else
- if trace_initialize then
- setter.report("skipping %s (%s -> %s)",key,filename,tostring(value))
- end
- end
- else
- -- we do a simple preregistration i.e. not in the
- -- list as it might be an obsolete entry
- functions = { default = value }
- data[key] = functions
- if trace_initialize then
- setter.report("storing %s (%s -> %s)",key,filename,tostring(value))
- end
- end
- end
- return true
- end
- end
-end
-
--- user interface code
-
-local function set(t,what,newvalue)
- local data, done = t.data, t.done
- if type(what) == "string" then
- what = settings_to_hash(what) -- inefficient but ok
- end
- if type(what) ~= "table" then
- return
- end
- if not done then -- catch ... why not set?
- done = { }
- t.done = done
- end
- for w, value in next, what do
- if value == "" then
- value = newvalue
- elseif not value then
- value = false -- catch nil
- else
- value = is_boolean(value,value)
- end
- w = "^" .. escapedpattern(w,true) .. "$" -- new: anchored
- for name, functions in next, data do
- if done[name] then
- -- prevent recursion due to wildcards
- elseif find(name,w) then
- done[name] = true
- for i=1,#functions do
- functions[i](value)
- end
- functions.value = value
- end
- end
- end
-end
-
-local function reset(t)
- for name, functions in next, t.data do
- for i=1,#functions do
- functions[i](false)
- end
- functions.value = false
- end
-end
-
-local function enable(t,what)
- set(t,what,true)
-end
-
-local function disable(t,what)
- local data = t.data
- if not what or what == "" then
- t.done = { }
- reset(t)
- else
- set(t,what,false)
- end
-end
-
-function setters.register(t,what,...)
- local data = t.data
- what = lower(what)
- local functions = data[what]
- if not functions then
- functions = { }
- data[what] = functions
- if trace_initialize then
- t.report("defining %s",what)
- end
- end
- local default = functions.default -- can be set from cnf file
- for _, fnc in next, { ... } do
- local typ = type(fnc)
- if typ == "string" then
- if trace_initialize then
- t.report("coupling %s to %s",what,fnc)
- end
- local s = fnc -- else wrong reference
- fnc = function(value) set(t,s,value) end
- elseif typ ~= "function" then
- fnc = nil
- end
- if fnc then
- functions[#functions+1] = fnc
- -- default: set at command line or in cnf file
- -- value : set in tex run (needed when loading runtime)
- local value = functions.value or default
- if value ~= nil then
- fnc(value)
- functions.value = value
- end
- end
- end
- return false -- so we can use it in an assignment
-end
-
-function setters.enable(t,what)
- local e = t.enable
- t.enable, t.done = enable, { }
- enable(t,what)
- t.enable, t.done = e, { }
-end
-
-function setters.disable(t,what)
- local e = t.disable
- t.disable, t.done = disable, { }
- disable(t,what)
- t.disable, t.done = e, { }
-end
-
-function setters.reset(t)
- t.done = { }
- reset(t)
-end
-
-function setters.list(t) -- pattern
- local list = table.sortedkeys(t.data)
- local user, system = { }, { }
- for l=1,#list do
- local what = list[l]
- if find(what,"^%*") then
- system[#system+1] = what
- else
- user[#user+1] = what
- end
- end
- return user, system
-end
-
-function setters.show(t)
- local category = t.name
- local list = setters.list(t)
- t.report()
- for k=1,#list do
- local name = list[k]
- local functions = t.data[name]
- if functions then
- local value, default, modules = functions.value, functions.default, #functions
- value = value == nil and "unset" or tostring(value)
- default = default == nil and "unset" or tostring(default)
- t.report("%-30s modules: %2i default: %6s value: %6s",name,modules,default,value)
- end
- end
- t.report()
-end
-
--- we could have used a bit of oo and the trackers:enable syntax but
--- there is already a lot of code around using the singular tracker
-
--- we could make this into a module but we also want the rest avaliable
-
-local enable, disable, register, list, show = setters.enable, setters.disable, setters.register, setters.list, setters.show
-
-local function report(setter,...)
- local report = logs and logs.report
- if report then
- report(setter.name,...)
- else -- fallback, as this module is loaded before the logger
- write_nl(format("%-15s : %s\n",setter.name,format(...)))
- end
-end
-
-function setters.new(name)
- local setter -- we need to access it in setter itself
- setter = {
- data = allocate(), -- indexed, but also default and value fields
- name = name,
- report = function(...) report (setter,...) end,
- enable = function(...) enable (setter,...) end,
- disable = function(...) disable (setter,...) end,
- register = function(...) register(setter,...) end,
- list = function(...) list (setter,...) end,
- show = function(...) show (setter,...) end,
- }
- data[name] = setter
- return setter
-end
-
-trackers = setters.new("trackers")
-directives = setters.new("directives")
-experiments = setters.new("experiments")
-
-local t_enable, t_disable, t_report = trackers .enable, trackers .disable, trackers .report
-local d_enable, d_disable, d_report = directives .enable, directives .disable, directives .report
-local e_enable, e_disable, e_report = experiments.enable, experiments.disable, experiments.report
-
--- nice trick: we overload two of the directives related functions with variants that
--- do tracing (itself using a tracker) .. proof of concept
-
-local trace_directives = false local trace_directives = false trackers.register("system.directives", function(v) trace_directives = v end)
-local trace_experiments = false local trace_experiments = false trackers.register("system.experiments", function(v) trace_experiments = v end)
-
-function directives.enable(...)
- if trace_directives then
- d_report("enabling: %s",concat({...}," "))
- end
- d_enable(...)
-end
-
-function directives.disable(...)
- if trace_directives then
- d_report("disabling: %s",concat({...}," "))
- end
- d_disable(...)
-end
-
-function experiments.enable(...)
- if trace_experiments then
- e_report("enabling: %s",concat({...}," "))
- end
- e_enable(...)
-end
-
-function experiments.disable(...)
- if trace_experiments then
- e_report("disabling: %s",concat({...}," "))
- end
- e_disable(...)
-end
-
--- a useful example
-
-directives.register("system.nostatistics", function(v)
- statistics.enable = not v
-end)
-
-directives.register("system.nolibraries", function(v)
- libraries = nil -- we discard this tracing for security
-end)
-
--- experiment
-
-local flags = environment and environment.engineflags
-
-if flags then
- if trackers and flags.trackers then
- setters.initialize("flags","trackers", settings_to_hash(flags.trackers))
- -- t_enable(flags.trackers)
- end
- if directives and flags.directives then
- setters.initialize("flags","directives", settings_to_hash(flags.directives))
- -- d_enable(flags.directives)
- end
-end
-
--- here
-
-if texconfig then
-
- -- this happens too late in ini mode but that is no problem
-
- local function set(k,v)
- v = tonumber(v)
- if v then
- texconfig[k] = v
- end
- end
-
- directives.register("luatex.expanddepth", function(v) set("expand_depth",v) end)
- directives.register("luatex.hashextra", function(v) set("hash_extra",v) end)
- directives.register("luatex.nestsize", function(v) set("nest_size",v) end)
- directives.register("luatex.maxinopen", function(v) set("max_in_open",v) end)
- directives.register("luatex.maxprintline", function(v) set("max_print_line",v) end)
- directives.register("luatex.maxstrings", function(v) set("max_strings",v) end)
- directives.register("luatex.paramsize", function(v) set("param_size",v) end)
- directives.register("luatex.savesize", function(v) set("save_size",v) end)
- directives.register("luatex.stacksize", function(v) set("stack_size",v) end)
-
-end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['trac-log'] = {
- version = 1.001,
- comment = "companion to trac-log.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- todo: less categories, more subcategories (e.g. nodes)
-
-
-local write_nl, write = texio and texio.write_nl or print, texio and texio.write or io.write
-local format, gmatch, find = string.format, string.gmatch, string.find
-local concat, insert, remove = table.concat, table.insert, table.remove
-local escapedpattern = string.escapedpattern
-local texcount = tex and tex.count
-local next, type = next, type
-
-local setmetatableindex = table.setmetatableindex
-
---[[ldx--
-This is a prelude to a more extensive logging module. We no longer
-provide based logging a sparsing is relatively easy anyway.
---ldx]]--
-
-logs = logs or { }
-local logs = logs
-
-local moreinfo = [[
-More information about ConTeXt and the tools that come with it can be found at:
-
-maillist : ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
-webpage : http://www.pragma-ade.nl / http://tex.aanhet.net
-wiki : http://contextgarden.net
-]]
-
--- basic loggers
-
-local function ignore() end
-
-setmetatableindex(logs, function(t,k) t[k] = ignore ; return ignore end)
-
-local report, subreport, status, settarget, setformats, settranslations
-
-local direct, subdirect, writer, pushtarget, poptarget
-
-if tex and (tex.jobname or tex.formatname) then
-
- local valueiskey = { __index = function(t,k) t[k] = k return k end } -- will be helper
-
- local target = "term and log"
-
- logs.flush = io.flush
-
- local formats = { } setmetatable(formats, valueiskey)
- local translations = { } setmetatable(translations,valueiskey)
-
- writer = function(...)
- write_nl(target,...)
- end
-
- newline = function()
- write_nl(target,"\n")
- end
-
- report = function(a,b,c,...)
- if c then
- write_nl(target,format("%-15s > %s\n",translations[a],format(formats[b],c,...)))
- elseif b then
- write_nl(target,format("%-15s > %s\n",translations[a],formats[b]))
- elseif a then
- write_nl(target,format("%-15s >\n", translations[a]))
- else
- write_nl(target,"\n")
- end
- end
-
- direct = function(a,b,c,...)
- if c then
- return format("%-15s > %s",translations[a],format(formats[b],c,...))
- elseif b then
- return format("%-15s > %s",translations[a],formats[b])
- elseif a then
- return format("%-15s >", translations[a])
- else
- return ""
- end
- end
-
- subreport = function(a,s,b,c,...)
- if c then
- write_nl(target,format("%-15s > %s > %s\n",translations[a],translations[s],format(formats[b],c,...)))
- elseif b then
- write_nl(target,format("%-15s > %s > %s\n",translations[a],translations[s],formats[b]))
- elseif a then
- write_nl(target,format("%-15s > %s >\n", translations[a],translations[s]))
- else
- write_nl(target,"\n")
- end
- end
-
- subdirect = function(a,s,b,c,...)
- if c then
- return format("%-15s > %s > %s",translations[a],translations[s],format(formats[b],c,...))
- elseif b then
- return format("%-15s > %s > %s",translations[a],translations[s],formats[b])
- elseif a then
- return format("%-15s > %s >", translations[a],translations[s])
- else
- return ""
- end
- end
-
- status = function(a,b,c,...)
- if c then
- write_nl(target,format("%-15s : %s\n",translations[a],format(formats[b],c,...)))
- elseif b then
- write_nl(target,format("%-15s : %s\n",translations[a],formats[b]))
- elseif a then
- write_nl(target,format("%-15s :\n", translations[a]))
- else
- write_nl(target,"\n")
- end
- end
-
- local targets = {
- logfile = "log",
- log = "log",
- file = "log",
- console = "term",
- terminal = "term",
- both = "term and log",
- }
-
- settarget = function(whereto)
- target = targets[whereto or "both"] or targets.both
- if target == "term" or target == "term and log" then
- logs.flush = io.flush
- else
- logs.flush = ignore
- end
- end
-
- local stack = { }
-
- pushtarget = function(newtarget)
- insert(stack,target)
- settarget(newtarget)
- end
-
- poptarget = function()
- if #stack > 0 then
- settarget(remove(stack))
- end
- end
-
- setformats = function(f)
- formats = f
- end
-
- settranslations = function(t)
- translations = t
- end
-
-else
-
- logs.flush = ignore
-
- writer = write_nl
-
- newline = function()
- write_nl("\n")
- end
-
- report = function(a,b,c,...)
- if c then
- write_nl(format("%-15s | %s",a,format(b,c,...)))
- elseif b then
- write_nl(format("%-15s | %s",a,b))
- elseif a then
- write_nl(format("%-15s |", a))
- else
- write_nl("")
- end
- end
-
- subreport = function(a,sub,b,c,...)
- if c then
- write_nl(format("%-15s | %s | %s",a,sub,format(b,c,...)))
- elseif b then
- write_nl(format("%-15s | %s | %s",a,sub,b))
- elseif a then
- write_nl(format("%-15s | %s |", a,sub))
- else
- write_nl("")
- end
- end
-
- status = function(a,b,c,...) -- not to be used in lua anyway
- if c then
- write_nl(format("%-15s : %s\n",a,format(b,c,...)))
- elseif b then
- write_nl(format("%-15s : %s\n",a,b)) -- b can have %'s
- elseif a then
- write_nl(format("%-15s :\n", a))
- else
- write_nl("\n")
- end
- end
-
- direct = ignore
- subdirect = ignore
-
- settarget = ignore
- pushtarget = ignore
- poptarget = ignore
- setformats = ignore
- settranslations = ignore
-
-end
-
-logs.report = report
-logs.subreport = subreport
-logs.status = status
-logs.settarget = settarget
-logs.pushtarget = pushtarget
-logs.poptarget = poptarget
-logs.setformats = setformats
-logs.settranslations = settranslations
-
-logs.direct = direct
-logs.subdirect = subdirect
-logs.writer = writer
-logs.newline = newline
-
--- installer
-
--- todo: renew (un) locks when a new one is added and wildcard
-
-local data, states = { }, nil
-
-function logs.reporter(category,subcategory)
- local logger = data[category]
- if not logger then
- local state = false
- if states == true then
- state = true
- elseif type(states) == "table" then
- for c, _ in next, states do
- if find(category,c) then
- state = true
- break
- end
- end
- end
- logger = {
- reporters = { },
- state = state,
- }
- data[category] = logger
- end
- local reporter = logger.reporters[subcategory or "default"]
- if not reporter then
- if subcategory then
- reporter = function(...)
- if not logger.state then
- subreport(category,subcategory,...)
- end
- end
- logger.reporters[subcategory] = reporter
- else
- local tag = category
- reporter = function(...)
- if not logger.state then
- report(category,...)
- end
- end
- logger.reporters.default = reporter
- end
- end
- return reporter
-end
-
-logs.new = logs.reporter -- for old times sake
-
--- context specicific: this ends up in the macro stream
-
-local ctxreport = logs.writer
-
-function logs.setmessenger(m)
- ctxreport = m
-end
-
-function logs.messenger(category,subcategory)
- -- we need to avoid catcode mess (todo: fast context)
- if subcategory then
- return function(...)
- ctxreport(subdirect(category,subcategory,...))
- end
- else
- return function(...)
- ctxreport(direct(category,...))
- end
- end
-end
-
--- so far
-
-local function setblocked(category,value)
- if category == true then
- -- lock all
- category, value = "*", true
- elseif category == false then
- -- unlock all
- category, value = "*", false
- elseif value == nil then
- -- lock selective
- value = true
- end
- if category == "*" then
- states = value
- for k, v in next, data do
- v.state = value
- end
- else
- states = utilities.parsers.settings_to_hash(category)
- for c, _ in next, states do
- if data[c] then
- v.state = value
- else
- c = escapedpattern(c,true)
- for k, v in next, data do
- if find(k,c) then
- v.state = value
- end
- end
- end
- end
- end
-end
-
-function logs.disable(category,value)
- setblocked(category,value == nil and true or value)
-end
-
-function logs.enable(category)
- setblocked(category,false)
-end
-
-function logs.categories()
- return table.sortedkeys(data)
-end
-
-function logs.show()
- local n, c, s, max = 0, 0, 0, 0
- for category, v in table.sortedpairs(data) do
- n = n + 1
- local state = v.state
- local reporters = v.reporters
- local nc = #category
- if nc > c then
- c = nc
- end
- for subcategory, _ in next, reporters do
- local ns = #subcategory
- if ns > c then
- s = ns
- end
- local m = nc + ns
- if m > max then
- max = m
- end
- end
- local subcategories = concat(table.sortedkeys(reporters),", ")
- if state == true then
- state = "disabled"
- elseif state == false then
- state = "enabled"
- else
- state = "unknown"
- end
- -- no new here
- report("logging","category: '%s', subcategories: '%s', state: '%s'",category,subcategories,state)
- end
- report("logging","categories: %s, max category: %s, max subcategory: %s, max combined: %s",n,c,s,max)
-end
-
-directives.register("logs.blocked", function(v)
- setblocked(v,true)
-end)
-
-directives.register("logs.target", function(v)
- settarget(v)
-end)
-
--- tex specific loggers (might move elsewhere)
-
-local report_pages = logs.reporter("pages") -- not needed but saves checking when we grep for it
-
-local real, user, sub
-
-function logs.start_page_number()
- real, user, sub = texcount.realpageno, texcount.userpageno, texcount.subpageno
--- real, user, sub = 0, 0, 0
-end
-
-local timing = false
-local starttime = nil
-local lasttime = nil
-
-trackers.register("pages.timing", function(v) -- only for myself (diagnostics)
- starttime = os.clock()
- timing = true
-end)
-
-function logs.stop_page_number() -- the first page can includes the initialization so we omit this in average
- if timing then
- local elapsed, average
- local stoptime = os.clock()
- if not lasttime or real < 2 then
- elapsed = stoptime
- average = stoptime
- starttime = stoptime
- else
- elapsed = stoptime - lasttime
- average = (stoptime - starttime) / (real - 1)
- end
- lasttime = stoptime
- if real > 0 then
- if user > 0 then
- if sub > 0 then
- report_pages("flushing realpage %s, userpage %s, subpage %s, time %0.04f / %0.04f",real,user,sub,elapsed,average)
- else
- report_pages("flushing realpage %s, userpage %s, time %0.04f / %0.04f",real,user,elapsed,average)
- end
- else
- report_pages("flushing realpage %s, time %0.04f / %0.04f",real,elapsed,average)
- end
- else
- report_pages("flushing page, time %0.04f / %0.04f",elapsed,average)
- end
- else
- if real > 0 then
- if user > 0 then
- if sub > 0 then
- report_pages("flushing realpage %s, userpage %s, subpage %s",real,user,sub)
- else
- report_pages("flushing realpage %s, userpage %s",real,user)
- end
- else
- report_pages("flushing realpage %s",real)
- end
- else
- report_pages("flushing page")
- end
- end
- logs.flush()
-end
-
-logs.report_job_stat = statistics and statistics.showjobstat
-
-local report_files = logs.reporter("files")
-
-local nesting = 0
-local verbose = false
-local hasscheme = url.hasscheme
-
--- we don't have show_open and show_close callbacks yet
-
-function logs.show_open(name)
- -- if hasscheme(name) ~= "virtual" then
- -- if verbose then
- -- nesting = nesting + 1
- -- report_files("level %s, opening %s",nesting,name)
- -- else
- -- write(format("(%s",name)) -- tex adds a space
- -- end
- -- end
-end
-
-function logs.show_close(name)
- -- if hasscheme(name) ~= "virtual" then
- -- if verbose then
- -- report_files("level %s, closing %s",nesting,name)
- -- nesting = nesting - 1
- -- else
- -- write(")") -- tex adds a space
- -- end
- -- end
-end
-
-function logs.show_load(name)
- -- if hasscheme(name) ~= "virtual" then
- -- if verbose then
- -- report_files("level %s, loading %s",nesting+1,name)
- -- else
- -- write(format("(%s)",name))
- -- end
- -- end
-end
-
--- there may be scripts out there using this:
-
-local simple = logs.reporter("comment")
-
-logs.simple = simple
-logs.simpleline = simple
-
--- obsolete
-
-function logs.setprogram () end -- obsolete
-function logs.extendbanner() end -- obsolete
-function logs.reportlines () end -- obsolete
-function logs.reportbanner() end -- obsolete
-function logs.reportline () end -- obsolete
-function logs.simplelines () end -- obsolete
-function logs.help () end -- obsolete
-
--- applications
-
-local function reportlines(t,str)
- if str then
- for line in gmatch(str,"(.-)[\n\r]") do
- t.report(line)
- end
- end
-end
-
-local function reportbanner(t)
- local banner = t.banner
- if banner then
- t.report(banner)
- t.report()
- end
-end
-
-local function reportversion(t)
- local banner = t.banner
- if banner then
- t.report(banner)
- end
-end
-
-local function reporthelp(t,...)
- local helpinfo = t.helpinfo
- if type(helpinfo) == "string" then
- reportlines(t,helpinfo)
- elseif type(helpinfo) == "table" then
- local tags = { ... }
- for i=1,#tags do
- reportlines(t,t.helpinfo[tags[i]])
- if i < #tags then
- t.report()
- end
- end
- end
-end
-
-local function reportinfo(t)
- t.report()
- reportlines(t,moreinfo)
-end
-
-function logs.application(t)
- t.name = t.name or "unknown"
- t.banner = t.banner
- t.report = logs.reporter(t.name)
- t.help = function(...) reportbanner(t) ; reporthelp(t,...) ; reportinfo(t) end
- t.identify = function() reportbanner(t) end
- t.version = function() reportversion(t) end
- return t
-end
-
--- somewhat special
-
--- logging to a file
-
-
-function logs.system(whereto,process,jobname,category,...)
- local message = format("%s %s => %s => %s => %s\r",os.date("%d/%m/%y %H:%m:%S"),process,jobname,category,format(...))
- for i=1,10 do
- local f = io.open(whereto,"a") -- we can consider keepint the file open
- if f then
- f:write(message)
- f:close()
- break
- else
- sleep(0.1)
- end
- end
-end
-
-local report_system = logs.reporter("system","logs")
-
-function logs.obsolete(old,new)
- local o = loadstring("return " .. new)()
- if type(o) == "function" then
- return function(...)
- report_system("function %s is obsolete, use %s",old,new)
- loadstring(old .. "=" .. new .. " return ".. old)()(...)
- end
- elseif type(o) == "table" then
- local t, m = { }, { }
- m.__index = function(t,k)
- report_system("table %s is obsolete, use %s",old,new)
- m.__index, m.__newindex = o, o
- return o[k]
- end
- m.__newindex = function(t,k,v)
- report_system("table %s is obsolete, use %s",old,new)
- m.__index, m.__newindex = o, o
- o[k] = v
- end
- if libraries then
- libraries.obsolete[old] = t -- true
- end
- setmetatable(t,m)
- return t
- end
-end
-
-if utilities then
- utilities.report = report_system
-end
-
-if tex and tex.error then
- function logs.texerrormessage(...) -- for the moment we put this function here
- tex.error(format(...), { })
- end
-else
- function logs.texerrormessage(...)
- print(format(...))
- end
-end
-
--- do we still need io.flush then?
-
-io.stdout:setvbuf('no')
-io.stderr:setvbuf('no')
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['trac-pro'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local getmetatable, setmetatable, rawset, type = getmetatable, setmetatable, rawset, type
-
--- The protection implemented here is probably not that tight but good enough to catch
--- problems due to naive usage.
---
--- There's a more extensive version (trac-xxx.lua) that supports nesting.
---
--- This will change when we have _ENV in lua 5.2+
-
-local trace_namespaces = false trackers.register("system.namespaces", function(v) trace_namespaces = v end)
-
-local report_system = logs.reporter("system","protection")
-
-namespaces = namespaces or { }
-local namespaces = namespaces
-
-local registered = { }
-
-local function report_index(k,name)
- if trace_namespaces then
- report_system("reference to '%s' in protected namespace '%s', %s",k,name,debug.traceback())
- else
- report_system("reference to '%s' in protected namespace '%s'",k,name)
- end
-end
-
-local function report_newindex(k,name)
- if trace_namespaces then
- report_system("assignment to '%s' in protected namespace '%s', %s",k,name,debug.traceback())
- else
- report_system("assignment to '%s' in protected namespace '%s'",k,name)
- end
-end
-
-local function register(name)
- local data = name == "global" and _G or _G[name]
- if not data then
- return -- error
- end
- registered[name] = data
- local m = getmetatable(data)
- if not m then
- m = { }
- setmetatable(data,m)
- end
- local index, newindex = { }, { }
- m.__saved__index = m.__index
- m.__no__index = function(t,k)
- if not index[k] then
- index[k] = true
- report_index(k,name)
- end
- return nil
- end
- m.__saved__newindex = m.__newindex
- m.__no__newindex = function(t,k,v)
- if not newindex[k] then
- newindex[k] = true
- report_newindex(k,name)
- end
- rawset(t,k,v)
- end
- m.__protection__depth = 0
-end
-
-local function private(name) -- maybe save name
- local data = registered[name]
- if not data then
- data = _G[name]
- if not data then
- data = { }
- _G[name] = data
- end
- register(name)
- end
- return data
-end
-
-local function protect(name)
- local data = registered[name]
- if not data then
- return
- end
- local m = getmetatable(data)
- local pd = m.__protection__depth
- if pd > 0 then
- m.__protection__depth = pd + 1
- else
- m.__save_d_index, m.__saved__newindex = m.__index, m.__newindex
- m.__index, m.__newindex = m.__no__index, m.__no__newindex
- m.__protection__depth = 1
- end
-end
-
-local function unprotect(name)
- local data = registered[name]
- if not data then
- return
- end
- local m = getmetatable(data)
- local pd = m.__protection__depth
- if pd > 1 then
- m.__protection__depth = pd - 1
- else
- m.__index, m.__newindex = m.__saved__index, m.__saved__newindex
- m.__protection__depth = 0
- end
-end
-
-local function protectall()
- for name, _ in next, registered do
- if name ~= "global" then
- protect(name)
- end
- end
-end
-
-local function unprotectall()
- for name, _ in next, registered do
- if name ~= "global" then
- unprotect(name)
- end
- end
-end
-
-namespaces.register = register -- register when defined
-namespaces.private = private -- allocate and register if needed
-namespaces.protect = protect
-namespaces.unprotect = unprotect
-namespaces.protectall = protectall
-namespaces.unprotectall = unprotectall
-
-namespaces.private("namespaces") registered = { } register("global") -- unreachable
-
-directives.register("system.protect", function(v)
- if v then
- protectall()
- else
- unprotectall()
- end
-end)
-
-directives.register("system.checkglobals", function(v)
- if v then
- report_system("enabling global namespace guard")
- protect("global")
- else
- report_system("disabling global namespace guard")
- unprotect("global")
- end
-end)
-
--- dummy section (will go to luat-dum.lua)
-
-
-
-
-
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['luat-env'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- A former version provided functionality for non embeded core
--- scripts i.e. runtime library loading. Given the amount of
--- Lua code we use now, this no longer makes sense. Much of this
--- evolved before bytecode arrays were available and so a lot of
--- code has disappeared already.
-
-local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
-
-local report_lua = logs.reporter("resolvers","lua")
-
-local allocate, mark = utilities.storage.allocate, utilities.storage.mark
-
-local format, sub, match, gsub, find = string.format, string.sub, string.match, string.gsub, string.find
-local unquoted, quoted = string.unquoted, string.quoted
-local concat = table.concat
-
--- precautions
-
-os.setlocale(nil,nil) -- useless feature and even dangerous in luatex
-
-function os.setlocale()
- -- no way you can mess with it
-end
-
--- dirty tricks
-
-if arg and (arg[0] == 'luatex' or arg[0] == 'luatex.exe') and arg[1] == "--luaonly" then
- arg[-1] = arg[0]
- arg[ 0] = arg[2]
- for k=3,#arg do
- arg[k-2] = arg[k]
- end
- arg[#arg] = nil -- last
- arg[#arg] = nil -- pre-last
-end
-
--- environment
-
-environment = environment or { }
-local environment = environment
-
-environment.arguments = allocate()
-environment.files = allocate()
-environment.sortedflags = nil
-
-local mt = {
- __index = function(_,k)
- if k == "version" then
- local version = tex.toks and tex.toks.contextversiontoks
- if version and version ~= "" then
- rawset(environment,"version",version)
- return version
- else
- return "unknown"
- end
- elseif k == "jobname" or k == "formatname" then
- local name = tex and tex[k]
- if name or name== "" then
- rawset(environment,k,name)
- return name
- else
- return "unknown"
- end
- elseif k == "outputfilename" then
- local name = environment.jobname
- rawset(environment,k,name)
- return name
- end
- end
-}
-
-setmetatable(environment,mt)
-
-function environment.initializearguments(arg)
- local arguments, files = { }, { }
- environment.arguments, environment.files, environment.sortedflags = arguments, files, nil
- for index=1,#arg do
- local argument = arg[index]
- if index > 0 then
- local flag, value = match(argument,"^%-+(.-)=(.-)$")
- if flag then
- arguments[flag] = unquoted(value or "")
- else
- flag = match(argument,"^%-+(.+)")
- if flag then
- arguments[flag] = true
- else
- files[#files+1] = argument
- end
- end
- end
- end
- environment.ownname = environment.ownname or arg[0] or 'unknown.lua'
-end
-
-function environment.setargument(name,value)
- environment.arguments[name] = value
-end
-
--- todo: defaults, better checks e.g on type (boolean versus string)
---
--- tricky: too many hits when we support partials unless we add
--- a registration of arguments so from now on we have 'partial'
-
-function environment.argument(name,partial)
- local arguments, sortedflags = environment.arguments, environment.sortedflags
- if arguments[name] then
- return arguments[name]
- elseif partial then
- if not sortedflags then
- sortedflags = allocate(table.sortedkeys(arguments))
- for k=1,#sortedflags do
- sortedflags[k] = "^" .. sortedflags[k]
- end
- environment.sortedflags = sortedflags
- end
- -- example of potential clash: ^mode ^modefile
- for k=1,#sortedflags do
- local v = sortedflags[k]
- if find(name,v) then
- return arguments[sub(v,2,#v)]
- end
- end
- end
- return nil
-end
-
-function environment.splitarguments(separator) -- rather special, cut-off before separator
- local done, before, after = false, { }, { }
- local originalarguments = environment.originalarguments
- for k=1,#originalarguments do
- local v = originalarguments[k]
- if not done and v == separator then
- done = true
- elseif done then
- after[#after+1] = v
- else
- before[#before+1] = v
- end
- end
- return before, after
-end
-
-function environment.reconstructcommandline(arg,noquote)
- arg = arg or environment.originalarguments
- if noquote and #arg == 1 then
- -- we could just do: return unquoted(resolvers.resolve(arg[i]))
- local a = arg[1]
- a = resolvers.resolve(a)
- a = unquoted(a)
- return a
- elseif #arg > 0 then
- local result = { }
- for i=1,#arg do
- -- we could just do: result[#result+1] = format("%q",unquoted(resolvers.resolve(arg[i])))
- local a = arg[i]
- a = resolvers.resolve(a)
- a = unquoted(a)
- a = gsub(a,'"','\\"') -- tricky
- if find(a," ") then
- result[#result+1] = quoted(a)
- else
- result[#result+1] = a
- end
- end
- return concat(result," ")
- else
- return ""
- end
-end
-
-
-if arg then
-
- -- new, reconstruct quoted snippets (maybe better just remove the " then and add them later)
- local newarg, instring = { }, false
-
- for index=1,#arg do
- local argument = arg[index]
- if find(argument,"^\"") then
- newarg[#newarg+1] = gsub(argument,"^\"","")
- if not find(argument,"\"$") then
- instring = true
- end
- elseif find(argument,"\"$") then
- newarg[#newarg] = newarg[#newarg] .. " " .. gsub(argument,"\"$","")
- instring = false
- elseif instring then
- newarg[#newarg] = newarg[#newarg] .. " " .. argument
- else
- newarg[#newarg+1] = argument
- end
- end
- for i=1,-5,-1 do
- newarg[i] = arg[i]
- end
-
- environment.initializearguments(newarg)
-
- environment.originalarguments = mark(newarg)
- environment.rawarguments = mark(arg)
-
- arg = { } -- prevent duplicate handling
-
-end
-
--- weird place ... depends on a not yet loaded module
-
-function environment.texfile(filename)
- return resolvers.findfile(filename,'tex')
-end
-
-function environment.luafile(filename)
- local resolved = resolvers.findfile(filename,'tex') or ""
- if resolved ~= "" then
- return resolved
- end
- resolved = resolvers.findfile(filename,'texmfscripts') or ""
- if resolved ~= "" then
- return resolved
- end
- return resolvers.findfile(filename,'luatexlibs') or ""
-end
-
-environment.loadedluacode = loadfile -- can be overloaded
-
-function environment.luafilechunk(filename,silent) -- used for loading lua bytecode in the format
- filename = file.replacesuffix(filename, "lua")
- local fullname = environment.luafile(filename)
- if fullname and fullname ~= "" then
- local data = environment.loadedluacode(fullname)
- if trace_locating then
- report_lua("loading file %s%s", fullname, not data and " failed" or "")
- elseif not silent then
- texio.write("<",data and "+ " or "- ",fullname,">")
- end
- return data
- else
- if trace_locating then
- report_lua("unknown file %s", filename)
- end
- return nil
- end
-end
-
--- the next ones can use the previous ones / combine
-
-function environment.loadluafile(filename, version)
- local lucname, luaname, chunk
- local basename = file.removesuffix(filename)
- if basename == filename then
- lucname, luaname = basename .. ".luc", basename .. ".lua"
- else
- lucname, luaname = nil, basename -- forced suffix
- end
- -- when not overloaded by explicit suffix we look for a luc file first
- local fullname = (lucname and environment.luafile(lucname)) or ""
- if fullname ~= "" then
- if trace_locating then
- report_lua("loading %s", fullname)
- end
- chunk = loadfile(fullname) -- this way we don't need a file exists check
- end
- if chunk then
- assert(chunk)()
- if version then
- -- we check of the version number of this chunk matches
- local v = version -- can be nil
- if modules and modules[filename] then
- v = modules[filename].version -- new method
- elseif versions and versions[filename] then
- v = versions[filename] -- old method
- end
- if v == version then
- return true
- else
- if trace_locating then
- report_lua("version mismatch for %s: lua=%s, luc=%s", filename, v, version)
- end
- environment.loadluafile(filename)
- end
- else
- return true
- end
- end
- fullname = (luaname and environment.luafile(luaname)) or ""
- if fullname ~= "" then
- if trace_locating then
- report_lua("loading %s", fullname)
- end
- chunk = loadfile(fullname) -- this way we don't need a file exists check
- if not chunk then
- if trace_locating then
- report_lua("unknown file %s", filename)
- end
- else
- assert(chunk)()
- return true
- end
- end
- return false
-end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['lxml-tab'] = {
- version = 1.001,
- comment = "this module is the basis for the lxml-* ones",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- this module needs a cleanup: check latest lpeg, passing args, (sub)grammar, etc etc
--- stripping spaces from e.g. cont-en.xml saves .2 sec runtime so it's not worth the
--- trouble
-
--- todo: when serializing optionally remap named entities to hex (if known in char-ent.lua)
--- maybe when letter -> utf, else name .. then we need an option to the serializer .. a bit
--- of work so we delay this till we cleanup
-
-local trace_entities = false trackers.register("xml.entities", function(v) trace_entities = v end)
-
-local report_xml = logs and logs.reporter("xml","core") or function(...) print(format(...)) end
-
---[[ldx--
-The parser used here is inspired by the variant discussed in the lua book, but
-handles comment and processing instructions, has a different structure, provides
-parent access; a first version used different trickery but was less optimized to we
-went this route. First we had a find based parser, now we have an based one.
-The find based parser can be found in l-xml-edu.lua along with other older code.
-
-Beware, the interface may change. For instance at, ns, tg, dt may get more
-verbose names. Once the code is stable we will also remove some tracing and
-optimize the code.
-
-I might even decide to reimplement the parser using the latest trickery
-as the current variant was written when showed up and it's easier now to
-build tables in one go.
---ldx]]--
-
-xml = xml or { }
-local xml = xml
-
-
-local utf = unicode.utf8
-local concat, remove, insert = table.concat, table.remove, table.insert
-local type, next, setmetatable, getmetatable, tonumber = type, next, setmetatable, getmetatable, tonumber
-local format, lower, find, match, gsub = string.format, string.lower, string.find, string.match, string.gsub
-local utfchar, utffind, utfgsub = utf.char, utf.find, utf.gsub
-local lpegmatch = lpeg.match
-local P, S, R, C, V, C, Cs = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.V, lpeg.C, lpeg.Cs
-
---[[ldx--
-First a hack to enable namespace resolving. A namespace is characterized by
-a . The following function associates a namespace prefix with a
-pattern. We use , which in this case is more than twice as fast as a
-find based solution where we loop over an array of patterns. Less code and
-much cleaner.
---ldx]]--
-
-xml.xmlns = xml.xmlns or { }
-
-local check = P(false)
-local parse = check
-
---[[ldx--
-The next function associates a namespace prefix with an . This
-normally happens independent of parsing.
-
-
-xml.registerns("mml","mathml")
-
---ldx]]--
-
-function xml.registerns(namespace, pattern) -- pattern can be an lpeg
- check = check + C(P(lower(pattern))) / namespace
- parse = P { P(check) + 1 * V(1) }
-end
-
---[[ldx--
-The next function also registers a namespace, but this time we map a
-given namespace prefix onto a registered one, using the given
- . This used for attributes like xmlns:m .
-
-
-xml.checkns("m","http://www.w3.org/mathml")
-
---ldx]]--
-
-function xml.checkns(namespace,url)
- local ns = lpegmatch(parse,lower(url))
- if ns and namespace ~= ns then
- xml.xmlns[namespace] = ns
- end
-end
-
---[[ldx--
-Next we provide a way to turn an into a registered
-namespace. This used for the xmlns attribute.
-
-
-resolvedns = xml.resolvens("http://www.w3.org/mathml")
-
-
-This returns mml .
---ldx]]--
-
-function xml.resolvens(url)
- return lpegmatch(parse,lower(url)) or ""
-end
-
---[[ldx--
-A namespace in an element can be remapped onto the registered
-one efficiently by using the xml.xmlns table.
---ldx]]--
-
---[[ldx--
-This version uses . We follow the same approach as before, stack and top and
-such. This version is about twice as fast which is mostly due to the fact that
-we don't have to prepare the stream for cdata, doctype etc etc. This variant is
-is dedicated to Luigi Scarso, who challenged me with 40 megabyte files that
-took 12.5 seconds to load (1.5 for file io and the rest for tree building). With
-the implementation we got that down to less 7.3 seconds. Loading the 14
- interface definition files (2.6 meg) went down from 1.05 seconds to 0.55.
-
-Next comes the parser. The rather messy doctype definition comes in many
-disguises so it is no surprice that later on have to dedicate quite some
- code to it.
-
-
-
-
-
-
-
-
-
-
-The code may look a bit complex but this is mostly due to the fact that we
-resolve namespaces and attach metatables. There is only one public function:
-
-
-local x = xml.convert(somestring)
-
-
-An optional second boolean argument tells this function not to create a root
-element.
-
-Valid entities are:
-
-
-
-
-
-
---ldx]]--
-
--- not just one big nested table capture (lpeg overflow)
-
-local nsremap, resolvens = xml.xmlns, xml.resolvens
-
-local stack = { }
-local top = { }
-local dt = { }
-local at = { }
-local xmlns = { }
-local errorstr = nil
-local entities = { }
-local strip = false
-local cleanup = false
-local utfize = false
-local resolve_predefined = false
-local unify_predefined = false
-
-local dcache = { }
-local hcache = { }
-local acache = { }
-
-local mt = { }
-
-local function initialize_mt(root)
- mt = { __index = root } -- will be redefined later
-end
-
-function xml.setproperty(root,k,v)
- getmetatable(root).__index[k] = v
-end
-
-function xml.checkerror(top,toclose)
- return "" -- can be set
-end
-
-local function add_attribute(namespace,tag,value)
- if cleanup and #value > 0 then
- value = cleanup(value) -- new
- end
- if tag == "xmlns" then
- xmlns[#xmlns+1] = resolvens(value)
- at[tag] = value
- elseif namespace == "" then
- at[tag] = value
- elseif namespace == "xmlns" then
- xml.checkns(tag,value)
- at["xmlns:" .. tag] = value
- else
- -- for the moment this way:
- at[namespace .. ":" .. tag] = value
- end
-end
-
-local function add_empty(spacing, namespace, tag)
- if #spacing > 0 then
- dt[#dt+1] = spacing
- end
- local resolved = (namespace == "" and xmlns[#xmlns]) or nsremap[namespace] or namespace
- top = stack[#stack]
- dt = top.dt
- local t = { ns=namespace or "", rn=resolved, tg=tag, at=at, dt={}, __p__ = top }
- dt[#dt+1] = t
- setmetatable(t, mt)
- if at.xmlns then
- remove(xmlns)
- end
- at = { }
-end
-
-local function add_begin(spacing, namespace, tag)
- if #spacing > 0 then
- dt[#dt+1] = spacing
- end
- local resolved = (namespace == "" and xmlns[#xmlns]) or nsremap[namespace] or namespace
- top = { ns=namespace or "", rn=resolved, tg=tag, at=at, dt={}, __p__ = stack[#stack] }
- setmetatable(top, mt)
- dt = top.dt
- stack[#stack+1] = top
- at = { }
-end
-
-local function add_end(spacing, namespace, tag)
- if #spacing > 0 then
- dt[#dt+1] = spacing
- end
- local toclose = remove(stack)
- top = stack[#stack]
- if #stack < 1 then
- errorstr = format("nothing to close with %s %s", tag, xml.checkerror(top,toclose) or "")
- elseif toclose.tg ~= tag then -- no namespace check
- errorstr = format("unable to close %s with %s %s", toclose.tg, tag, xml.checkerror(top,toclose) or "")
- end
- dt = top.dt
- dt[#dt+1] = toclose
- -- dt[0] = top -- nasty circular reference when serializing table
- if toclose.at.xmlns then
- remove(xmlns)
- end
-end
-
-local function add_text(text)
- if cleanup and #text > 0 then
- dt[#dt+1] = cleanup(text)
- else
- dt[#dt+1] = text
- end
-end
-
-local function add_special(what, spacing, text)
- if #spacing > 0 then
- dt[#dt+1] = spacing
- end
- if strip and (what == "@cm@" or what == "@dt@") then
- -- forget it
- else
- dt[#dt+1] = { special=true, ns="", tg=what, dt={ text } }
- end
-end
-
-local function set_message(txt)
- errorstr = "garbage at the end of the file: " .. gsub(txt,"([ \n\r\t]*)","")
-end
-
-local reported_attribute_errors = { }
-
-local function attribute_value_error(str)
- if not reported_attribute_errors[str] then
- report_xml("invalid attribute value: %q",str)
- reported_attribute_errors[str] = true
- at._error_ = str
- end
- return str
-end
-
-local function attribute_specification_error(str)
- if not reported_attribute_errors[str] then
- report_xml("invalid attribute specification: %q",str)
- reported_attribute_errors[str] = true
- at._error_ = str
- end
- return str
-end
-
-xml.placeholders = {
- unknown_dec_entity = function(str) return (str == "" and "&error;") or format("&%s;",str) end,
- unknown_hex_entity = function(str) return format("%s;",str) end,
- unknown_any_entity = function(str) return format("%s;",str) end,
-}
-
-local placeholders = xml.placeholders
-
-local function fromhex(s)
- local n = tonumber(s,16)
- if n then
- return utfchar(n)
- else
- return format("h:%s",s), true
- end
-end
-
-local function fromdec(s)
- local n = tonumber(s)
- if n then
- return utfchar(n)
- else
- return format("d:%s",s), true
- end
-end
-
--- one level expansion (simple case), no checking done
-
-local rest = (1-P(";"))^0
-local many = P(1)^0
-
-local parsedentity =
- P("&") * (P("#x")*(rest/fromhex) + P("#")*(rest/fromdec)) * P(";") * P(-1) +
- (P("#x")*(many/fromhex) + P("#")*(many/fromdec))
-
--- parsing in the xml file
-
-local predefined_unified = {
- [38] = "&",
- [42] = """,
- [47] = "'",
- [74] = "<",
- [76] = ">",
-}
-
-local predefined_simplified = {
- [38] = "&", amp = "&",
- [42] = '"', quot = '"',
- [47] = "'", apos = "'",
- [74] = "<", lt = "<",
- [76] = ">", gt = ">",
-}
-
-local nofprivates = 0xF0000 -- shared but seldom used
-
-local privates_u = { -- unescaped
- [ [[&]] ] = "&",
- [ [["]] ] = """,
- [ [[']] ] = "'",
- [ [[<]] ] = "<",
- [ [[>]] ] = ">",
-}
-
-local privates_p = {
-}
-
-local privates_n = {
- -- keeps track of defined ones
-}
-
-local function escaped(s)
- if s == "" then
- return ""
- else -- if utffind(s,privates_u) then
- return (utfgsub(s,".",privates_u))
- -- else
- -- return s
- end
-end
-
-local function unescaped(s)
- local p = privates_n[s]
- if not p then
- nofprivates = nofprivates + 1
- p = utfchar(nofprivates)
- privates_n[s] = p
- s = "&" .. s .. ";" -- todo: use char-ent to map to hex
- privates_u[p] = s
- privates_p[p] = s
- end
- return p
-end
-
-local function unprivatized(s,resolve)
- if s == "" then
- return ""
- else
- return (utfgsub(s,".",privates_p))
- end
-end
-
-xml.privatetoken = unescaped
-xml.unprivatized = unprivatized
-xml.privatecodes = privates_n
-
-local function handle_hex_entity(str)
- local h = hcache[str]
- if not h then
- local n = tonumber(str,16)
- h = unify_predefined and predefined_unified[n]
- if h then
- if trace_entities then
- report_xml("utfize, converting hex entity %s; into %s",str,h)
- end
- elseif utfize then
- h = (n and utfchar(n)) or xml.unknown_hex_entity(str) or ""
- if not n then
- report_xml("utfize, ignoring hex entity %s;",str)
- elseif trace_entities then
- report_xml("utfize, converting hex entity %s; into %s",str,h)
- end
- else
- if trace_entities then
- report_xml("found entity %s;",str)
- end
- h = "" .. str .. ";"
- end
- hcache[str] = h
- end
- return h
-end
-
-local function handle_dec_entity(str)
- local d = dcache[str]
- if not d then
- local n = tonumber(str)
- d = unify_predefined and predefined_unified[n]
- if d then
- if trace_entities then
- report_xml("utfize, converting dec entity %s; into %s",str,d)
- end
- elseif utfize then
- d = (n and utfchar(n)) or placeholders.unknown_dec_entity(str) or ""
- if not n then
- report_xml("utfize, ignoring dec entity %s;",str)
- elseif trace_entities then
- report_xml("utfize, converting dec entity %s; into %s",str,d)
- end
- else
- if trace_entities then
- report_xml("found entity %s;",str)
- end
- d = "" .. str .. ";"
- end
- dcache[str] = d
- end
- return d
-end
-
-xml.parsedentitylpeg = parsedentity
-
-local function handle_any_entity(str)
- if resolve then
- local a = acache[str] -- per instance ! todo
- if not a then
- a = resolve_predefined and predefined_simplified[str]
- if a then
- if trace_entities then
- report_xml("resolved entity &%s; -> %s (predefined)",str,a)
- end
- else
- if type(resolve) == "function" then
- a = resolve(str) or entities[str]
- else
- a = entities[str]
- end
- if a then
- if type(a) == "function" then
- if trace_entities then
- report_xml("expanding entity &%s; (function)",str)
- end
- a = a(str) or ""
- end
- a = lpegmatch(parsedentity,a) or a -- for nested
- if trace_entities then
- report_xml("resolved entity &%s; -> %s (internal)",str,a)
- end
- else
- local unknown_any_entity = placeholders.unknown_any_entity
- if unknown_any_entity then
- a = unknown_any_entity(str) or ""
- end
- if a then
- if trace_entities then
- report_xml("resolved entity &%s; -> %s (external)",str,a)
- end
- else
- if trace_entities then
- report_xml("keeping entity &%s;",str)
- end
- if str == "" then
- a = "&error;"
- else
- a = "&" .. str .. ";"
- end
- end
- end
- end
- acache[str] = a
- elseif trace_entities then
- if not acache[str] then
- report_xml("converting entity &%s; into %s",str,a)
- acache[str] = a
- end
- end
- return a
- else
- local a = acache[str]
- if not a then
- a = resolve_predefined and predefined_simplified[str]
- if a then
- -- one of the predefined
- acache[str] = a
- if trace_entities then
- report_xml("entity &%s; becomes %s",str,tostring(a))
- end
- elseif str == "" then
- if trace_entities then
- report_xml("invalid entity &%s;",str)
- end
- a = "&error;"
- acache[str] = a
- else
- if trace_entities then
- report_xml("entity &%s; is made private",str)
- end
- -- a = "&" .. str .. ";"
- a = unescaped(str)
- acache[str] = a
- end
- end
- return a
- end
-end
-
-local function handle_end_entity(chr)
- report_xml("error in entity, %q found instead of ';'",chr)
-end
-
-local space = S(' \r\n\t')
-local open = P('<')
-local close = P('>')
-local squote = S("'")
-local dquote = S('"')
-local equal = P('=')
-local slash = P('/')
-local colon = P(':')
-local semicolon = P(';')
-local ampersand = P('&')
-local valid = R('az', 'AZ', '09') + S('_-.')
-local name_yes = C(valid^1) * colon * C(valid^1)
-local name_nop = C(P(true)) * C(valid^1)
-local name = name_yes + name_nop
-local utfbom = lpeg.patterns.utfbom -- no capture
-local spacing = C(space^0)
-
------ entitycontent = (1-open-semicolon)^0
-local anyentitycontent = (1-open-semicolon-space-close)^0
-local hexentitycontent = R("AF","af","09")^0
-local decentitycontent = R("09")^0
-local parsedentity = P("#")/"" * (
- P("x")/"" * (hexentitycontent/handle_hex_entity) +
- (decentitycontent/handle_dec_entity)
- ) + (anyentitycontent/handle_any_entity)
-local entity = ampersand/"" * parsedentity * ( (semicolon/"") + #(P(1)/handle_end_entity))
-
-local text_unparsed = C((1-open)^1)
-local text_parsed = Cs(((1-open-ampersand)^1 + entity)^1)
-
-local somespace = space^1
-local optionalspace = space^0
-
------ value = (squote * C((1 - squote)^0) * squote) + (dquote * C((1 - dquote)^0) * dquote) -- ampersand and < also invalid in value
-local value = (squote * Cs((entity + (1 - squote))^0) * squote) + (dquote * Cs((entity + (1 - dquote))^0) * dquote) -- ampersand and < also invalid in value
-
-local endofattributes = slash * close + close -- recovery of flacky html
-local whatever = space * name * optionalspace * equal
------ wrongvalue = C(P(1-whatever-close)^1 + P(1-close)^1) / attribute_value_error
------ wrongvalue = C(P(1-whatever-endofattributes)^1 + P(1-endofattributes)^1) / attribute_value_error
------ wrongvalue = C(P(1-space-endofattributes)^1) / attribute_value_error
-local wrongvalue = Cs(P(entity + (1-space-endofattributes))^1) / attribute_value_error
-
-local attributevalue = value + wrongvalue
-
-local attribute = (somespace * name * optionalspace * equal * optionalspace * attributevalue) / add_attribute
------ attributes = (attribute)^0
-
-local attributes = (attribute + somespace^-1 * (((1-endofattributes)^1)/attribute_specification_error))^0
-
-local parsedtext = text_parsed / add_text
-local unparsedtext = text_unparsed / add_text
-local balanced = P { "[" * ((1 - S"[]") + V(1))^0 * "]" } -- taken from lpeg manual, () example
-
-local emptyelement = (spacing * open * name * attributes * optionalspace * slash * close) / add_empty
-local beginelement = (spacing * open * name * attributes * optionalspace * close) / add_begin
-local endelement = (spacing * open * slash * name * optionalspace * close) / add_end
-
-local begincomment = open * P("!--")
-local endcomment = P("--") * close
-local begininstruction = open * P("?")
-local endinstruction = P("?") * close
-local begincdata = open * P("![CDATA[")
-local endcdata = P("]]") * close
-
-local someinstruction = C((1 - endinstruction)^0)
-local somecomment = C((1 - endcomment )^0)
-local somecdata = C((1 - endcdata )^0)
-
-local function normalentity(k,v ) entities[k] = v end
-local function systementity(k,v,n) entities[k] = v end
-local function publicentity(k,v,n) entities[k] = v end
-
--- todo: separate dtd parser
-
-local begindoctype = open * P("!DOCTYPE")
-local enddoctype = close
-local beginset = P("[")
-local endset = P("]")
-local doctypename = C((1-somespace-close)^0)
-local elementdoctype = optionalspace * P(" &
- cleanup = settings.text_cleanup
- entities = settings.entities or { }
- --
- if utfize == nil then
- settings.utfize_entities = true
- utfize = true
- end
- if resolve_predefined == nil then
- settings.resolve_predefined_entities = true
- resolve_predefined = true
- end
- --
- --
- stack, top, at, xmlns, errorstr = { }, { }, { }, { }, nil
- acache, hcache, dcache = { }, { }, { } -- not stored
- reported_attribute_errors = { }
- if settings.parent_root then
- mt = getmetatable(settings.parent_root)
- else
- initialize_mt(top)
- end
- stack[#stack+1] = top
- top.dt = { }
- dt = top.dt
- if not data or data == "" then
- errorstr = "empty xml file"
- elseif utfize or resolve then
- if lpegmatch(grammar_parsed_text,data) then
- errorstr = ""
- else
- errorstr = "invalid xml file - parsed text"
- end
- elseif type(data) == "string" then
- if lpegmatch(grammar_unparsed_text,data) then
- errorstr = ""
- else
- errorstr = "invalid xml file - unparsed text"
- end
- else
- errorstr = "invalid xml file - no text at all"
- end
- local result
- if errorstr and errorstr ~= "" then
- result = { dt = { { ns = "", tg = "error", dt = { errorstr }, at={ }, er = true } } }
- setmetatable(stack, mt)
- local errorhandler = settings.error_handler
- if errorhandler == false then
- -- no error message
- else
- errorhandler = errorhandler or xml.errorhandler
- if errorhandler then
- xml.errorhandler(format("load error: %s",errorstr))
- end
- end
- else
- result = stack[1]
- end
- if not settings.no_root then
- result = { special = true, ns = "", tg = '@rt@', dt = result.dt, at={ }, entities = entities, settings = settings }
- setmetatable(result, mt)
- local rdt = result.dt
- for k=1,#rdt do
- local v = rdt[k]
- if type(v) == "table" and not v.special then -- always table -)
- result.ri = k -- rootindex
- v.__p__ = result -- new, experiment, else we cannot go back to settings, we need to test this !
- break
- end
- end
- end
- if errorstr and errorstr ~= "" then
- result.error = true
- end
- result.statistics = {
- entities = {
- decimals = dcache,
- hexadecimals = hcache,
- names = acache,
- }
- }
- strip, utfize, resolve, resolve_predefined = nil, nil, nil, nil
- unify_predefined, cleanup, entities = nil, nil, nil
- stack, top, at, xmlns, errorstr = nil, nil, nil, nil, nil
- acache, hcache, dcache = nil, nil, nil
- reported_attribute_errors, mt, errorhandler = nil, nil, nil
- return result
-end
-
--- Because we can have a crash (stack issues) with faulty xml, we wrap this one
--- in a protector:
-
-function xmlconvert(data,settings)
- local ok, result = pcall(function() return _xmlconvert_(data,settings) end)
- if ok then
- return result
- else
- return _xmlconvert_("")
- end
-end
-
-xml.convert = xmlconvert
-
-function xml.inheritedconvert(data,xmldata) -- xmldata is parent
- local settings = xmldata.settings
- if settings then
- settings.parent_root = xmldata -- to be tested
- end
- -- settings.no_root = true
- local xc = xmlconvert(data,settings) -- hm, we might need to locate settings
- -- xc.settings = nil
- -- xc.entities = nil
- -- xc.special = nil
- -- xc.ri = nil
- -- print(xc.tg)
- return xc
-end
-
---[[ldx--
-Packaging data in an xml like table is done with the following
-function. Maybe it will go away (when not used).
---ldx]]--
-
-function xml.is_valid(root)
- return root and root.dt and root.dt[1] and type(root.dt[1]) == "table" and not root.dt[1].er
-end
-
-function xml.package(tag,attributes,data)
- local ns, tg = match(tag,"^(.-):?([^:]+)$")
- local t = { ns = ns, tg = tg, dt = data or "", at = attributes or {} }
- setmetatable(t, mt)
- return t
-end
-
-function xml.is_valid(root)
- return root and not root.error
-end
-
-xml.errorhandler = report_xml
-
---[[ldx--
-We cannot load an from a filehandle so we need to load
-the whole file first. The function accepts a string representing
-a filename or a file handle.
---ldx]]--
-
-function xml.load(filename,settings)
- local data = ""
- if type(filename) == "string" then
- -- local data = io.loaddata(filename) - -todo: check type in io.loaddata
- local f = io.open(filename,'r')
- if f then
- data = f:read("*all")
- f:close()
- end
- elseif filename then -- filehandle
- data = filename:read("*all")
- end
- return xmlconvert(data,settings)
-end
-
---[[ldx--
-When we inject new elements, we need to convert strings to
-valid trees, which is what the next function does.
---ldx]]--
-
-local no_root = { no_root = true }
-
-function xml.toxml(data)
- if type(data) == "string" then
- local root = { xmlconvert(data,no_root) }
- return (#root > 1 and root) or root[1]
- else
- return data
- end
-end
-
---[[ldx--
-For copying a tree we use a dedicated function instead of the
-generic table copier. Since we know what we're dealing with we
-can speed up things a bit. The second argument is not to be used!
---ldx]]--
-
-local function copy(old,tables)
- if old then
- tables = tables or { }
- local new = { }
- if not tables[old] then
- tables[old] = new
- end
- for k,v in next, old do
- new[k] = (type(v) == "table" and (tables[v] or copy(v, tables))) or v
- end
- local mt = getmetatable(old)
- if mt then
- setmetatable(new,mt)
- end
- return new
- else
- return { }
- end
-end
-
-xml.copy = copy
-
---[[ldx--
-In serializing the tree or parts of the tree is a major
-actitivity which is why the following function is pretty optimized resulting
-in a few more lines of code than needed. The variant that uses the formatting
-function for all components is about 15% slower than the concatinating
-alternative.
---ldx]]--
-
--- todo: add when not present
-
-function xml.checkbom(root) -- can be made faster
- if root.ri then
- local dt = root.dt
- for k=1,#dt do
- local v = dt[k]
- if type(v) == "table" and v.special and v.tg == "@pi@" and find(v.dt[1],"xml.*version=") then
- return
- end
- end
- insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
- insert(dt, 2, "\n" )
- end
-end
-
---[[ldx--
-At the cost of some 25% runtime overhead you can first convert the tree to a string
-and then handle the lot.
---ldx]]--
-
--- new experimental reorganized serialize
-
-local function verbose_element(e,handlers) -- options
- local handle = handlers.handle
- local serialize = handlers.serialize
- local ens, etg, eat, edt, ern = e.ns, e.tg, e.at, e.dt, e.rn
- local ats = eat and next(eat) and { }
- if ats then
- for k,v in next, eat do
- ats[#ats+1] = format('%s=%q',k,escaped(v))
- end
- end
- if ern and trace_entities and ern ~= ens then
- ens = ern
- end
- if ens ~= "" then
- if edt and #edt > 0 then
- if ats then
- handle("<",ens,":",etg," ",concat(ats," "),">")
- else
- handle("<",ens,":",etg,">")
- end
- for i=1,#edt do
- local e = edt[i]
- if type(e) == "string" then
- handle(escaped(e))
- else
- serialize(e,handlers)
- end
- end
- handle("",ens,":",etg,">")
- else
- if ats then
- handle("<",ens,":",etg," ",concat(ats," "),"/>")
- else
- handle("<",ens,":",etg,"/>")
- end
- end
- else
- if edt and #edt > 0 then
- if ats then
- handle("<",etg," ",concat(ats," "),">")
- else
- handle("<",etg,">")
- end
- for i=1,#edt do
- local e = edt[i]
- if type(e) == "string" then
- handle(escaped(e)) -- option: hexify escaped entities
- else
- serialize(e,handlers)
- end
- end
- handle("",etg,">")
- else
- if ats then
- handle("<",etg," ",concat(ats," "),"/>")
- else
- handle("<",etg,"/>")
- end
- end
- end
-end
-
-local function verbose_pi(e,handlers)
- handlers.handle("",e.dt[1],"?>")
-end
-
-local function verbose_comment(e,handlers)
- handlers.handle("")
-end
-
-local function verbose_cdata(e,handlers)
- handlers.handle("")
-end
-
-local function verbose_doctype(e,handlers)
- handlers.handle("")
-end
-
-local function verbose_root(e,handlers)
- handlers.serialize(e.dt,handlers)
-end
-
-local function verbose_text(e,handlers)
- handlers.handle(escaped(e))
-end
-
-local function verbose_document(e,handlers)
- local serialize = handlers.serialize
- local functions = handlers.functions
- for i=1,#e do
- local ei = e[i]
- if type(ei) == "string" then
- functions["@tx@"](ei,handlers)
- else
- serialize(ei,handlers)
- end
- end
-end
-
-local function serialize(e,handlers,...)
- local initialize = handlers.initialize
- local finalize = handlers.finalize
- local functions = handlers.functions
- if initialize then
- local state = initialize(...)
- if not state == true then
- return state
- end
- end
- local etg = e.tg
- if etg then
- (functions[etg] or functions["@el@"])(e,handlers)
- -- elseif type(e) == "string" then
- -- functions["@tx@"](e,handlers)
- else
- functions["@dc@"](e,handlers) -- dc ?
- end
- if finalize then
- return finalize()
- end
-end
-
-local function xserialize(e,handlers)
- local functions = handlers.functions
- local etg = e.tg
- if etg then
- (functions[etg] or functions["@el@"])(e,handlers)
- -- elseif type(e) == "string" then
- -- functions["@tx@"](e,handlers)
- else
- functions["@dc@"](e,handlers)
- end
-end
-
-local handlers = { }
-
-local function newhandlers(settings)
- local t = table.copy(handlers.verbose or { }) -- merge
- if settings then
- for k,v in next, settings do
- if type(v) == "table" then
- local tk = t[k] if not tk then tk = { } t[k] = tk end
- for kk,vv in next, v do
- tk[kk] = vv
- end
- else
- t[k] = v
- end
- end
- if settings.name then
- handlers[settings.name] = t
- end
- end
- utilities.storage.mark(t)
- return t
-end
-
-local nofunction = function() end
-
-function xml.sethandlersfunction(handler,name,fnc)
- handler.functions[name] = fnc or nofunction
-end
-
-function xml.gethandlersfunction(handler,name)
- return handler.functions[name]
-end
-
-function xml.gethandlers(name)
- return handlers[name]
-end
-
-newhandlers {
- name = "verbose",
- initialize = false, -- faster than nil and mt lookup
- finalize = false, -- faster than nil and mt lookup
- serialize = xserialize,
- handle = print,
- functions = {
- ["@dc@"] = verbose_document,
- ["@dt@"] = verbose_doctype,
- ["@rt@"] = verbose_root,
- ["@el@"] = verbose_element,
- ["@pi@"] = verbose_pi,
- ["@cm@"] = verbose_comment,
- ["@cd@"] = verbose_cdata,
- ["@tx@"] = verbose_text,
- }
-}
-
---[[ldx--
-How you deal with saving data depends on your preferences. For a 40 MB database
-file the timing on a 2.3 Core Duo are as follows (time in seconds):
-
-
-1.3 : load data from file to string
-6.1 : convert string into tree
-5.3 : saving in file using xmlsave
-6.8 : converting to string using xml.tostring
-3.6 : saving converted string in file
-
-
-Beware, these were timing with the old routine but measurements will not be that
-much different I guess.
---ldx]]--
-
--- maybe this will move to lxml-xml
-
-local result
-
-local xmlfilehandler = newhandlers {
- name = "file",
- initialize = function(name)
- result = io.open(name,"wb")
- return result
- end,
- finalize = function()
- result:close()
- return true
- end,
- handle = function(...)
- result:write(...)
- end,
-}
-
--- no checking on writeability here but not faster either
---
--- local xmlfilehandler = newhandlers {
--- initialize = function(name)
--- io.output(name,"wb")
--- return true
--- end,
--- finalize = function()
--- io.close()
--- return true
--- end,
--- handle = io.write,
--- }
-
-function xml.save(root,name)
- serialize(root,xmlfilehandler,name)
-end
-
-local result
-
-local xmlstringhandler = newhandlers {
- name = "string",
- initialize = function()
- result = { }
- return result
- end,
- finalize = function()
- return concat(result)
- end,
- handle = function(...)
- result[#result+1] = concat { ... }
- end,
-}
-
-local function xmltostring(root) -- 25% overhead due to collecting
- if not root then
- return ""
- elseif type(root) == 'string' then
- return root
- else -- if next(root) then -- next is faster than type (and >0 test)
- return serialize(root,xmlstringhandler) or ""
- end
-end
-
-local function __tostring(root) -- inline
- return (root and xmltostring(root)) or ""
-end
-
-initialize_mt = function(root) -- redefinition
- mt = { __tostring = __tostring, __index = root }
-end
-
-xml.defaulthandlers = handlers
-xml.newhandlers = newhandlers
-xml.serialize = serialize
-xml.tostring = xmltostring
-
---[[ldx--
-The next function operated on the content only and needs a handle function
-that accepts a string.
---ldx]]--
-
-local function xmlstring(e,handle)
- if not handle or (e.special and e.tg ~= "@rt@") then
- -- nothing
- elseif e.tg then
- local edt = e.dt
- if edt then
- for i=1,#edt do
- xmlstring(edt[i],handle)
- end
- end
- else
- handle(e)
- end
-end
-
-xml.string = xmlstring
-
---[[ldx--
-A few helpers:
---ldx]]--
-
-
-function xml.settings(e)
- while e do
- local s = e.settings
- if s then
- return s
- else
- e = e.__p__
- end
- end
- return nil
-end
-
-function xml.root(e)
- local r = e
- while e do
- e = e.__p__
- if e then
- r = e
- end
- end
- return r
-end
-
-function xml.parent(root)
- return root.__p__
-end
-
-function xml.body(root)
- return (root.ri and root.dt[root.ri]) or root -- not ok yet
-end
-
-function xml.name(root)
- if not root then
- return ""
- elseif root.ns == "" then
- return root.tg
- else
- return root.ns .. ":" .. root.tg
- end
-end
-
---[[ldx--
-The next helper erases an element but keeps the table as it is,
-and since empty strings are not serialized (effectively) it does
-not harm. Copying the table would take more time. Usage:
---ldx]]--
-
-function xml.erase(dt,k)
- if dt then
- if k then
- dt[k] = ""
- else for k=1,#dt do
- dt[1] = { "" }
- end end
- end
-end
-
---[[ldx--
-The next helper assigns a tree (or string). Usage:
-
-
-dt[k] = xml.assign(root) or xml.assign(dt,k,root)
-
---ldx]]--
-
-function xml.assign(dt,k,root)
- if dt and k then
- dt[k] = (type(root) == "table" and xml.body(root)) or root
- return dt[k]
- else
- return xml.body(root)
- end
-end
-
--- the following helpers may move
-
---[[ldx--
-The next helper assigns a tree (or string). Usage:
-
-xml.tocdata(e)
-xml.tocdata(e,"error")
-
---ldx]]--
-
-function xml.tocdata(e,wrapper) -- a few more in the aux module
- local whatever = type(e) == "table" and xmltostring(e.dt) or e or ""
- if wrapper then
- whatever = format("<%s>%s%s>",wrapper,whatever,wrapper)
- end
- local t = { special = true, ns = "", tg = "@cd@", at = {}, rn = "", dt = { whatever }, __p__ = e }
- setmetatable(t,getmetatable(e))
- e.dt = { t }
-end
-
-function xml.makestandalone(root)
- if root.ri then
- local dt = root.dt
- for k=1,#dt do
- local v = dt[k]
- if type(v) == "table" and v.special and v.tg == "@pi@" then
- local txt = v.dt[1]
- if find(txt,"xml.*version=") then
- v.dt[1] = txt .. " standalone='yes'"
- break
- end
- end
- end
- end
- return root
-end
-
-function xml.kind(e)
- local dt = e and e.dt
- if dt then
- local n = #dt
- if n == 1 then
- local d = dt[1]
- if d.special then
- local tg = d.tg
- if tg == "@cd@" then
- return "cdata"
- elseif tg == "@cm" then
- return "comment"
- elseif tg == "@pi@" then
- return "instruction"
- elseif tg == "@dt@" then
- return "declaration"
- end
- elseif type(d) == "string" then
- return "text"
- end
- return "element"
- elseif n > 0 then
- return "mixed"
- end
- end
- return "empty"
-end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['lxml-pth'] = {
- version = 1.001,
- comment = "this module is the basis for the lxml-* ones",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- e.ni is only valid after a filter run
--- todo: B/C/[get first match]
-
-local concat, remove, insert = table.concat, table.remove, table.insert
-local type, next, tonumber, tostring, setmetatable, loadstring = type, next, tonumber, tostring, setmetatable, loadstring
-local format, upper, lower, gmatch, gsub, find, rep = string.format, string.upper, string.lower, string.gmatch, string.gsub, string.find, string.rep
-local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
-
-local setmetatableindex = table.setmetatableindex
-
--- beware, this is not xpath ... e.g. position is different (currently) and
--- we have reverse-sibling as reversed preceding sibling
-
---[[ldx--
-This module can be used stand alone but also inside in
-which case it hooks into the tracker code. Therefore we provide a few
-functions that set the tracers. Here we overload a previously defined
-function.
-If I can get in the mood I will make a variant that is XSLT compliant
-but I wonder if it makes sense.
---ldx]]--
-
---[[ldx--
-Expecially the lpath code is experimental, we will support some of xpath, but
-only things that make sense for us; as compensation it is possible to hook in your
-own functions. Apart from preprocessing content for we also need
-this module for process management, like handling and
-files.
-
-
-a/b/c /*/c
-a/b/c/first() a/b/c/last() a/b/c/index(n) a/b/c/index(-n)
-a/b/c/text() a/b/c/text(1) a/b/c/text(-1) a/b/c/text(n)
-
---ldx]]--
-
-local trace_lpath = false if trackers then trackers.register("xml.path", function(v) trace_lpath = v end) end
-local trace_lparse = false if trackers then trackers.register("xml.parse", function(v) trace_lparse = v end) end
-local trace_lprofile = false if trackers then trackers.register("xml.profile", function(v) trace_lpath = v trace_lparse = v trace_lprofile = v end) end
-
-local report_lpath = logs.reporter("xml","lpath")
-
---[[ldx--
-We've now arrived at an interesting part: accessing the tree using a subset
-of and since we're not compatible we call it . We
-will explain more about its usage in other documents.
---ldx]]--
-
-local xml = xml
-
-local lpathcalls = 0 function xml.lpathcalls () return lpathcalls end
-local lpathcached = 0 function xml.lpathcached() return lpathcached end
-
-xml.functions = xml.functions or { } -- internal
-local functions = xml.functions
-
-xml.expressions = xml.expressions or { } -- in expressions
-local expressions = xml.expressions
-
-xml.finalizers = xml.finalizers or { } -- fast do-with ... (with return value other than collection)
-local finalizers = xml.finalizers
-
-xml.specialhandler = xml.specialhandler or { }
-local specialhandler = xml.specialhandler
-
-lpegpatterns.xml = lpegpatterns.xml or { }
-local xmlpatterns = lpegpatterns.xml
-
-finalizers.xml = finalizers.xml or { }
-finalizers.tex = finalizers.tex or { }
-
-local function fallback (t, name)
- local fn = finalizers[name]
- if fn then
- t[name] = fn
- else
- report_lpath("unknown sub finalizer '%s'",tostring(name))
- fn = function() end
- end
- return fn
-end
-
-setmetatableindex(finalizers.xml, fallback)
-setmetatableindex(finalizers.tex, fallback)
-
-xml.defaultprotocol = "xml"
-
--- as xsl does not follow xpath completely here we will also
--- be more liberal especially with regards to the use of | and
--- the rootpath:
---
--- test : all 'test' under current
--- /test : 'test' relative to current
--- a|b|c : set of names
--- (a|b|c) : idem
--- ! : not
---
--- after all, we're not doing transformations but filtering. in
--- addition we provide filter functions (last bit)
---
--- todo: optimizer
---
--- .. : parent
--- * : all kids
--- / : anchor here
--- // : /**/
--- ** : all in between
---
--- so far we had (more practical as we don't transform)
---
--- {/test} : kids 'test' under current node
--- {test} : any kid with tag 'test'
--- {//test} : same as above
-
--- evaluator (needs to be redone, for the moment copied)
-
--- todo: apply_axis(list,notable) and collection vs single
-
-local apply_axis = { }
-
-apply_axis['root'] = function(list)
- local collected = { }
- for l=1,#list do
- local ll = list[l]
- local rt = ll
- while ll do
- ll = ll.__p__
- if ll then
- rt = ll
- end
- end
- collected[l] = rt
- end
- return collected
-end
-
-apply_axis['self'] = function(list)
- return list
-end
-
-apply_axis['child'] = function(list)
- local collected, c = { }, 0
- for l=1,#list do
- local ll = list[l]
- local dt = ll.dt
- if dt then -- weird that this is needed
- local en = 0
- for k=1,#dt do
- local dk = dt[k]
- if dk.tg then
- c = c + 1
- collected[c] = dk
- dk.ni = k -- refresh
- en = en + 1
- dk.ei = en
- end
- end
- ll.en = en
- end
- end
- return collected
-end
-
-local function collect(list,collected,c)
- local dt = list.dt
- if dt then
- local en = 0
- for k=1,#dt do
- local dk = dt[k]
- if dk.tg then
- c = c + 1
- collected[c] = dk
- dk.ni = k -- refresh
- en = en + 1
- dk.ei = en
- c = collect(dk,collected,c)
- end
- end
- list.en = en
- end
- return c
-end
-
-apply_axis['descendant'] = function(list)
- local collected, c = { }, 0
- for l=1,#list do
- c = collect(list[l],collected,c)
- end
- return collected
-end
-
-local function collect(list,collected,c)
- local dt = list.dt
- if dt then
- local en = 0
- for k=1,#dt do
- local dk = dt[k]
- if dk.tg then
- c = c + 1
- collected[c] = dk
- dk.ni = k -- refresh
- en = en + 1
- dk.ei = en
- c = collect(dk,collected,c)
- end
- end
- list.en = en
- end
- return c
-end
-apply_axis['descendant-or-self'] = function(list)
- local collected, c = { }, 0
- for l=1,#list do
- local ll = list[l]
- if ll.special ~= true then -- catch double root
- c = c + 1
- collected[c] = ll
- end
- c = collect(ll,collected,c)
- end
- return collected
-end
-
-apply_axis['ancestor'] = function(list)
- local collected, c = { }, 0
- for l=1,#list do
- local ll = list[l]
- while ll do
- ll = ll.__p__
- if ll then
- c = c + 1
- collected[c] = ll
- end
- end
- end
- return collected
-end
-
-apply_axis['ancestor-or-self'] = function(list)
- local collected, c = { }, 0
- for l=1,#list do
- local ll = list[l]
- c = c + 1
- collected[c] = ll
- while ll do
- ll = ll.__p__
- if ll then
- c = c + 1
- collected[c] = ll
- end
- end
- end
- return collected
-end
-
-apply_axis['parent'] = function(list)
- local collected, c = { }, 0
- for l=1,#list do
- local pl = list[l].__p__
- if pl then
- c = c + 1
- collected[c] = pl
- end
- end
- return collected
-end
-
-apply_axis['attribute'] = function(list)
- return { }
-end
-
-apply_axis['namespace'] = function(list)
- return { }
-end
-
-apply_axis['following'] = function(list) -- incomplete
- return { }
-end
-
-apply_axis['preceding'] = function(list) -- incomplete
- return { }
-end
-
-apply_axis['following-sibling'] = function(list)
- local collected, c = { }, 0
- for l=1,#list do
- local ll = list[l]
- local p = ll.__p__
- local d = p.dt
- for i=ll.ni+1,#d do
- local di = d[i]
- if type(di) == "table" then
- c = c + 1
- collected[c] = di
- end
- end
- end
- return collected
-end
-
-apply_axis['preceding-sibling'] = function(list)
- local collected, c = { }, 0
- for l=1,#list do
- local ll = list[l]
- local p = ll.__p__
- local d = p.dt
- for i=1,ll.ni-1 do
- local di = d[i]
- if type(di) == "table" then
- c = c + 1
- collected[c] = di
- end
- end
- end
- return collected
-end
-
-apply_axis['reverse-sibling'] = function(list) -- reverse preceding
- local collected, c = { }, 0
- for l=1,#list do
- local ll = list[l]
- local p = ll.__p__
- local d = p.dt
- for i=ll.ni-1,1,-1 do
- local di = d[i]
- if type(di) == "table" then
- c = c + 1
- collected[c] = di
- end
- end
- end
- return collected
-end
-
-apply_axis['auto-descendant-or-self'] = apply_axis['descendant-or-self']
-apply_axis['auto-descendant'] = apply_axis['descendant']
-apply_axis['auto-child'] = apply_axis['child']
-apply_axis['auto-self'] = apply_axis['self']
-apply_axis['initial-child'] = apply_axis['child']
-
-local function apply_nodes(list,directive,nodes)
- -- todo: nodes[1] etc ... negated node name in set ... when needed
- -- ... currently ignored
- local maxn = #nodes
- if maxn == 3 then --optimized loop
- local nns, ntg = nodes[2], nodes[3]
- if not nns and not ntg then -- wildcard
- if directive then
- return list
- else
- return { }
- end
- else
- local collected, c, m, p = { }, 0, 0, nil
- if not nns then -- only check tag
- for l=1,#list do
- local ll = list[l]
- local ltg = ll.tg
- if ltg then
- if directive then
- if ntg == ltg then
- local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
- c = c + 1
- collected[c], ll.mi = ll, m
- end
- elseif ntg ~= ltg then
- local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
- c = c + 1
- collected[c], ll.mi = ll, m
- end
- end
- end
- elseif not ntg then -- only check namespace
- for l=1,#list do
- local ll = list[l]
- local lns = ll.rn or ll.ns
- if lns then
- if directive then
- if lns == nns then
- local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
- c = c + 1
- collected[c], ll.mi = ll, m
- end
- elseif lns ~= nns then
- local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
- c = c + 1
- collected[c], ll.mi = ll, m
- end
- end
- end
- else -- check both
- for l=1,#list do
- local ll = list[l]
- local ltg = ll.tg
- if ltg then
- local lns = ll.rn or ll.ns
- local ok = ltg == ntg and lns == nns
- if directive then
- if ok then
- local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
- c = c + 1
- collected[c], ll.mi = ll, m
- end
- elseif not ok then
- local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
- c = c + 1
- collected[c], ll.mi = ll, m
- end
- end
- end
- end
- return collected
- end
- else
- local collected, c, m, p = { }, 0, 0, nil
- for l=1,#list do
- local ll = list[l]
- local ltg = ll.tg
- if ltg then
- local lns = ll.rn or ll.ns
- local ok = false
- for n=1,maxn,3 do
- local nns, ntg = nodes[n+1], nodes[n+2]
- ok = (not ntg or ltg == ntg) and (not nns or lns == nns)
- if ok then
- break
- end
- end
- if directive then
- if ok then
- local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
- c = c + 1
- collected[c], ll.mi = ll, m
- end
- elseif not ok then
- local llp = ll.__p__ ; if llp ~= p then p, m = llp, 1 else m = m + 1 end
- c = c + 1
- collected[c], ll.mi = ll, m
- end
- end
- end
- return collected
- end
-end
-
-local quit_expression = false
-
-local function apply_expression(list,expression,order)
- local collected, c = { }, 0
- quit_expression = false
- for l=1,#list do
- local ll = list[l]
- if expression(list,ll,l,order) then -- nasty, order alleen valid als n=1
- c = c + 1
- collected[c] = ll
- end
- if quit_expression then
- break
- end
- end
- return collected
-end
-
-local P, V, C, Cs, Cc, Ct, R, S, Cg, Cb = lpeg.P, lpeg.V, lpeg.C, lpeg.Cs, lpeg.Cc, lpeg.Ct, lpeg.R, lpeg.S, lpeg.Cg, lpeg.Cb
-
-local spaces = S(" \n\r\t\f")^0
-local lp_space = S(" \n\r\t\f")
-local lp_any = P(1)
-local lp_noequal = P("!=") / "~=" + P("<=") + P(">=") + P("==")
-local lp_doequal = P("=") / "=="
-local lp_or = P("|") / " or "
-local lp_and = P("&") / " and "
-
-local lp_builtin = P (
- P("text") / "(ll.dt[1] or '')" + -- fragile
- P("content") / "ll.dt" +
- -- P("name") / "(ll.ns~='' and ll.ns..':'..ll.tg)" +
- P("name") / "((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)" +
- P("tag") / "ll.tg" +
- P("position") / "l" + -- is element in finalizer
- P("firstindex") / "1" +
- P("lastindex") / "(#ll.__p__.dt or 1)" +
- P("firstelement") / "1" +
- P("lastelement") / "(ll.__p__.en or 1)" +
- P("first") / "1" +
- P("last") / "#list" +
- P("rootposition") / "order" +
- P("order") / "order" +
- P("element") / "(ll.ei or 1)" +
- P("index") / "(ll.ni or 1)" +
- P("match") / "(ll.mi or 1)" +
- -- P("namespace") / "ll.ns" +
- P("ns") / "ll.ns"
- ) * ((spaces * P("(") * spaces * P(")"))/"")
-
--- for the moment we keep namespaces with attributes
-
-local lp_attribute = (P("@") + P("attribute::")) / "" * Cc("(ll.at and ll.at['") * ((R("az","AZ") + S("-_:"))^1) * Cc("'])")
-local lp_fastpos_p = ((P("+")^0 * R("09")^1 * P(-1)) / function(s) return "l==" .. s end)
-local lp_fastpos_n = ((P("-") * R("09")^1 * P(-1)) / function(s) return "(" .. s .. "<0 and (#list+".. s .. "==l))" end)
-local lp_fastpos = lp_fastpos_n + lp_fastpos_p
-local lp_reserved = C("and") + C("or") + C("not") + C("div") + C("mod") + C("true") + C("false")
-
-local lp_lua_function = C(R("az","AZ","__")^1 * (P(".") * R("az","AZ","__")^1)^1) * ("(") / function(t) -- todo: better . handling
- return t .. "("
-end
-
-local lp_function = C(R("az","AZ","__")^1) * P("(") / function(t) -- todo: better . handling
- if expressions[t] then
- return "expr." .. t .. "("
- else
- return "expr.error("
- end
-end
-
-local lparent = P("(")
-local rparent = P(")")
-local noparent = 1 - (lparent+rparent)
-local nested = P{lparent * (noparent + V(1))^0 * rparent}
-local value = P(lparent * C((noparent + nested)^0) * rparent) -- P{"("*C(((1-S("()"))+V(1))^0)*")"}
-
-local lp_child = Cc("expr.child(ll,'") * R("az","AZ","--","__")^1 * Cc("')")
-local lp_number = S("+-") * R("09")^1
-local lp_string = Cc("'") * R("az","AZ","--","__")^1 * Cc("'")
-local lp_content = (P("'") * (1-P("'"))^0 * P("'") + P('"') * (1-P('"'))^0 * P('"'))
-
-local cleaner
-
-local lp_special = (C(P("name")+P("text")+P("tag")+P("count")+P("child"))) * value / function(t,s)
- if expressions[t] then
- s = s and s ~= "" and lpegmatch(cleaner,s)
- if s and s ~= "" then
- return "expr." .. t .. "(ll," .. s ..")"
- else
- return "expr." .. t .. "(ll)"
- end
- else
- return "expr.error(" .. t .. ")"
- end
-end
-
-local content =
- lp_builtin +
- lp_attribute +
- lp_special +
- lp_noequal + lp_doequal +
- lp_or + lp_and +
- lp_reserved +
- lp_lua_function + lp_function +
- lp_content + -- too fragile
- lp_child +
- lp_any
-
-local converter = Cs (
- lp_fastpos + (P { lparent * (V(1))^0 * rparent + content } )^0
-)
-
-cleaner = Cs ( (
- lp_reserved +
- lp_number +
- lp_string +
-1 )^1 )
-
-
-
-local template_e = [[
- local expr = xml.expressions
- return function(list,ll,l,order)
- return %s
- end
-]]
-
-local template_f_y = [[
- local finalizer = xml.finalizers['%s']['%s']
- return function(collection)
- return finalizer(collection,%s)
- end
-]]
-
-local template_f_n = [[
- return xml.finalizers['%s']['%s']
-]]
-
---
-
-local register_self = { kind = "axis", axis = "self" } -- , apply = apply_axis["self"] }
-local register_parent = { kind = "axis", axis = "parent" } -- , apply = apply_axis["parent"] }
-local register_descendant = { kind = "axis", axis = "descendant" } -- , apply = apply_axis["descendant"] }
-local register_child = { kind = "axis", axis = "child" } -- , apply = apply_axis["child"] }
-local register_descendant_or_self = { kind = "axis", axis = "descendant-or-self" } -- , apply = apply_axis["descendant-or-self"] }
-local register_root = { kind = "axis", axis = "root" } -- , apply = apply_axis["root"] }
-local register_ancestor = { kind = "axis", axis = "ancestor" } -- , apply = apply_axis["ancestor"] }
-local register_ancestor_or_self = { kind = "axis", axis = "ancestor-or-self" } -- , apply = apply_axis["ancestor-or-self"] }
-local register_attribute = { kind = "axis", axis = "attribute" } -- , apply = apply_axis["attribute"] }
-local register_namespace = { kind = "axis", axis = "namespace" } -- , apply = apply_axis["namespace"] }
-local register_following = { kind = "axis", axis = "following" } -- , apply = apply_axis["following"] }
-local register_following_sibling = { kind = "axis", axis = "following-sibling" } -- , apply = apply_axis["following-sibling"] }
-local register_preceding = { kind = "axis", axis = "preceding" } -- , apply = apply_axis["preceding"] }
-local register_preceding_sibling = { kind = "axis", axis = "preceding-sibling" } -- , apply = apply_axis["preceding-sibling"] }
-local register_reverse_sibling = { kind = "axis", axis = "reverse-sibling" } -- , apply = apply_axis["reverse-sibling"] }
-
-local register_auto_descendant_or_self = { kind = "axis", axis = "auto-descendant-or-self" } -- , apply = apply_axis["auto-descendant-or-self"] }
-local register_auto_descendant = { kind = "axis", axis = "auto-descendant" } -- , apply = apply_axis["auto-descendant"] }
-local register_auto_self = { kind = "axis", axis = "auto-self" } -- , apply = apply_axis["auto-self"] }
-local register_auto_child = { kind = "axis", axis = "auto-child" } -- , apply = apply_axis["auto-child"] }
-
-local register_initial_child = { kind = "axis", axis = "initial-child" } -- , apply = apply_axis["initial-child"] }
-
-local register_all_nodes = { kind = "nodes", nodetest = true, nodes = { true, false, false } }
-
-local skip = { }
-
-local function errorrunner_e(str,cnv)
- if not skip[str] then
- report_lpath("error in expression: %s => %s",str,cnv)
- skip[str] = cnv or str
- end
- return false
-end
-local function errorrunner_f(str,arg)
- report_lpath("error in finalizer: %s(%s)",str,arg or "")
- return false
-end
-
-local function register_nodes(nodetest,nodes)
- return { kind = "nodes", nodetest = nodetest, nodes = nodes }
-end
-
-local function register_expression(expression)
- local converted = lpegmatch(converter,expression)
- local runner = loadstring(format(template_e,converted))
- runner = (runner and runner()) or function() errorrunner_e(expression,converted) end
- return { kind = "expression", expression = expression, converted = converted, evaluator = runner }
-end
-
-local function register_finalizer(protocol,name,arguments)
- local runner
- if arguments and arguments ~= "" then
- runner = loadstring(format(template_f_y,protocol or xml.defaultprotocol,name,arguments))
- else
- runner = loadstring(format(template_f_n,protocol or xml.defaultprotocol,name))
- end
- runner = (runner and runner()) or function() errorrunner_f(name,arguments) end
- return { kind = "finalizer", name = name, arguments = arguments, finalizer = runner }
-end
-
-local expression = P { "ex",
- ex = "[" * C((V("sq") + V("dq") + (1 - S("[]")) + V("ex"))^0) * "]",
- sq = "'" * (1 - S("'"))^0 * "'",
- dq = '"' * (1 - S('"'))^0 * '"',
-}
-
-local arguments = P { "ar",
- ar = "(" * Cs((V("sq") + V("dq") + V("nq") + P(1-P(")")))^0) * ")",
- nq = ((1 - S("),'\""))^1) / function(s) return format("%q",s) end,
- sq = P("'") * (1 - P("'"))^0 * P("'"),
- dq = P('"') * (1 - P('"'))^0 * P('"'),
-}
-
--- todo: better arg parser
-
-local function register_error(str)
- return { kind = "error", error = format("unparsed: %s",str) }
-end
-
--- there is a difference in * and /*/ and so we need to catch a few special cases
-
-local special_1 = P("*") * Cc(register_auto_descendant) * Cc(register_all_nodes) -- last one not needed
-local special_2 = P("/") * Cc(register_auto_self)
-local special_3 = P("") * Cc(register_auto_self)
-
-local no_nextcolon = P(-1) + #(1-P(":")) -- newer lpeg needs the P(-1)
-local no_nextlparent = P(-1) + #(1-P("(")) -- newer lpeg needs the P(-1)
-
-local pathparser = Ct { "patterns", -- can be made a bit faster by moving some patterns outside
-
- patterns = spaces * V("protocol") * spaces * (
- ( V("special") * spaces * P(-1) ) +
- ( V("initial") * spaces * V("step") * spaces * (P("/") * spaces * V("step") * spaces)^0 )
- ),
-
- protocol = Cg(V("letters"),"protocol") * P("://") + Cg(Cc(nil),"protocol"),
-
- -- the / is needed for // as descendant or self is somewhat special
- -- step = (V("shortcuts") + V("axis") * spaces * V("nodes")^0 + V("error")) * spaces * V("expressions")^0 * spaces * V("finalizer")^0,
- step = ((V("shortcuts") + P("/") + V("axis")) * spaces * V("nodes")^0 + V("error")) * spaces * V("expressions")^0 * spaces * V("finalizer")^0,
-
- axis = V("descendant") + V("child") + V("parent") + V("self") + V("root") + V("ancestor") +
- V("descendant_or_self") + V("following_sibling") + V("following") +
- V("reverse_sibling") + V("preceding_sibling") + V("preceding") + V("ancestor_or_self") +
- #(1-P(-1)) * Cc(register_auto_child),
-
- special = special_1 + special_2 + special_3,
-
- initial = (P("/") * spaces * Cc(register_initial_child))^-1,
-
- error = (P(1)^1) / register_error,
-
- shortcuts_a = V("s_descendant_or_self") + V("s_descendant") + V("s_child") + V("s_parent") + V("s_self") + V("s_root") + V("s_ancestor"),
-
- shortcuts = V("shortcuts_a") * (spaces * "/" * spaces * V("shortcuts_a"))^0,
-
- s_descendant_or_self = (P("***/") + P("/")) * Cc(register_descendant_or_self), --- *** is a bonus
- s_descendant = P("**") * Cc(register_descendant),
- s_child = P("*") * no_nextcolon * Cc(register_child ),
- s_parent = P("..") * Cc(register_parent ),
- s_self = P("." ) * Cc(register_self ),
- s_root = P("^^") * Cc(register_root ),
- s_ancestor = P("^") * Cc(register_ancestor ),
-
- descendant = P("descendant::") * Cc(register_descendant ),
- child = P("child::") * Cc(register_child ),
- parent = P("parent::") * Cc(register_parent ),
- self = P("self::") * Cc(register_self ),
- root = P('root::') * Cc(register_root ),
- ancestor = P('ancestor::') * Cc(register_ancestor ),
- descendant_or_self = P('descendant-or-self::') * Cc(register_descendant_or_self ),
- ancestor_or_self = P('ancestor-or-self::') * Cc(register_ancestor_or_self ),
- -- attribute = P('attribute::') * Cc(register_attribute ),
- -- namespace = P('namespace::') * Cc(register_namespace ),
- following = P('following::') * Cc(register_following ),
- following_sibling = P('following-sibling::') * Cc(register_following_sibling ),
- preceding = P('preceding::') * Cc(register_preceding ),
- preceding_sibling = P('preceding-sibling::') * Cc(register_preceding_sibling ),
- reverse_sibling = P('reverse-sibling::') * Cc(register_reverse_sibling ),
-
- nodes = (V("nodefunction") * spaces * P("(") * V("nodeset") * P(")") + V("nodetest") * V("nodeset")) / register_nodes,
-
- expressions = expression / register_expression,
-
- letters = R("az")^1,
- name = (1-S("/[]()|:*!"))^1, -- make inline
- negate = P("!") * Cc(false),
-
- nodefunction = V("negate") + P("not") * Cc(false) + Cc(true),
- nodetest = V("negate") + Cc(true),
- nodename = (V("negate") + Cc(true)) * spaces * ((V("wildnodename") * P(":") * V("wildnodename")) + (Cc(false) * V("wildnodename"))),
- wildnodename = (C(V("name")) + P("*") * Cc(false)) * no_nextlparent,
- nodeset = spaces * Ct(V("nodename") * (spaces * P("|") * spaces * V("nodename"))^0) * spaces,
-
- finalizer = (Cb("protocol") * P("/")^-1 * C(V("name")) * arguments * P(-1)) / register_finalizer,
-
-}
-
-xmlpatterns.pathparser = pathparser
-
-local cache = { }
-
-local function nodesettostring(set,nodetest)
- local t = { }
- for i=1,#set,3 do
- local directive, ns, tg = set[i], set[i+1], set[i+2]
- if not ns or ns == "" then ns = "*" end
- if not tg or tg == "" then tg = "*" end
- tg = (tg == "@rt@" and "[root]") or format("%s:%s",ns,tg)
- t[i] = (directive and tg) or format("not(%s)",tg)
- end
- if nodetest == false then
- return format("not(%s)",concat(t,"|"))
- else
- return concat(t,"|")
- end
-end
-
-local function tagstostring(list)
- if #list == 0 then
- return "no elements"
- else
- local t = { }
- for i=1, #list do
- local li = list[i]
- local ns, tg = li.ns, li.tg
- if not ns or ns == "" then ns = "*" end
- if not tg or tg == "" then tg = "*" end
- t[i] = (tg == "@rt@" and "[root]") or format("%s:%s",ns,tg)
- end
- return concat(t," ")
- end
-end
-
-xml.nodesettostring = nodesettostring
-
-local lpath -- we have a harmless kind of circular reference
-
-local lshowoptions = { functions = false }
-
-local function lshow(parsed)
- if type(parsed) == "string" then
- parsed = lpath(parsed)
- end
- report_lpath("%s://%s => %s",parsed.protocol or xml.defaultprotocol,parsed.pattern,
- table.serialize(parsed,false,lshowoptions))
-end
-
-xml.lshow = lshow
-
-local function add_comment(p,str)
- local pc = p.comment
- if not pc then
- p.comment = { str }
- else
- pc[#pc+1] = str
- end
-end
-
-lpath = function (pattern) -- the gain of caching is rather minimal
- lpathcalls = lpathcalls + 1
- if type(pattern) == "table" then
- return pattern
- else
- local parsed = cache[pattern]
- if parsed then
- lpathcached = lpathcached + 1
- else
- parsed = lpegmatch(pathparser,pattern)
- if parsed then
- parsed.pattern = pattern
- local np = #parsed
- if np == 0 then
- parsed = { pattern = pattern, register_self, state = "parsing error" }
- report_lpath("parsing error in '%s'",pattern)
- lshow(parsed)
- else
- -- we could have done this with a more complex parser but this
- -- is cleaner
- local pi = parsed[1]
- if pi.axis == "auto-child" then
- if false then
- add_comment(parsed, "auto-child replaced by auto-descendant-or-self")
- parsed[1] = register_auto_descendant_or_self
- else
- add_comment(parsed, "auto-child replaced by auto-descendant")
- parsed[1] = register_auto_descendant
- end
- elseif pi.axis == "initial-child" and np > 1 and parsed[2].axis then
- add_comment(parsed, "initial-child removed") -- we could also make it a auto-self
- remove(parsed,1)
- end
- local np = #parsed -- can have changed
- if np > 1 then
- local pnp = parsed[np]
- if pnp.kind == "nodes" and pnp.nodetest == true then
- local nodes = pnp.nodes
- if nodes[1] == true and nodes[2] == false and nodes[3] == false then
- add_comment(parsed, "redundant final wildcard filter removed")
- remove(parsed,np)
- end
- end
- end
- end
- else
- parsed = { pattern = pattern }
- end
- cache[pattern] = parsed
- if trace_lparse and not trace_lprofile then
- lshow(parsed)
- end
- end
- return parsed
- end
-end
-
-xml.lpath = lpath
-
--- we can move all calls inline and then merge the trace back
--- technically we can combine axis and the next nodes which is
--- what we did before but this a bit cleaner (but slower too)
--- but interesting is that it's not that much faster when we
--- go inline
---
--- beware: we need to return a collection even when we filter
--- else the (simple) cache gets messed up
-
--- caching found lookups saves not that much (max .1 sec on a 8 sec run)
--- and it also messes up finalizers
-
--- watch out: when there is a finalizer, it's always called as there
--- can be cases that a finalizer returns (or does) something in case
--- there is no match; an example of this is count()
-
-local profiled = { } xml.profiled = profiled
-
-local function profiled_apply(list,parsed,nofparsed,order)
- local p = profiled[parsed.pattern]
- if p then
- p.tested = p.tested + 1
- else
- p = { tested = 1, matched = 0, finalized = 0 }
- profiled[parsed.pattern] = p
- end
- local collected = list
- for i=1,nofparsed do
- local pi = parsed[i]
- local kind = pi.kind
- if kind == "axis" then
- collected = apply_axis[pi.axis](collected)
- elseif kind == "nodes" then
- collected = apply_nodes(collected,pi.nodetest,pi.nodes)
- elseif kind == "expression" then
- collected = apply_expression(collected,pi.evaluator,order)
- elseif kind == "finalizer" then
- collected = pi.finalizer(collected) -- no check on # here
- p.matched = p.matched + 1
- p.finalized = p.finalized + 1
- return collected
- end
- if not collected or #collected == 0 then
- local pn = i < nofparsed and parsed[nofparsed]
- if pn and pn.kind == "finalizer" then
- collected = pn.finalizer(collected)
- p.finalized = p.finalized + 1
- return collected
- end
- return nil
- end
- end
- if collected then
- p.matched = p.matched + 1
- end
- return collected
-end
-
-local function traced_apply(list,parsed,nofparsed,order)
- if trace_lparse then
- lshow(parsed)
- end
- report_lpath("collecting: %s",parsed.pattern)
- report_lpath("root tags : %s",tagstostring(list))
- report_lpath("order : %s",order or "unset")
- local collected = list
- for i=1,nofparsed do
- local pi = parsed[i]
- local kind = pi.kind
- if kind == "axis" then
- collected = apply_axis[pi.axis](collected)
- report_lpath("% 10i : ax : %s",(collected and #collected) or 0,pi.axis)
- elseif kind == "nodes" then
- collected = apply_nodes(collected,pi.nodetest,pi.nodes)
- report_lpath("% 10i : ns : %s",(collected and #collected) or 0,nodesettostring(pi.nodes,pi.nodetest))
- elseif kind == "expression" then
- collected = apply_expression(collected,pi.evaluator,order)
- report_lpath("% 10i : ex : %s -> %s",(collected and #collected) or 0,pi.expression,pi.converted)
- elseif kind == "finalizer" then
- collected = pi.finalizer(collected)
- report_lpath("% 10i : fi : %s : %s(%s)",(type(collected) == "table" and #collected) or 0,parsed.protocol or xml.defaultprotocol,pi.name,pi.arguments or "")
- return collected
- end
- if not collected or #collected == 0 then
- local pn = i < nofparsed and parsed[nofparsed]
- if pn and pn.kind == "finalizer" then
- collected = pn.finalizer(collected)
- report_lpath("% 10i : fi : %s : %s(%s)",(type(collected) == "table" and #collected) or 0,parsed.protocol or xml.defaultprotocol,pn.name,pn.arguments or "")
- return collected
- end
- return nil
- end
- end
- return collected
-end
-
-local function normal_apply(list,parsed,nofparsed,order)
- local collected = list
- for i=1,nofparsed do
- local pi = parsed[i]
- local kind = pi.kind
- if kind == "axis" then
- local axis = pi.axis
- if axis ~= "self" then
- collected = apply_axis[axis](collected)
- end
- elseif kind == "nodes" then
- collected = apply_nodes(collected,pi.nodetest,pi.nodes)
- elseif kind == "expression" then
- collected = apply_expression(collected,pi.evaluator,order)
- elseif kind == "finalizer" then
- return pi.finalizer(collected)
- end
- if not collected or #collected == 0 then
- local pf = i < nofparsed and parsed[nofparsed].finalizer
- if pf then
- return pf(collected) -- can be anything
- end
- return nil
- end
- end
- return collected
-end
-
-
-local function applylpath(list,pattern)
- if not list then
- return
- end
- local parsed = cache[pattern]
- if parsed then
- lpathcalls = lpathcalls + 1
- lpathcached = lpathcached + 1
- elseif type(pattern) == "table" then
- lpathcalls = lpathcalls + 1
- parsed = pattern
- else
- parsed = lpath(pattern) or pattern
- end
- if not parsed then
- return
- end
- local nofparsed = #parsed
- if nofparsed == 0 then
- return -- something is wrong
- end
- if not trace_lpath then
- return normal_apply ({ list },parsed,nofparsed,list.mi)
- elseif trace_lprofile then
- return profiled_apply({ list },parsed,nofparsed,list.mi)
- else
- return traced_apply ({ list },parsed,nofparsed,list.mi)
- end
-end
-
-xml.applylpath = applylpath -- takes a table as first argment, which is what xml.filter will do
-
---[[ldx--
-This is the main filter function. It returns whatever is asked for.
---ldx]]--
-
-function xml.filter(root,pattern) -- no longer funny attribute handling here
- return applylpath(root,pattern)
-end
-
--- internal (parsed)
-
-expressions.child = function(e,pattern)
- return applylpath(e,pattern) -- todo: cache
-end
-expressions.count = function(e,pattern) -- what if pattern == empty or nil
- local collected = applylpath(e,pattern) -- todo: cache
- return pattern and (collected and #collected) or 0
-end
-
--- external
-
-expressions.oneof = function(s,...) -- slow
- local t = {...} for i=1,#t do if s == t[i] then return true end end return false
-end
-expressions.error = function(str)
- xml.errorhandler(format("unknown function in lpath expression: %s",tostring(str or "?")))
- return false
-end
-expressions.undefined = function(s)
- return s == nil
-end
-
-expressions.quit = function(s)
- if s or s == nil then
- quit_expression = true
- end
- return true
-end
-
-expressions.print = function(...)
- print(...)
- return true
-end
-
-expressions.contains = find
-expressions.find = find
-expressions.upper = upper
-expressions.lower = lower
-expressions.number = tonumber
-expressions.boolean = toboolean
-
-function expressions.contains(str,pattern)
- local t = type(str)
- if t == "string" then
- if find(str,pattern) then
- return true
- end
- elseif t == "table" then
- for i=1,#str do
- local d = str[i]
- if type(d) == "string" and find(d,pattern) then
- return true
- end
- end
- end
- return false
-end
-
--- user interface
-
-local function traverse(root,pattern,handle)
- report_lpath("use 'xml.selection' instead for '%s'",pattern)
- local collected = applylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local r = e.__p__
- handle(r,r.dt,e.ni)
- end
- end
-end
-
-local function selection(root,pattern,handle)
- local collected = applylpath(root,pattern)
- if collected then
- if handle then
- for c=1,#collected do
- handle(collected[c])
- end
- else
- return collected
- end
- end
-end
-
-xml.traverse = traverse -- old method, r, d, k
-xml.selection = selection -- new method, simple handle
-
-
--- generic function finalizer (independant namespace)
-
-local function dofunction(collected,fnc)
- if collected then
- local f = functions[fnc]
- if f then
- for c=1,#collected do
- f(collected[c])
- end
- else
- report_lpath("unknown function '%s'",fnc)
- end
- end
-end
-
-finalizers.xml["function"] = dofunction
-finalizers.tex["function"] = dofunction
-
--- functions
-
-expressions.text = function(e,n)
- local rdt = e.__p__.dt
- return (rdt and rdt[n]) or ""
-end
-
-expressions.name = function(e,n) -- ns + tg
- local found = false
- n = tonumber(n) or 0
- if n == 0 then
- found = type(e) == "table" and e
- elseif n < 0 then
- local d, k = e.__p__.dt, e.ni
- for i=k-1,1,-1 do
- local di = d[i]
- if type(di) == "table" then
- if n == -1 then
- found = di
- break
- else
- n = n + 1
- end
- end
- end
- else
- local d, k = e.__p__.dt, e.ni
- for i=k+1,#d,1 do
- local di = d[i]
- if type(di) == "table" then
- if n == 1 then
- found = di
- break
- else
- n = n - 1
- end
- end
- end
- end
- if found then
- local ns, tg = found.rn or found.ns or "", found.tg
- if ns ~= "" then
- return ns .. ":" .. tg
- else
- return tg
- end
- else
- return ""
- end
-end
-
-expressions.tag = function(e,n) -- only tg
- if not e then
- return ""
- else
- local found = false
- n = tonumber(n) or 0
- if n == 0 then
- found = (type(e) == "table") and e -- seems to fail
- elseif n < 0 then
- local d, k = e.__p__.dt, e.ni
- for i=k-1,1,-1 do
- local di = d[i]
- if type(di) == "table" then
- if n == -1 then
- found = di
- break
- else
- n = n + 1
- end
- end
- end
- else
- local d, k = e.__p__.dt, e.ni
- for i=k+1,#d,1 do
- local di = d[i]
- if type(di) == "table" then
- if n == 1 then
- found = di
- break
- else
- n = n - 1
- end
- end
- end
- end
- return (found and found.tg) or ""
- end
-end
-
---[[ldx--
-Often using an iterators looks nicer in the code than passing handler
-functions. The book describes how to use coroutines for that
-purpose ( ). This permits
-code like:
-
-
-for r, d, k in xml.elements(xml.load('text.xml'),"title") do
- print(d[k]) -- old method
-end
-for e in xml.collected(xml.load('text.xml'),"title") do
- print(e) -- new one
-end
-
---ldx]]--
-
-local wrap, yield = coroutine.wrap, coroutine.yield
-
-function xml.elements(root,pattern,reverse) -- r, d, k
- local collected = applylpath(root,pattern)
- if collected then
- if reverse then
- return wrap(function() for c=#collected,1,-1 do
- local e = collected[c] local r = e.__p__ yield(r,r.dt,e.ni)
- end end)
- else
- return wrap(function() for c=1,#collected do
- local e = collected[c] local r = e.__p__ yield(r,r.dt,e.ni)
- end end)
- end
- end
- return wrap(function() end)
-end
-
-function xml.collected(root,pattern,reverse) -- e
- local collected = applylpath(root,pattern)
- if collected then
- if reverse then
- return wrap(function() for c=#collected,1,-1 do yield(collected[c]) end end)
- else
- return wrap(function() for c=1,#collected do yield(collected[c]) end end)
- end
- end
- return wrap(function() end)
-end
-
--- handy
-
-function xml.inspect(collection,pattern)
- pattern = pattern or "."
- for e in xml.collected(collection,pattern or ".") do
- report_lpath("pattern %q\n\n%s\n",pattern,xml.tostring(e))
- end
-end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['lxml-mis'] = {
- version = 1.001,
- comment = "this module is the basis for the lxml-* ones",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local xml, lpeg, string = xml, lpeg, string
-
-local concat = table.concat
-local type, next, tonumber, tostring, setmetatable, loadstring = type, next, tonumber, tostring, setmetatable, loadstring
-local format, gsub, match = string.format, string.gsub, string.match
-local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
-local P, S, R, C, V, Cc, Cs = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.V, lpeg.Cc, lpeg.Cs
-
-lpegpatterns.xml = lpegpatterns.xml or { }
-local xmlpatterns = lpegpatterns.xml
-
---[[ldx--
-The following helper functions best belong to the lxml-ini
-module. Some are here because we need then in the mk
-document and other manuals, others came up when playing with
-this module. Since this module is also used in we've
-put them here instead of loading mode modules there then needed.
---ldx]]--
-
-local function xmlgsub(t,old,new) -- will be replaced
- local dt = t.dt
- if dt then
- for k=1,#dt do
- local v = dt[k]
- if type(v) == "string" then
- dt[k] = gsub(v,old,new)
- else
- xmlgsub(v,old,new)
- end
- end
- end
-end
-
-
-function xml.stripleadingspaces(dk,d,k) -- cosmetic, for manual
- if d and k then
- local dkm = d[k-1]
- if dkm and type(dkm) == "string" then
- local s = match(dkm,"\n(%s+)")
- xmlgsub(dk,"\n"..rep(" ",#s),"\n")
- end
- end
-end
-
-
-
--- 100 * 2500 * "oeps< oeps> oeps&" : gsub:lpeg|lpeg|lpeg
---
--- 1021:0335:0287:0247
-
--- 10 * 1000 * "oeps< oeps> oeps& asfjhalskfjh alskfjh alskfjh alskfjh ;al J;LSFDJ"
---
--- 1559:0257:0288:0190 (last one suggested by roberto)
-
--- escaped = Cs((S("<&>") / xml.escapes + 1)^0)
--- escaped = Cs((S("<")/"<" + S(">")/">" + S("&")/"&" + 1)^0)
-local normal = (1 - S("<&>"))^0
-local special = P("<")/"<" + P(">")/">" + P("&")/"&"
-local escaped = Cs(normal * (special * normal)^0)
-
--- 100 * 1000 * "oeps< oeps> oeps&" : gsub:lpeg == 0153:0280:0151:0080 (last one by roberto)
-
-local normal = (1 - S"&")^0
-local special = P("<")/"<" + P(">")/">" + P("&")/"&"
-local unescaped = Cs(normal * (special * normal)^0)
-
--- 100 * 5000 * "oeps oeps oeps " : gsub:lpeg == 623:501 msec (short tags, less difference)
-
-local cleansed = Cs(((P("<") * (1-P(">"))^0 * P(">"))/"" + 1)^0)
-
-xmlpatterns.escaped = escaped
-xmlpatterns.unescaped = unescaped
-xmlpatterns.cleansed = cleansed
-
-function xml.escaped (str) return lpegmatch(escaped,str) end
-function xml.unescaped(str) return lpegmatch(unescaped,str) end
-function xml.cleansed (str) return lpegmatch(cleansed,str) end
-
--- this might move
-
-function xml.fillin(root,pattern,str,check)
- local e = xml.first(root,pattern)
- if e then
- local n = #e.dt
- if not check or n == 0 or (n == 1 and e.dt[1] == "") then
- e.dt = { str }
- end
- end
-end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['lxml-aux'] = {
- version = 1.001,
- comment = "this module is the basis for the lxml-* ones",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- not all functions here make sense anymore vbut we keep them for
--- compatibility reasons
-
-local trace_manipulations = false trackers.register("lxml.manipulations", function(v) trace_manipulations = v end)
-
-local report_xml = logs.reporter("xml")
-
-local xml = xml
-
-local xmlconvert, xmlcopy, xmlname = xml.convert, xml.copy, xml.name
-local xmlinheritedconvert = xml.inheritedconvert
-local xmlapplylpath = xml.applylpath
-local xmlfilter = xml.filter
-
-local type, setmetatable, getmetatable = type, setmetatable, getmetatable
-local insert, remove, fastcopy, concat = table.insert, table.remove, table.fastcopy, table.concat
-local gmatch, gsub, format, find, strip = string.gmatch, string.gsub, string.format, string.find, string.strip
-local utfbyte = utf.byte
-
-local function report(what,pattern,c,e)
- report_xml("%s element '%s' (root: '%s', position: %s, index: %s, pattern: %s)",what,xmlname(e),xmlname(e.__p__),c,e.ni,pattern)
-end
-
-local function withelements(e,handle,depth)
- if e and handle then
- local edt = e.dt
- if edt then
- depth = depth or 0
- for i=1,#edt do
- local e = edt[i]
- if type(e) == "table" then
- handle(e,depth)
- withelements(e,handle,depth+1)
- end
- end
- end
- end
-end
-
-xml.withelements = withelements
-
-function xml.withelement(e,n,handle) -- slow
- if e and n ~= 0 and handle then
- local edt = e.dt
- if edt then
- if n > 0 then
- for i=1,#edt do
- local ei = edt[i]
- if type(ei) == "table" then
- if n == 1 then
- handle(ei)
- return
- else
- n = n - 1
- end
- end
- end
- elseif n < 0 then
- for i=#edt,1,-1 do
- local ei = edt[i]
- if type(ei) == "table" then
- if n == -1 then
- handle(ei)
- return
- else
- n = n + 1
- end
- end
- end
- end
- end
- end
-end
-
-function xml.each(root,pattern,handle,reverse)
- local collected = xmlapplylpath(root,pattern)
- if collected then
- if reverse then
- for c=#collected,1,-1 do
- handle(collected[c])
- end
- else
- for c=1,#collected do
- handle(collected[c])
- end
- end
- return collected
- end
-end
-
-function xml.processattributes(root,pattern,handle)
- local collected = xmlapplylpath(root,pattern)
- if collected and handle then
- for c=1,#collected do
- handle(collected[c].at)
- end
- end
- return collected
-end
-
---[[ldx--
-The following functions collect elements and texts.
---ldx]]--
-
--- are these still needed -> lxml-cmp.lua
-
-function xml.collect(root, pattern)
- return xmlapplylpath(root,pattern)
-end
-
-function xml.collecttexts(root, pattern, flatten) -- todo: variant with handle
- local collected = xmlapplylpath(root,pattern)
- if collected and flatten then
- local xmltostring = xml.tostring
- for c=1,#collected do
- collected[c] = xmltostring(collected[c].dt)
- end
- end
- return collected or { }
-end
-
-function xml.collect_tags(root, pattern, nonamespace)
- local collected = xmlapplylpath(root,pattern)
- if collected then
- local t, n = { }, 0
- for c=1,#collected do
- local e = collected[c]
- local ns, tg = e.ns, e.tg
- n = n + 1
- if nonamespace then
- t[n] = tg
- elseif ns == "" then
- t[n] = tg
- else
- t[n] = ns .. ":" .. tg
- end
- end
- return t
- end
-end
-
---[[ldx--
-We've now arrived at the functions that manipulate the tree.
---ldx]]--
-
-local no_root = { no_root = true }
-
-local function redo_ni(d)
- for k=1,#d do
- local dk = d[k]
- if type(dk) == "table" then
- dk.ni = k
- end
- end
-end
-
-local function xmltoelement(whatever,root)
- if not whatever then
- return nil
- end
- local element
- if type(whatever) == "string" then
- element = xmlinheritedconvert(whatever,root) -- beware, not really a root
- else
- element = whatever -- we assume a table
- end
- if element.error then
- return whatever -- string
- end
- if element then
- end
- return element
-end
-
-xml.toelement = xmltoelement
-
-local function copiedelement(element,newparent)
- if type(element) == "string" then
- return element
- else
- element = xmlcopy(element).dt
- if newparent and type(element) == "table" then
- element.__p__ = newparent
- end
- return element
- end
-end
-
-function xml.delete(root,pattern)
- if not pattern or pattern == "" then
- local p = root.__p__
- if p then
- if trace_manipulations then
- report('deleting',"--",c,root)
- end
- local d = p.dt
- remove(d,root.ni)
- redo_ni(d) -- can be made faster and inlined
- end
- else
- local collected = xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local p = e.__p__
- if p then
- if trace_manipulations then
- report('deleting',pattern,c,e)
- end
- local d = p.dt
- remove(d,e.ni)
- redo_ni(d) -- can be made faster and inlined
- end
- end
- end
- end
-end
-
-function xml.replace(root,pattern,whatever)
- local element = root and xmltoelement(whatever,root)
- local collected = element and xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local p = e.__p__
- if p then
- if trace_manipulations then
- report('replacing',pattern,c,e)
- end
- local d = p.dt
- d[e.ni] = copiedelement(element,p)
- redo_ni(d) -- probably not needed
- end
- end
- end
-end
-
-local function wrap(e,wrapper)
- local t = {
- rn = e.rn,
- tg = e.tg,
- ns = e.ns,
- at = e.at,
- dt = e.dt,
- __p__ = e,
- }
- setmetatable(t,getmetatable(e))
- e.rn = wrapper.rn or e.rn or ""
- e.tg = wrapper.tg or e.tg or ""
- e.ns = wrapper.ns or e.ns or ""
- e.at = fastcopy(wrapper.at)
- e.dt = { t }
-end
-
-function xml.wrap(root,pattern,whatever)
- if whatever then
- local wrapper = xmltoelement(whatever,root)
- local collected = xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- if trace_manipulations then
- report('wrapping',pattern,c,e)
- end
- wrap(e,wrapper)
- end
- end
- else
- wrap(root,xmltoelement(pattern))
- end
-end
-
-local function inject_element(root,pattern,whatever,prepend)
- local element = root and xmltoelement(whatever,root)
- local collected = element and xmlapplylpath(root,pattern)
- local function inject_e(e)
- local r = e.__p__
- local d, k, rri = r.dt, e.ni, r.ri
- local edt = (rri and d[rri].dt) or (d and d[k] and d[k].dt)
- if edt then
- local be, af
- local cp = copiedelement(element,e)
- if prepend then
- be, af = cp, edt
- else
- be, af = edt, cp
- end
- local bn = #be
- for i=1,#af do
- bn = bn + 1
- be[bn] = af[i]
- end
- if rri then
- r.dt[rri].dt = be
- else
- d[k].dt = be
- end
- redo_ni(d)
- end
- end
- if not collected then
- -- nothing
- elseif collected.tg then
- -- first or so
- inject_e(collected)
- else
- for c=1,#collected do
- inject_e(collected[c])
- end
- end
-end
-
-local function insert_element(root,pattern,whatever,before) -- todo: element als functie
- local element = root and xmltoelement(whatever,root)
- local collected = element and xmlapplylpath(root,pattern)
- local function insert_e(e)
- local r = e.__p__
- local d, k = r.dt, e.ni
- if not before then
- k = k + 1
- end
- insert(d,k,copiedelement(element,r))
- redo_ni(d)
- end
- if not collected then
- -- nothing
- elseif collected.tg then
- -- first or so
- insert_e(collected)
- else
- for c=1,#collected do
- insert_e(collected[c])
- end
- end
-end
-
-xml.insert_element = insert_element
-xml.insertafter = insert_element
-xml.insertbefore = function(r,p,e) insert_element(r,p,e,true) end
-xml.injectafter = inject_element
-xml.injectbefore = function(r,p,e) inject_element(r,p,e,true) end
-
-local function include(xmldata,pattern,attribute,recursive,loaddata)
- -- parse="text" (default: xml), encoding="" (todo)
- -- attribute = attribute or 'href'
- pattern = pattern or 'include'
- loaddata = loaddata or io.loaddata
- local collected = xmlapplylpath(xmldata,pattern)
- if collected then
- for c=1,#collected do
- local ek = collected[c]
- local name = nil
- local ekdt = ek.dt
- local ekat = ek.at
- local epdt = ek.__p__.dt
- if not attribute or attribute == "" then
- name = (type(ekdt) == "table" and ekdt[1]) or ekdt -- check, probably always tab or str
- end
- if not name then
- for a in gmatch(attribute or "href","([^|]+)") do
- name = ekat[a]
- if name then break end
- end
- end
- local data = (name and name ~= "" and loaddata(name)) or ""
- if data == "" then
- epdt[ek.ni] = "" -- xml.empty(d,k)
- elseif ekat["parse"] == "text" then
- -- for the moment hard coded
- epdt[ek.ni] = xml.escaped(data) -- d[k] = xml.escaped(data)
- else
- local xi = xmlinheritedconvert(data,xmldata)
- if not xi then
- epdt[ek.ni] = "" -- xml.empty(d,k)
- else
- if recursive then
- include(xi,pattern,attribute,recursive,loaddata)
- end
- epdt[ek.ni] = xml.body(xi) -- xml.assign(d,k,xi)
- end
- end
- end
- end
-end
-
-xml.include = include
-
-local function stripelement(e,nolines,anywhere)
- local edt = e.dt
- if edt then
- if anywhere then
- local t, n = { }, 0
- for e=1,#edt do
- local str = edt[e]
- if type(str) ~= "string" then
- n = n + 1
- t[n] = str
- elseif str ~= "" then
- -- todo: lpeg for each case
- if nolines then
- str = gsub(str,"%s+"," ")
- end
- str = gsub(str,"^%s*(.-)%s*$","%1")
- if str ~= "" then
- n = n + 1
- t[n] = str
- end
- end
- end
- e.dt = t
- else
- -- we can assume a regular sparse xml table with no successive strings
- -- otherwise we should use a while loop
- if #edt > 0 then
- -- strip front
- local str = edt[1]
- if type(str) ~= "string" then
- -- nothing
- elseif str == "" then
- remove(edt,1)
- else
- if nolines then
- str = gsub(str,"%s+"," ")
- end
- str = gsub(str,"^%s+","")
- if str == "" then
- remove(edt,1)
- else
- edt[1] = str
- end
- end
- end
- local nedt = #edt
- if nedt > 0 then
- -- strip end
- local str = edt[nedt]
- if type(str) ~= "string" then
- -- nothing
- elseif str == "" then
- remove(edt)
- else
- if nolines then
- str = gsub(str,"%s+"," ")
- end
- str = gsub(str,"%s+$","")
- if str == "" then
- remove(edt)
- else
- edt[nedt] = str
- end
- end
- end
- end
- end
- return e -- convenient
-end
-
-xml.stripelement = stripelement
-
-function xml.strip(root,pattern,nolines,anywhere) -- strips all leading and trailing spacing
- local collected = xmlapplylpath(root,pattern) -- beware, indices no longer are valid now
- if collected then
- for i=1,#collected do
- stripelement(collected[i],nolines,anywhere)
- end
- end
-end
-
-local function renamespace(root, oldspace, newspace) -- fast variant
- local ndt = #root.dt
- for i=1,ndt or 0 do
- local e = root[i]
- if type(e) == "table" then
- if e.ns == oldspace then
- e.ns = newspace
- if e.rn then
- e.rn = newspace
- end
- end
- local edt = e.dt
- if edt then
- renamespace(edt, oldspace, newspace)
- end
- end
- end
-end
-
-xml.renamespace = renamespace
-
-function xml.remaptag(root, pattern, newtg)
- local collected = xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- collected[c].tg = newtg
- end
- end
-end
-
-function xml.remapnamespace(root, pattern, newns)
- local collected = xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- collected[c].ns = newns
- end
- end
-end
-
-function xml.checknamespace(root, pattern, newns)
- local collected = xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- if (not e.rn or e.rn == "") and e.ns == "" then
- e.rn = newns
- end
- end
- end
-end
-
-function xml.remapname(root, pattern, newtg, newns, newrn)
- local collected = xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- e.tg, e.ns, e.rn = newtg, newns, newrn
- end
- end
-end
-
---[[ldx--
-Helper (for q2p).
---ldx]]--
-
-function xml.cdatatotext(e)
- local dt = e.dt
- if #dt == 1 then
- local first = dt[1]
- if first.tg == "@cd@" then
- e.dt = first.dt
- end
- else
- -- maybe option
- end
-end
-
--- local x = xml.convert("12 3 ")
--- xml.texttocdata(xml.first(x,"a"))
--- print(x) -- 2 3]]>
-
-function xml.texttocdata(e) -- could be a finalizer
- local dt = e.dt
- local s = xml.tostring(dt) -- no shortcut?
- e.tg = "@cd@"
- e.special = true
- e.ns = ""
- e.rn = ""
- e.dt = { s }
- e.at = nil
-end
-
--- local x = xml.convert("12 3 ")
--- xml.tocdata(xml.first(x,"a"))
--- print(x) -- 12 3]]>
-
-function xml.elementtocdata(e) -- could be a finalizer
- local dt = e.dt
- local s = xml.tostring(e) -- no shortcut?
- e.tg = "@cd@"
- e.special = true
- e.ns = ""
- e.rn = ""
- e.dt = { s }
- e.at = nil
-end
-
-xml.builtinentities = table.tohash { "amp", "quot", "apos", "lt", "gt" } -- used often so share
-
-local entities = characters and characters.entities or nil
-local builtinentities = xml.builtinentities
-
-function xml.addentitiesdoctype(root,option) -- we could also have a 'resolve' i.e. inline hex
- if not entities then
- require("char-ent")
- entities = characters.entities
- end
- if entities and root and root.tg == "@rt@" and root.statistics then
- local list = { }
- local hexify = option == "hexadecimal"
- for k, v in table.sortedhash(root.statistics.entities.names) do
- if not builtinentities[k] then
- local e = entities[k]
- if not e then
- e = format("[%s]",k)
- elseif hexify then
- e = format("%05X;",utfbyte(k))
- end
- list[#list+1] = format(" ",k,e)
- end
- end
- local dt = root.dt
- local n = dt[1].tg == "@pi@" and 2 or 1
- if #list > 0 then
- insert(dt, n, { "\n" })
- insert(dt, n, {
- tg = "@dt@", -- beware, doctype is unparsed
- dt = { format("Something [\n%s\n] ",concat(list)) },
- ns = "",
- special = true,
- })
- insert(dt, n, { "\n\n" })
- else
- -- insert(dt, n, { table.serialize(root.statistics) })
- end
- end
-end
-
--- local str = [==[
---
---
--- test test { test
---
---
--- ]==]
---
--- local x = xml.convert(str)
--- xml.addentitiesdoctype(x,"hexadecimal")
--- print(x)
-
---[[ldx--
-Here are a few synonyms.
---ldx]]--
-
-xml.all = xml.each
-xml.insert = xml.insertafter
-xml.inject = xml.injectafter
-xml.after = xml.insertafter
-xml.before = xml.insertbefore
-xml.process = xml.each
-
--- obsolete
-
-xml.obsolete = xml.obsolete or { }
-local obsolete = xml.obsolete
-
-xml.strip_whitespace = xml.strip obsolete.strip_whitespace = xml.strip
-xml.collect_elements = xml.collect obsolete.collect_elements = xml.collect
-xml.delete_element = xml.delete obsolete.delete_element = xml.delete
-xml.replace_element = xml.replace obsolete.replace_element = xml.replacet
-xml.each_element = xml.each obsolete.each_element = xml.each
-xml.process_elements = xml.process obsolete.process_elements = xml.process
-xml.insert_element_after = xml.insertafter obsolete.insert_element_after = xml.insertafter
-xml.insert_element_before = xml.insertbefore obsolete.insert_element_before = xml.insertbefore
-xml.inject_element_after = xml.injectafter obsolete.inject_element_after = xml.injectafter
-xml.inject_element_before = xml.injectbefore obsolete.inject_element_before = xml.injectbefore
-xml.process_attributes = xml.processattributes obsolete.process_attributes = xml.processattributes
-xml.collect_texts = xml.collecttexts obsolete.collect_texts = xml.collecttexts
-xml.inject_element = xml.inject obsolete.inject_element = xml.inject
-xml.remap_tag = xml.remaptag obsolete.remap_tag = xml.remaptag
-xml.remap_name = xml.remapname obsolete.remap_name = xml.remapname
-xml.remap_namespace = xml.remapnamespace obsolete.remap_namespace = xml.remapnamespace
-
--- new (probably ok)
-
-function xml.cdata(e)
- if e then
- local dt = e.dt
- if dt and #dt == 1 then
- local first = dt[1]
- return first.tg == "@cd@" and first.dt[1] or ""
- end
- end
- return ""
-end
-
-function xml.finalizers.xml.cdata(collected)
- if collected then
- local e = collected[1]
- if e then
- local dt = e.dt
- if dt and #dt == 1 then
- local first = dt[1]
- return first.tg == "@cd@" and first.dt[1] or ""
- end
- end
- end
- return ""
-end
-
-function xml.insertcomment(e,str,n) -- also insertcdata
- table.insert(e.dt,n or 1,{
- tg = "@cm@",
- ns = "",
- special = true,
- at = { },
- dt = { str },
- })
-end
-
-function xml.setcdata(e,str) -- also setcomment
- e.dt = { {
- tg = "@cd@",
- ns = "",
- special = true,
- at = { },
- dt = { str },
- } }
-end
-
--- maybe helpers like this will move to an autoloader
-
-function xml.separate(x,pattern)
- local collected = xmlapplylpath(x,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local d = e.dt
- if d == x then
- report_xml("warning: xml.separate changes root")
- x = d
- end
- local t, n = { "\n" }, 1
- local i, nd = 1, #d
- while i <= nd do
- while i <= nd do
- local di = d[i]
- if type(di) == "string" then
- if di == "\n" or find(di,"^%s+$") then -- first test is speedup
- i = i + 1
- else
- d[i] = strip(di)
- break
- end
- else
- break
- end
- end
- if i > nd then
- break
- end
- t[n+1] = "\n"
- t[n+2] = d[i]
- t[n+3] = "\n"
- n = n + 3
- i = i + 1
- end
- t[n+1] = "\n"
- setmetatable(t,getmetatable(d))
- e.dt = t
- end
- end
- return x
-end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['lxml-xml'] = {
- version = 1.001,
- comment = "this module is the basis for the lxml-* ones",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local concat = table.concat
-local find, lower, upper = string.find, string.lower, string.upper
-
-local xml = xml
-
-local finalizers = xml.finalizers.xml
-local xmlfilter = xml.filter -- we could inline this one for speed
-local xmltostring = xml.tostring
-local xmlserialize = xml.serialize
-local xmlcollected = xml.collected
-local xmlnewhandlers = xml.newhandlers
-
-local function first(collected) -- wrong ?
- return collected and collected[1]
-end
-
-local function last(collected)
- return collected and collected[#collected]
-end
-
-local function all(collected)
- return collected
-end
-
--- local function reverse(collected)
--- if collected then
--- local nc = #collected
--- if nc > 0 then
--- local reversed, r = { }, 0
--- for c=nc,1,-1 do
--- r = r + 1
--- reversed[r] = collected[c]
--- end
--- return reversed
--- else
--- return collected
--- end
--- end
--- end
-
-local reverse = table.reversed
-
-local function attribute(collected,name)
- if collected and #collected > 0 then
- local at = collected[1].at
- return at and at[name]
- end
-end
-
-local function att(id,name)
- local at = id.at
- return at and at[name]
-end
-
-local function count(collected)
- return collected and #collected or 0
-end
-
-local function position(collected,n)
- if not collected then
- return 0
- end
- local nc = #collected
- if nc == 0 then
- return 0
- end
- n = tonumber(n) or 0
- if n < 0 then
- return collected[nc + n + 1]
- elseif n > 0 then
- return collected[n]
- else
- return collected[1].mi or 0
- end
-end
-
-local function match(collected)
- return collected and #collected > 0 and collected[1].mi or 0 -- match
-end
-
-local function index(collected)
- return collected and #collected > 0 and collected[1].ni or 0 -- 0 is new
-end
-
-local function attributes(collected,arguments)
- if collected and #collected > 0 then
- local at = collected[1].at
- if arguments then
- return at[arguments]
- elseif next(at) then
- return at -- all of them
- end
- end
-end
-
-local function chainattribute(collected,arguments) -- todo: optional levels
- if collected and #collected > 0 then
- local e = collected[1]
- while e do
- local at = e.at
- if at then
- local a = at[arguments]
- if a then
- return a
- end
- else
- break -- error
- end
- e = e.__p__
- end
- end
- return ""
-end
-
-local function raw(collected) -- hybrid (not much different from text so it might go)
- if collected and #collected > 0 then
- local e = collected[1] or collected
- return e and xmltostring(e) or "" -- only first as we cannot concat function
- else
- return ""
- end
-end
-
---
-
-local xmltexthandler = xmlnewhandlers {
- name = "string",
- initialize = function()
- result = { }
- return result
- end,
- finalize = function()
- return concat(result)
- end,
- handle = function(...)
- result[#result+1] = concat { ... }
- end,
- escape = false,
-}
-
-local function xmltotext(root)
- local dt = root.dt
- if not dt then
- return ""
- end
- local nt = #dt -- string or table
- if nt == 0 then
- return ""
- elseif nt == 1 and type(dt[1]) == "string" then
- return dt[1] -- no escaping of " ' < > &
- else
- return xmlserialize(root,xmltexthandler) or ""
- end
-end
-
---
-
-local function text(collected) -- hybrid
- if collected then -- no # test here !
- local e = collected[1] or collected -- why fallback to element, how about cdata
- return e and xmltotext(e) or ""
- else
- return ""
- end
-end
-
-local function texts(collected)
- if not collected then
- return { } -- why no nil
- end
- local nc = #collected
- if nc == 0 then
- return { } -- why no nil
- end
- local t, n = { }, 0
- for c=1,nc do
- local e = collected[c]
- if e and e.dt then
- n = n + 1
- t[n] = e.dt
- end
- end
- return t
-end
-
-local function tag(collected,n)
- if not collected then
- return
- end
- local nc = #collected
- if nc == 0 then
- return
- end
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[nc-n+1]
- end
- return c and c.tg
-end
-
-local function name(collected,n)
- if not collected then
- return
- end
- local nc = #collected
- if nc == 0 then
- return
- end
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[nc-n+1]
- end
- if not c then
- -- sorry
- elseif c.ns == "" then
- return c.tg
- else
- return c.ns .. ":" .. c.tg
- end
-end
-
-local function tags(collected,nonamespace)
- if not collected then
- return
- end
- local nc = #collected
- if nc == 0 then
- return
- end
- local t, n = { }, 0
- for c=1,nc do
- local e = collected[c]
- local ns, tg = e.ns, e.tg
- n = n + 1
- if nonamespace or ns == "" then
- t[n] = tg
- else
- t[n] = ns .. ":" .. tg
- end
- end
- return t
-end
-
-local function empty(collected,spacesonly)
- if not collected then
- return true
- end
- local nc = #collected
- if nc == 0 then
- return true
- end
- for c=1,nc do
- local e = collected[c]
- if e then
- local edt = e.dt
- if edt then
- local n = #edt
- if n == 1 then
- local edk = edt[1]
- local typ = type(edk)
- if typ == "table" then
- return false
- elseif edk ~= "" then
- return false
- elseif spacesonly and not find(edk,"%S") then
- return false
- end
- elseif n > 1 then
- return false
- end
- end
- end
- end
- return true
-end
-
-finalizers.first = first
-finalizers.last = last
-finalizers.all = all
-finalizers.reverse = reverse
-finalizers.elements = all
-finalizers.default = all
-finalizers.attribute = attribute
-finalizers.att = att
-finalizers.count = count
-finalizers.position = position
-finalizers.match = match
-finalizers.index = index
-finalizers.attributes = attributes
-finalizers.chainattribute = chainattribute
-finalizers.text = text
-finalizers.texts = texts
-finalizers.tag = tag
-finalizers.name = name
-finalizers.tags = tags
-finalizers.empty = empty
-
--- shortcuts -- we could support xmlfilter(id,pattern,first)
-
-function xml.first(id,pattern)
- return first(xmlfilter(id,pattern))
-end
-
-function xml.last(id,pattern)
- return last(xmlfilter(id,pattern))
-end
-
-function xml.count(id,pattern)
- return count(xmlfilter(id,pattern))
-end
-
-function xml.attribute(id,pattern,a,default)
- return attribute(xmlfilter(id,pattern),a,default)
-end
-
-function xml.raw(id,pattern)
- if pattern then
- return raw(xmlfilter(id,pattern))
- else
- return raw(id)
- end
-end
-
-function xml.text(id,pattern) -- brrr either content or element (when cdata)
- if pattern then
- -- return text(xmlfilter(id,pattern))
- local collected = xmlfilter(id,pattern)
- return collected and #collected > 0 and xmltotext(collected[1]) or ""
- elseif id then
- -- return text(id)
- return xmltotext(id) or ""
- else
- return ""
- end
-end
-
-xml.content = text
-
---
-
-function xml.position(id,pattern,n) -- element
- return position(xmlfilter(id,pattern),n)
-end
-
-function xml.match(id,pattern) -- number
- return match(xmlfilter(id,pattern))
-end
-
-function xml.empty(id,pattern,spacesonly)
- return empty(xmlfilter(id,pattern),spacesonly)
-end
-
-xml.all = xml.filter
-xml.index = xml.position
-xml.found = xml.filter
-
--- a nice one:
-
-local function totable(x)
- local t = { }
- for e in xmlcollected(x[1] or x,"/*") do
- t[e.tg] = xmltostring(e.dt) or ""
- end
- return next(t) and t or nil
-end
-
-xml.table = totable
-finalizers.table = totable
-
-local function textonly(e,t)
- if e then
- local edt = e.dt
- if edt then
- for i=1,#edt do
- local e = edt[i]
- if type(e) == "table" then
- textonly(e,t)
- else
- t[#t+1] = e
- end
- end
- end
- end
- return t
-end
-
-function xml.textonly(e) -- no pattern
- return concat(textonly(e,{}))
-end
-
---
-
--- local x = xml.convert("12 3 ")
--- xml.filter(x,"**/lowerall()") print(x)
--- xml.filter(x,"**/upperall()") print(x)
-
-function finalizers.lowerall(collected)
- for c=1,#collected do
- local e = collected[c]
- if not e.special then
- e.tg = lower(e.tg)
- local eat = e.at
- if eat then
- local t = { }
- for k,v in next, eat do
- t[lower(k)] = v
- end
- e.at = t
- end
- end
- end
-end
-
-function finalizers.upperall(collected)
- for c=1,#collected do
- local e = collected[c]
- if not e.special then
- e.tg = upper(e.tg)
- local eat = e.at
- if eat then
- local t = { }
- for k,v in next, eat do
- t[upper(k)] = v
- end
- e.at = t
- end
- end
- end
-end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['data-ini'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files",
-}
-
-local gsub, find, gmatch, char = string.gsub, string.find, string.gmatch, string.char
-local concat = table.concat
-local next, type = next, type
-
-local filedirname, filebasename, fileextname, filejoin = file.dirname, file.basename, file.extname, file.join
-
-local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
-local trace_detail = false trackers.register("resolvers.details", function(v) trace_detail = v end)
-local trace_expansions = false trackers.register("resolvers.expansions", function(v) trace_expansions = v end)
-
-local report_initialization = logs.reporter("resolvers","initialization")
-
-local ostype, osname, ossetenv, osgetenv = os.type, os.name, os.setenv, os.getenv
-
--- The code here used to be part of a data-res but for convenience
--- we now split it over multiple files. As this file is now the
--- starting point we introduce resolvers here.
-
-resolvers = resolvers or { }
-local resolvers = resolvers
-
--- We don't want the kpse library to kick in. Also, we want to be able to
--- execute programs. Control over execution is implemented later.
-
-texconfig.kpse_init = false
-texconfig.shell_escape = 't'
-
-if kpse and kpse.default_texmfcnf then
- local default_texmfcnf = kpse.default_texmfcnf()
- -- looks more like context:
- default_texmfcnf = gsub(default_texmfcnf,"$SELFAUTOLOC","selfautoloc:")
- default_texmfcnf = gsub(default_texmfcnf,"$SELFAUTODIR","selfautodir:")
- default_texmfcnf = gsub(default_texmfcnf,"$SELFAUTOPARENT","selfautoparent:")
- default_texmfcnf = gsub(default_texmfcnf,"$HOME","home:")
- --
- environment.default_texmfcnf = default_texmfcnf
-end
-
-kpse = { original = kpse }
-
-setmetatable(kpse, {
- __index = function(kp,name)
- report_initialization("fatal error: kpse library is accessed (key: %s)",name)
- os.exit()
- end
-} )
-
--- First we check a couple of environment variables. Some might be
--- set already but we need then later on. We start with the system
--- font path.
-
-do
-
- local osfontdir = osgetenv("OSFONTDIR")
-
- if osfontdir and osfontdir ~= "" then
- -- ok
- elseif osname == "windows" then
- ossetenv("OSFONTDIR","c:/windows/fonts//")
- elseif osname == "macosx" then
- ossetenv("OSFONTDIR","$HOME/Library/Fonts//;/Library/Fonts//;/System/Library/Fonts//")
- end
-
-end
-
--- Next comes the user's home path. We need this as later on we have
--- to replace ~ with its value.
-
-do
-
- local homedir = osgetenv(ostype == "windows" and 'USERPROFILE' or 'HOME') or ''
-
- if not homedir or homedir == "" then
- homedir = char(127) -- we need a value, later we wil trigger on it
- end
-
- homedir = file.collapsepath(homedir)
-
- ossetenv("HOME", homedir) -- can be used in unix cnf files
- ossetenv("USERPROFILE",homedir) -- can be used in windows cnf files
-
- environment.homedir = homedir
-
-end
-
--- The following code sets the name of the own binary and its
--- path. This is fallback code as we have os.selfdir now.
-
-do
-
- local args = environment.originalarguments or arg -- this needs a cleanup
-
- local ownbin = environment.ownbin or args[-2] or arg[-2] or args[-1] or arg[-1] or arg[0] or "luatex"
- local ownpath = environment.ownpath or os.selfdir
-
- ownbin = file.collapsepath(ownbin)
- ownpath = file.collapsepath(ownpath)
-
- if not ownpath or ownpath == "" or ownpath == "unset" then
- ownpath = args[-1] or arg[-1]
- ownpath = ownpath and filedirname(gsub(ownpath,"\\","/"))
- if not ownpath or ownpath == "" then
- ownpath = args[-0] or arg[-0]
- ownpath = ownpath and filedirname(gsub(ownpath,"\\","/"))
- end
- local binary = ownbin
- if not ownpath or ownpath == "" then
- ownpath = ownpath and filedirname(binary)
- end
- if not ownpath or ownpath == "" then
- if os.binsuffix ~= "" then
- binary = file.replacesuffix(binary,os.binsuffix)
- end
- local path = osgetenv("PATH")
- if path then
- for p in gmatch(path,"[^"..io.pathseparator.."]+") do
- local b = filejoin(p,binary)
- if lfs.isfile(b) then
- -- we assume that after changing to the path the currentdir function
- -- resolves to the real location and use this side effect here; this
- -- trick is needed because on the mac installations use symlinks in the
- -- path instead of real locations
- local olddir = lfs.currentdir()
- if lfs.chdir(p) then
- local pp = lfs.currentdir()
- if trace_locating and p ~= pp then
- report_initialization("following symlink '%s' to '%s'",p,pp)
- end
- ownpath = pp
- lfs.chdir(olddir)
- else
- if trace_locating then
- report_initialization("unable to check path '%s'",p)
- end
- ownpath = p
- end
- break
- end
- end
- end
- end
- if not ownpath or ownpath == "" then
- ownpath = "."
- report_initialization("forcing fallback ownpath .")
- elseif trace_locating then
- report_initialization("using ownpath '%s'",ownpath)
- end
- end
-
- environment.ownbin = ownbin
- environment.ownpath = ownpath
-
-end
-
-resolvers.ownpath = environment.ownpath
-
-function resolvers.getownpath()
- return environment.ownpath
-end
-
--- The self variables permit us to use only a few (or even no)
--- environment variables.
-
-do
-
- local ownpath = environment.ownpath or dir.current()
-
- if ownpath then
- ossetenv('SELFAUTOLOC', file.collapsepath(ownpath))
- ossetenv('SELFAUTODIR', file.collapsepath(ownpath .. "/.."))
- ossetenv('SELFAUTOPARENT', file.collapsepath(ownpath .. "/../.."))
- else
- report_initialization("error: unable to locate ownpath")
- os.exit()
- end
-
-end
-
--- The running os:
-
--- todo: check is context sits here os.platform is more trustworthy
--- that the bin check as mtx-update runs from another path
-
-local texos = environment.texos or osgetenv("TEXOS")
-local texmfos = environment.texmfos or osgetenv('SELFAUTODIR')
-
-if not texos or texos == "" then
- texos = file.basename(texmfos)
-end
-
-ossetenv('TEXMFOS', texmfos) -- full bin path
-ossetenv('TEXOS', texos) -- partial bin parent
-ossetenv('SELFAUTOSYSTEM',os.platform) -- bonus
-
-environment.texos = texos
-environment.texmfos = texmfos
-
--- The current root:
-
-local texroot = environment.texroot or osgetenv("TEXROOT")
-
-if not texroot or texroot == "" then
- texroot = osgetenv('SELFAUTOPARENT')
- ossetenv('TEXROOT',texroot)
-end
-
-environment.texroot = file.collapsepath(texroot)
-
--- Tracing. Todo ...
-
-function resolvers.settrace(n) -- no longer number but: 'locating' or 'detail'
- if n then
- trackers.disable("resolvers.*")
- trackers.enable("resolvers."..n)
- end
-end
-
-resolvers.settrace(osgetenv("MTX_INPUT_TRACE"))
-
--- todo:
-
--- if profiler and osgetenv("MTX_PROFILE_RUN") == "YES" then
--- profiler.start("luatex-profile.log")
--- end
-
--- a forward definition
-
-if not resolvers.resolve then
- function resolvers.resolve (s) return s end
- function resolvers.unresolve(s) return s end
- function resolvers.repath (s) return s end
-end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['data-exp'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files",
-}
-
-local format, find, gmatch, lower, char, sub = string.format, string.find, string.gmatch, string.lower, string.char, string.sub
-local concat, sort = table.concat, table.sort
-local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
-local Ct, Cs, Cc, P, C, S = lpeg.Ct, lpeg.Cs, lpeg.Cc, lpeg.P, lpeg.C, lpeg.S
-local type, next = type, next
-
-local ostype = os.type
-local collapsepath = file.collapsepath
-
-local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
-local trace_expansions = false trackers.register("resolvers.expansions", function(v) trace_expansions = v end)
-
-local report_expansions = logs.reporter("resolvers","expansions")
-
-local resolvers = resolvers
-
--- As this bit of code is somewhat special it gets its own module. After
--- all, when working on the main resolver code, I don't want to scroll
--- past this every time. See data-obs.lua for the gsub variant.
-
-local function f_first(a,b)
- local t, n = { }, 0
- for s in gmatch(b,"[^,]+") do
- n = n + 1 ; t[n] = a .. s
- end
- return concat(t,",")
-end
-
-local function f_second(a,b)
- local t, n = { }, 0
- for s in gmatch(a,"[^,]+") do
- n = n + 1 ; t[n] = s .. b
- end
- return concat(t,",")
-end
-
--- kpsewhich --expand-braces '{a,b}{c,d}'
--- ac:bc:ad:bd
-
--- old {a,b}{c,d} => ac ad bc bd
---
--- local function f_both(a,b)
--- local t, n = { }, 0
--- for sa in gmatch(a,"[^,]+") do
--- for sb in gmatch(b,"[^,]+") do
--- n = n + 1 ; t[n] = sa .. sb
--- end
--- end
--- return concat(t,",")
--- end
---
--- new {a,b}{c,d} => ac bc ad bd
-
-local function f_both(a,b)
- local t, n = { }, 0
- for sb in gmatch(b,"[^,]+") do -- and not sa
- for sa in gmatch(a,"[^,]+") do -- sb
- n = n + 1 ; t[n] = sa .. sb
- end
- end
- return concat(t,",")
-end
-
-local left = P("{")
-local right = P("}")
-local var = P((1 - S("{}" ))^0)
-local set = P((1 - S("{},"))^0)
-local other = P(1)
-
-local l_first = Cs( ( Cc("{") * (C(set) * left * C(var) * right / f_first) * Cc("}") + other )^0 )
-local l_second = Cs( ( Cc("{") * (left * C(var) * right * C(set) / f_second) * Cc("}") + other )^0 )
-local l_both = Cs( ( Cc("{") * (left * C(var) * right * left * C(var) * right / f_both) * Cc("}") + other )^0 )
-local l_rest = Cs( ( left * var * (left/"") * var * (right/"") * var * right + other )^0 )
-
-local stripper_1 = lpeg.stripper ("{}@")
-local replacer_1 = lpeg.replacer { { ",}", ",@}" }, { "{,", "{@," }, }
-
-local function splitpathexpr(str, newlist, validate) -- I couldn't resist lpegging it (nice exercise).
- if trace_expansions then
- report_expansions("expanding variable '%s'",str)
- end
- local t, ok, done = newlist or { }, false, false
- local n = #t
- str = lpegmatch(replacer_1,str)
- repeat
- local old = str
- repeat
- local old = str
- str = lpegmatch(l_first, str)
- until old == str
- repeat
- local old = str
- str = lpegmatch(l_second,str)
- until old == str
- repeat
- local old = str
- str = lpegmatch(l_both, str)
- until old == str
- repeat
- local old = str
- str = lpegmatch(l_rest, str)
- until old == str
- until old == str -- or not find(str,"{")
- str = lpegmatch(stripper_1,str)
- if validate then
- for s in gmatch(str,"[^,]+") do
- s = validate(s)
- if s then
- n = n + 1 ; t[n] = s
- end
- end
- else
- for s in gmatch(str,"[^,]+") do
- n = n + 1 ; t[n] = s
- end
- end
- if trace_expansions then
- for k=1,#t do
- report_expansions("% 4i: %s",k,t[k])
- end
- end
- return t
-end
-
--- We could make the previous one public.
-
-local function validate(s)
- s = collapsepath(s) -- already keeps the //
- return s ~= "" and not find(s,"^!*unset/*$") and s
-end
-
-resolvers.validatedpath = validate -- keeps the trailing //
-
-function resolvers.expandedpathfromlist(pathlist)
- local newlist = { }
- for k=1,#pathlist do
- splitpathexpr(pathlist[k],newlist,validate)
- end
- return newlist
-end
-
--- {a,b,c,d}
--- a,b,c/{p,q,r},d
--- a,b,c/{p,q,r}/d/{x,y,z}//
--- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
--- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
--- a{b,c}{d,e}f
--- {a,b,c,d}
--- {a,b,c/{p,q,r},d}
--- {a,b,c/{p,q,r}/d/{x,y,z}//}
--- {a,b,c/{p,q/{x,y,z}},d/{p,q,r}}
--- {a,b,c/{p,q/{x,y,z},w}v,d/{p,q,r}}
--- {$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,.local,}/web2c}
-
-local cleanup = lpeg.replacer {
- { "!" , "" },
- { "\\" , "/" },
-}
-
-function resolvers.cleanpath(str) -- tricky, maybe only simple paths
- local doslashes = (P("\\")/"/" + 1)^0
- local donegation = (P("!") /"" )^0
- local homedir = lpegmatch(Cs(donegation * doslashes),environment.homedir or "")
- if homedir == "~" or homedir == "" or not lfs.isdir(homedir) then
- if trace_expansions then
- report_expansions("no home dir set, ignoring dependent paths")
- end
- function resolvers.cleanpath(str)
- if not str or find(str,"~") then
- return "" -- special case
- else
- return lpegmatch(cleanup,str)
- end
- end
- else
- local dohome = ((P("~")+P("$HOME"))/homedir)^0
- local cleanup = Cs(donegation * dohome * doslashes)
- function resolvers.cleanpath(str)
- return str and lpegmatch(cleanup,str) or ""
- end
- end
- return resolvers.cleanpath(str)
-end
-
--- print(resolvers.cleanpath(""))
--- print(resolvers.cleanpath("!"))
--- print(resolvers.cleanpath("~"))
--- print(resolvers.cleanpath("~/test"))
--- print(resolvers.cleanpath("!~/test"))
--- print(resolvers.cleanpath("~/test~test"))
-
--- This one strips quotes and funny tokens.
-
-local expandhome = P("~") / "$HOME" -- environment.homedir
-
-local dodouble = P('"')/"" * (expandhome + (1 - P('"')))^0 * P('"')/""
-local dosingle = P("'")/"" * (expandhome + (1 - P("'")))^0 * P("'")/""
-local dostring = (expandhome + 1 )^0
-
-local stripper = Cs(
- lpegpatterns.unspacer * (dosingle + dodouble + dostring) * lpegpatterns.unspacer
-)
-
-function resolvers.checkedvariable(str) -- assumes str is a string
- return type(str) == "string" and lpegmatch(stripper,str) or str
-end
-
--- The path splitter:
-
--- A config (optionally) has the paths split in tables. Internally
--- we join them and split them after the expansion has taken place. This
--- is more convenient.
-
-local cache = { }
-
------ splitter = lpeg.tsplitat(S(ostype == "windows" and ";" or ":;")) -- maybe add ,
-local splitter = lpeg.tsplitat(";") -- as we move towards urls, prefixes and use tables we no longer do :
-
-local backslashswapper = lpeg.replacer("\\","/")
-
-local function splitconfigurationpath(str) -- beware, this can be either a path or a { specification }
- if str then
- local found = cache[str]
- if not found then
- if str == "" then
- found = { }
- else
- local split = lpegmatch(splitter,lpegmatch(backslashswapper,str)) -- can be combined
- found = { }
- local noffound = 0
- for i=1,#split do
- local s = split[i]
- if not find(s,"^{*unset}*") then
- noffound = noffound + 1
- found[noffound] = s
- end
- end
- if trace_expansions then
- report_expansions("splitting path specification '%s'",str)
- for k=1,noffound do
- report_expansions("% 4i: %s",k,found[k])
- end
- end
- cache[str] = found
- end
- end
- return found
- end
-end
-
-resolvers.splitconfigurationpath = splitconfigurationpath
-
-function resolvers.splitpath(str)
- if type(str) == 'table' then
- return str
- else
- return splitconfigurationpath(str)
- end
-end
-
-function resolvers.joinpath(str)
- if type(str) == 'table' then
- return file.joinpath(str)
- else
- return str
- end
-end
-
--- The next function scans directories and returns a hash where the
--- entries are either strings or tables.
-
--- starting with . or .. etc or funny char
-
-
-
-
--- a lot of this caching can be stripped away when we have ssd's everywhere
---
--- we could cache all the (sub)paths here if needed
-
-local attributes, directory = lfs.attributes, lfs.dir
-
-local weird = P(".")^1 + lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
-local timer = { }
-local scanned = { }
-local nofscans = 0
-local scancache = { }
-
-local function scan(files,spec,path,n,m,r)
- local full = (path == "" and spec) or (spec .. path .. '/')
- local dirs = { }
- local nofdirs = 0
- for name in directory(full) do
- if not lpegmatch(weird,name) then
- local mode = attributes(full..name,'mode')
- if mode == 'file' then
- n = n + 1
- local f = files[name]
- if f then
- if type(f) == 'string' then
- files[name] = { f, path }
- else
- f[#f+1] = path
- end
- else -- probably unique anyway
- files[name] = path
- local lower = lower(name)
- if name ~= lower then
- files["remap:"..lower] = name
- r = r + 1
- end
- end
- elseif mode == 'directory' then
- m = m + 1
- nofdirs = nofdirs + 1
- if path ~= "" then
- dirs[nofdirs] = path..'/'..name
- else
- dirs[nofdirs] = name
- end
- end
- end
- end
- if nofdirs > 0 then
- sort(dirs)
- for i=1,nofdirs do
- files, n, m, r = scan(files,spec,dirs[i],n,m,r)
- end
- end
- scancache[sub(full,1,-2)] = files
- return files, n, m, r
-end
-
-local fullcache = { }
-
-function resolvers.scanfiles(path,branch,usecache)
- statistics.starttiming(timer)
- local realpath = resolvers.resolve(path) -- no shortcut
- if usecache then
- local files = fullcache[realpath]
- if files then
- if trace_locating then
- report_expansions("using caches scan of path '%s', branch '%s'",path,branch or path)
- end
- return files
- end
- end
- if trace_locating then
- report_expansions("scanning path '%s', branch '%s'",path,branch or path)
- end
- local files, n, m, r = scan({ },realpath .. '/',"",0,0,0)
- files.__path__ = path -- can be selfautoparent:texmf-whatever
- files.__files__ = n
- files.__directories__ = m
- files.__remappings__ = r
- if trace_locating then
- report_expansions("%s files found on %s directories with %s uppercase remappings",n,m,r)
- end
- if usecache then
- scanned[#scanned+1] = realpath
- fullcache[realpath] = files
- end
- nofscans = nofscans + 1
- statistics.stoptiming(timer)
- return files
-end
-
-local function simplescan(files,spec,path) -- first match only, no map and such
- local full = (path == "" and spec) or (spec .. path .. '/')
- local dirs = { }
- local nofdirs = 0
- for name in directory(full) do
- if not lpegmatch(weird,name) then
- local mode = attributes(full..name,'mode')
- if mode == 'file' then
- if not files[name] then
- -- only first match
- files[name] = path
- end
- elseif mode == 'directory' then
- nofdirs = nofdirs + 1
- if path ~= "" then
- dirs[nofdirs] = path..'/'..name
- else
- dirs[nofdirs] = name
- end
- end
- end
- end
- if nofdirs > 0 then
- sort(dirs)
- for i=1,nofdirs do
- files = simplescan(files,spec,dirs[i])
- end
- end
- return files
-end
-
-local simplecache = { }
-local nofsharedscans = 0
-
-function resolvers.simplescanfiles(path,branch,usecache)
- statistics.starttiming(timer)
- local realpath = resolvers.resolve(path) -- no shortcut
- if usecache then
- local files = simplecache[realpath]
- if not files then
- files = scancache[realpath]
- if files then
- nofsharedscans = nofsharedscans + 1
- end
- end
- if files then
- if trace_locating then
- report_expansions("using caches scan of path '%s', branch '%s'",path,branch or path)
- end
- return files
- end
- end
- if trace_locating then
- report_expansions("scanning path '%s', branch '%s'",path,branch or path)
- end
- local files = simplescan({ },realpath .. '/',"")
- if trace_locating then
- report_expansions("%s files found",table.count(files))
- end
- if usecache then
- scanned[#scanned+1] = realpath
- simplecache[realpath] = files
- end
- nofscans = nofscans + 1
- statistics.stoptiming(timer)
- return files
-end
-
-function resolvers.scandata()
- table.sort(scanned)
- return {
- n = nofscans,
- shared = nofsharedscans,
- time = statistics.elapsedtime(timer),
- paths = scanned,
- }
-end
-
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['data-env'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files",
-}
-
-local lower, gsub = string.lower, string.gsub
-
-local resolvers = resolvers
-
-local allocate = utilities.storage.allocate
-local setmetatableindex = table.setmetatableindex
-local fileextname = file.extname
-
-local formats = allocate()
-local suffixes = allocate()
-local dangerous = allocate()
-local suffixmap = allocate()
-
-resolvers.formats = formats
-resolvers.suffixes = suffixes
-resolvers.dangerous = dangerous
-resolvers.suffixmap = suffixmap
-
-local relations = allocate { -- todo: handlers also here
- core = {
- ofm = { -- will become obsolete
- names = { "ofm", "omega font metric", "omega font metrics" },
- variable = 'OFMFONTS',
- suffixes = { 'ofm', 'tfm' },
- },
- ovf = { -- will become obsolete
- names = { "ovf", "omega virtual font", "omega virtual fonts" },
- variable = 'OVFFONTS',
- suffixes = { 'ovf', 'vf' },
- },
- tfm = {
- names = { "tfm", "tex font metric", "tex font metrics" },
- variable = 'TFMFONTS',
- suffixes = { 'tfm' },
- },
- vf = {
- names = { "vf", "virtual font", "virtual fonts" },
- variable = 'VFFONTS',
- suffixes = { 'vf' },
- },
- otf = {
- names = { "otf", "opentype", "opentype font", "opentype fonts"},
- variable = 'OPENTYPEFONTS',
- suffixes = { 'otf' },
- },
- ttf = {
- names = { "ttf", "truetype", "truetype font", "truetype fonts", "truetype collection", "truetype collections", "truetype dictionary", "truetype dictionaries" },
- variable = 'TTFONTS',
- suffixes = { 'ttf', 'ttc', 'dfont' },
- },
- afm = {
- names = { "afm", "adobe font metric", "adobe font metrics" },
- variable = "AFMFONTS",
- suffixes = { "afm" },
- },
- pfb = {
- names = { "pfb", "type1", "type 1", "type1 font", "type 1 font", "type1 fonts", "type 1 fonts" },
- variable = 'T1FONTS',
- suffixes = { 'pfb', 'pfa' },
- },
- fea = {
- names = { "fea", "font feature", "font features", "font feature file", "font feature files" },
- variable = 'FONTFEATURES',
- suffixes = { 'fea' },
- },
- cid = {
- names = { "cid", "cid map", "cid maps", "cid file", "cid files" },
- variable = 'FONTCIDMAPS',
- suffixes = { 'cid', 'cidmap' },
- },
- fmt = {
- names = { "fmt", "format", "tex format" },
- variable = 'TEXFORMATS',
- suffixes = { 'fmt' },
- },
- mem = { -- will become obsolete
- names = { 'mem', "metapost format" },
- variable = 'MPMEMS',
- suffixes = { 'mem' },
- },
- mp = {
- names = { "mp" },
- variable = 'MPINPUTS',
- suffixes = { 'mp', 'mpvi', 'mpiv', 'mpii' },
- },
- tex = {
- names = { "tex" },
- variable = 'TEXINPUTS',
- suffixes = { 'tex', "mkvi", "mkiv", "mkii" },
- },
- icc = {
- names = { "icc", "icc profile", "icc profiles" },
- variable = 'ICCPROFILES',
- suffixes = { 'icc' },
- },
- texmfscripts = {
- names = { "texmfscript", "texmfscripts", "script", "scripts" },
- variable = 'TEXMFSCRIPTS',
- suffixes = { 'rb', 'pl', 'py' },
- },
- lua = {
- names = { "lua" },
- variable = 'LUAINPUTS',
- suffixes = { 'lua', 'luc', 'tma', 'tmc' },
- },
- lib = {
- names = { "lib" },
- variable = 'CLUAINPUTS',
- suffixes = os.libsuffix and { os.libsuffix } or { 'dll', 'so' },
- },
- bib = {
- names = { 'bib' },
- suffixes = { 'bib' },
- },
- bst = {
- names = { 'bst' },
- suffixes = { 'bst' },
- },
- fontconfig = {
- names = { 'fontconfig', 'fontconfig file', 'fontconfig files' },
- variable = 'FONTCONFIG_PATH',
- },
- },
- obsolete = {
- enc = {
- names = { "enc", "enc files", "enc file", "encoding files", "encoding file" },
- variable = 'ENCFONTS',
- suffixes = { 'enc' },
- },
- map = {
- names = { "map", "map files", "map file" },
- variable = 'TEXFONTMAPS',
- suffixes = { 'map' },
- },
- lig = {
- names = { "lig files", "lig file", "ligature file", "ligature files" },
- variable = 'LIGFONTS',
- suffixes = { 'lig' },
- },
- opl = {
- names = { "opl" },
- variable = 'OPLFONTS',
- suffixes = { 'opl' },
- },
- ovp = {
- names = { "ovp" },
- variable = 'OVPFONTS',
- suffixes = { 'ovp' },
- },
- },
- kpse = { -- subset
- base = {
- names = { 'base', "metafont format" },
- variable = 'MFBASES',
- suffixes = { 'base', 'bas' },
- },
- cmap = {
- names = { 'cmap', 'cmap files', 'cmap file' },
- variable = 'CMAPFONTS',
- suffixes = { 'cmap' },
- },
- cnf = {
- names = { 'cnf' },
- suffixes = { 'cnf' },
- },
- web = {
- names = { 'web' },
- suffixes = { 'web', 'ch' }
- },
- cweb = {
- names = { 'cweb' },
- suffixes = { 'w', 'web', 'ch' },
- },
- gf = {
- names = { 'gf' },
- suffixes = { 'gf' },
- },
- mf = {
- names = { 'mf' },
- variable = 'MFINPUTS',
- suffixes = { 'mf' },
- },
- mft = {
- names = { 'mft' },
- suffixes = { 'mft' },
- },
- pk = {
- names = { 'pk' },
- suffixes = { 'pk' },
- },
- },
-}
-
-resolvers.relations = relations
-
--- formats: maps a format onto a variable
-
-function resolvers.updaterelations()
- for category, categories in next, relations do
- for name, relation in next, categories do
- local rn = relation.names
- local rv = relation.variable
- local rs = relation.suffixes
- if rn and rv then
- for i=1,#rn do
- local rni = lower(gsub(rn[i]," ",""))
- formats[rni] = rv
- if rs then
- suffixes[rni] = rs
- for i=1,#rs do
- local rsi = rs[i]
- suffixmap[rsi] = rni
- end
- end
- end
- end
- if rs then
- end
- end
- end
-end
-
-resolvers.updaterelations() -- push this in the metatable -> newindex
-
-local function simplified(t,k)
- return k and rawget(t,lower(gsub(k," ",""))) or nil
-end
-
-setmetatableindex(formats, simplified)
-setmetatableindex(suffixes, simplified)
-setmetatableindex(suffixmap, simplified)
-
--- A few accessors, mostly for command line tool.
-
-function resolvers.suffixofformat(str)
- local s = suffixes[str]
- return s and s[1] or ""
-end
-
-function resolvers.suffixofformat(str)
- return suffixes[str] or { }
-end
-
-for name, format in next, formats do
- dangerous[name] = true -- still needed ?
-end
-
--- because vf searching is somewhat dangerous, we want to prevent
--- too liberal searching esp because we do a lookup on the current
--- path anyway; only tex (or any) is safe
-
-dangerous.tex = nil
-
-
--- more helpers
-
-function resolvers.formatofvariable(str)
- return formats[str] or ''
-end
-
-function resolvers.formatofsuffix(str) -- of file
- return suffixmap[fileextname(str)] or 'tex' -- so many map onto tex (like mkiv, cld etc)
-end
-
-function resolvers.variableofformat(str)
- return formats[str] or ''
-end
-
-function resolvers.variableofformatorsuffix(str)
- local v = formats[str]
- if v then
- return v
- end
- v = suffixmap[fileextname(str)]
- if v then
- return formats[v]
- end
- return ''
-end
-
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['data-tmp'] = {
- version = 1.100,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
---[[ldx--
-This module deals with caching data. It sets up the paths and
-implements loaders and savers for tables. Best is to set the
-following variable. When not set, the usual paths will be
-checked. Personally I prefer the (users) temporary path.
-
-
-TEXMFCACHE=$TMP;$TEMP;$TMPDIR;$TEMPDIR;$HOME;$TEXMFVAR;$VARTEXMF;.
-
-
-Currently we do no locking when we write files. This is no real
-problem because most caching involves fonts and the chance of them
-being written at the same time is small. We also need to extend
-luatools with a recache feature.
---ldx]]--
-
-local format, lower, gsub, concat = string.format, string.lower, string.gsub, table.concat
-local serialize, serializetofile = table.serialize, table.tofile
-local mkdirs, isdir = dir.mkdirs, lfs.isdir
-
-local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
-local trace_cache = false trackers.register("resolvers.cache", function(v) trace_cache = v end)
-
-local report_caches = logs.reporter("resolvers","caches")
-local report_resolvers = logs.reporter("resolvers","caching")
-
-local resolvers = resolvers
-
--- intermezzo
-
-local directive_cleanup = false directives.register("system.compile.cleanup", function(v) directive_cleanup = v end)
-local directive_strip = true directives.register("system.compile.strip", function(v) directive_strip = v end)
-
-local compile = utilities.lua.compile
-
-function utilities.lua.compile(luafile,lucfile,cleanup,strip)
- if cleanup == nil then cleanup = directive_cleanup end
- if strip == nil then strip = directive_strip end
- return compile(luafile,lucfile,cleanup,strip)
-end
-
--- end of intermezzo
-
-caches = caches or { }
-local caches = caches
-
-caches.base = caches.base or "luatex-cache"
-caches.more = caches.more or "context"
-caches.direct = false -- true is faster but may need huge amounts of memory
-caches.tree = false
-caches.force = true
-caches.ask = false
-caches.relocate = false
-caches.defaults = { "TMPDIR", "TEMPDIR", "TMP", "TEMP", "HOME", "HOMEPATH" }
-
-local writable, readables, usedreadables = nil, { }, { }
-
--- we could use a metatable for writable and readable but not yet
-
-local function identify()
- -- Combining the loops makes it messy. First we check the format cache path
- -- and when the last component is not present we try to create it.
- local texmfcaches = resolvers.cleanpathlist("TEXMFCACHE")
- if texmfcaches then
- for k=1,#texmfcaches do
- local cachepath = texmfcaches[k]
- if cachepath ~= "" then
- cachepath = resolvers.resolve(cachepath)
- cachepath = resolvers.cleanpath(cachepath)
- cachepath = file.collapsepath(cachepath)
- local valid = isdir(cachepath)
- if valid then
- if file.is_readable(cachepath) then
- readables[#readables+1] = cachepath
- if not writable and file.is_writable(cachepath) then
- writable = cachepath
- end
- end
- elseif not writable and caches.force then
- local cacheparent = file.dirname(cachepath)
- if file.is_writable(cacheparent) and true then -- we go on anyway (needed for mojca's kind of paths)
- if not caches.ask or io.ask(format("\nShould I create the cache path %s?",cachepath), "no", { "yes", "no" }) == "yes" then
- mkdirs(cachepath)
- if isdir(cachepath) and file.is_writable(cachepath) then
- report_caches("created: %s",cachepath)
- writable = cachepath
- readables[#readables+1] = cachepath
- end
- end
- end
- end
- end
- end
- end
- -- As a last resort we check some temporary paths but this time we don't
- -- create them.
- local texmfcaches = caches.defaults
- if texmfcaches then
- for k=1,#texmfcaches do
- local cachepath = texmfcaches[k]
- cachepath = resolvers.expansion(cachepath) -- was getenv
- if cachepath ~= "" then
- cachepath = resolvers.resolve(cachepath)
- cachepath = resolvers.cleanpath(cachepath)
- local valid = isdir(cachepath)
- if valid and file.is_readable(cachepath) then
- if not writable and file.is_writable(cachepath) then
- readables[#readables+1] = cachepath
- writable = cachepath
- break
- end
- end
- end
- end
- end
- -- Some extra checking. If we have no writable or readable path then we simply
- -- quit.
- if not writable then
- report_caches("fatal error: there is no valid writable cache path defined")
- os.exit()
- elseif #readables == 0 then
- report_caches("fatal error: there is no valid readable cache path defined")
- os.exit()
- end
- -- why here
- writable = dir.expandname(resolvers.cleanpath(writable)) -- just in case
- -- moved here
- local base, more, tree = caches.base, caches.more, caches.tree or caches.treehash() -- we have only one writable tree
- if tree then
- caches.tree = tree
- writable = mkdirs(writable,base,more,tree)
- for i=1,#readables do
- readables[i] = file.join(readables[i],base,more,tree)
- end
- else
- writable = mkdirs(writable,base,more)
- for i=1,#readables do
- readables[i] = file.join(readables[i],base,more)
- end
- end
- -- end
- if trace_cache then
- for i=1,#readables do
- report_caches("using readable path '%s' (order %s)",readables[i],i)
- end
- report_caches("using writable path '%s'",writable)
- end
- identify = function()
- return writable, readables
- end
- return writable, readables
-end
-
-function caches.usedpaths()
- local writable, readables = identify()
- if #readables > 1 then
- local result = { }
- for i=1,#readables do
- local readable = readables[i]
- if usedreadables[i] or readable == writable then
- result[#result+1] = format("readable: '%s' (order %s)",readable,i)
- end
- end
- result[#result+1] = format("writable: '%s'",writable)
- return result
- else
- return writable
- end
-end
-
-function caches.configfiles()
- return concat(resolvers.instance.specification,";")
-end
-
-function caches.hashed(tree)
- tree = gsub(tree,"\\$","/")
- tree = gsub(tree,"/+$","")
- tree = lower(tree)
- local hash = md5.hex(tree)
- if trace_cache or trace_locating then
- report_caches("hashing tree %s, hash %s",tree,hash)
- end
- return hash
-end
-
-function caches.treehash()
- local tree = caches.configfiles()
- if not tree or tree == "" then
- return false
- else
- return caches.hashed(tree)
- end
-end
-
-local r_cache, w_cache = { }, { } -- normally w in in r but who cares
-
-local function getreadablepaths(...) -- we can optimize this as we have at most 2 tags
- local tags = { ... }
- local hash = concat(tags,"/")
- local done = r_cache[hash]
- if not done then
- local writable, readables = identify() -- exit if not found
- if #tags > 0 then
- done = { }
- for i=1,#readables do
- done[i] = file.join(readables[i],...)
- end
- else
- done = readables
- end
- r_cache[hash] = done
- end
- return done
-end
-
-local function getwritablepath(...)
- local tags = { ... }
- local hash = concat(tags,"/")
- local done = w_cache[hash]
- if not done then
- local writable, readables = identify() -- exit if not found
- if #tags > 0 then
- done = mkdirs(writable,...)
- else
- done = writable
- end
- w_cache[hash] = done
- end
- return done
-end
-
-caches.getreadablepaths = getreadablepaths
-caches.getwritablepath = getwritablepath
-
-function caches.getfirstreadablefile(filename,...)
- local rd = getreadablepaths(...)
- for i=1,#rd do
- local path = rd[i]
- local fullname = file.join(path,filename)
- if file.is_readable(fullname) then
- usedreadables[i] = true
- return fullname, path
- end
- end
- return caches.setfirstwritablefile(filename,...)
-end
-
-function caches.setfirstwritablefile(filename,...)
- local wr = getwritablepath(...)
- local fullname = file.join(wr,filename)
- return fullname, wr
-end
-
-function caches.define(category,subcategory) -- for old times sake
- return function()
- return getwritablepath(category,subcategory)
- end
-end
-
-function caches.setluanames(path,name)
- return path .. "/" .. name .. ".tma", path .. "/" .. name .. ".tmc"
-end
-
-function caches.loaddata(readables,name)
- if type(readables) == "string" then
- readables = { readables }
- end
- for i=1,#readables do
- local path = readables[i]
- local tmaname, tmcname = caches.setluanames(path,name)
- local loader = loadfile(tmcname) or loadfile(tmaname)
- if loader then
- loader = loader()
- collectgarbage("step")
- return loader
- end
- end
- return false
-end
-
-function caches.is_writable(filepath,filename)
- local tmaname, tmcname = caches.setluanames(filepath,filename)
- return file.is_writable(tmaname)
-end
-
-local saveoptions = { compact = true }
-
-function caches.savedata(filepath,filename,data,raw)
- local tmaname, tmcname = caches.setluanames(filepath,filename)
- local reduce, simplify = true, true
- if raw then
- reduce, simplify = false, false
- end
- data.cache_uuid = os.uuid()
- if caches.direct then
- file.savedata(tmaname,serialize(data,true,saveoptions))
- else
- serializetofile(tmaname,data,true,saveoptions)
- end
- utilities.lua.compile(tmaname,tmcname)
-end
-
--- moved from data-res:
-
-local content_state = { }
-
-function caches.contentstate()
- return content_state or { }
-end
-
-function caches.loadcontent(cachename,dataname)
- local name = caches.hashed(cachename)
- local full, path = caches.getfirstreadablefile(name ..".lua","trees")
- local filename = file.join(path,name)
- local blob = loadfile(filename .. ".luc") or loadfile(filename .. ".lua")
- if blob then
- local data = blob()
- if data and data.content then
- if data.type == dataname then
- if data.version == resolvers.cacheversion then
- content_state[#content_state+1] = data.uuid
- if trace_locating then
- report_resolvers("loading '%s' for '%s' from '%s'",dataname,cachename,filename)
- end
- return data.content
- else
- report_resolvers("skipping '%s' for '%s' from '%s' (version mismatch)",dataname,cachename,filename)
- end
- else
- report_resolvers("skipping '%s' for '%s' from '%s' (datatype mismatch)",dataname,cachename,filename)
- end
- elseif trace_locating then
- report_resolvers("skipping '%s' for '%s' from '%s' (no content)",dataname,cachename,filename)
- end
- elseif trace_locating then
- report_resolvers("skipping '%s' for '%s' from '%s' (invalid file)",dataname,cachename,filename)
- end
-end
-
-function caches.collapsecontent(content)
- for k, v in next, content do
- if type(v) == "table" and #v == 1 then
- content[k] = v[1]
- end
- end
-end
-
-function caches.savecontent(cachename,dataname,content)
- local name = caches.hashed(cachename)
- local full, path = caches.setfirstwritablefile(name ..".lua","trees")
- local filename = file.join(path,name) -- is full
- local luaname, lucname = filename .. ".lua", filename .. ".luc"
- if trace_locating then
- report_resolvers("preparing '%s' for '%s'",dataname,cachename)
- end
- local data = {
- type = dataname,
- root = cachename,
- version = resolvers.cacheversion,
- date = os.date("%Y-%m-%d"),
- time = os.date("%H:%M:%S"),
- content = content,
- uuid = os.uuid(),
- }
- local ok = io.savedata(luaname,serialize(data,true))
- if ok then
- if trace_locating then
- report_resolvers("category '%s', cachename '%s' saved in '%s'",dataname,cachename,luaname)
- end
- if utilities.lua.compile(luaname,lucname) then
- if trace_locating then
- report_resolvers("'%s' compiled to '%s'",dataname,lucname)
- end
- return true
- else
- if trace_locating then
- report_resolvers("compiling failed for '%s', deleting file '%s'",dataname,lucname)
- end
- os.remove(lucname)
- end
- elseif trace_locating then
- report_resolvers("unable to save '%s' in '%s' (access error)",dataname,luaname)
- end
-end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['data-met'] = {
- version = 1.100,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local find, format = string.find, string.format
-local sequenced = table.sequenced
-local addurlscheme, urlhashed = url.addscheme, url.hashed
-
-local trace_locating = false
-
-trackers.register("resolvers.locating", function(v) trace_methods = v end)
-trackers.register("resolvers.methods", function(v) trace_methods = v end)
-
-
-local report_methods = logs.reporter("resolvers","methods")
-
-local allocate = utilities.storage.allocate
-
-local resolvers = resolvers
-
-local registered = { }
-
-local function splitmethod(filename) -- todo: filetype in specification
- if not filename then
- return { scheme = "unknown", original = filename }
- end
- if type(filename) == "table" then
- return filename -- already split
- end
- filename = file.collapsepath(filename)
- if not find(filename,"://") then
- return { scheme = "file", path = filename, original = filename, filename = filename }
- end
- local specification = url.hashed(filename)
- if not specification.scheme or specification.scheme == "" then
- return { scheme = "file", path = filename, original = filename, filename = filename }
- else
- return specification
- end
-end
-
-resolvers.splitmethod = splitmethod -- bad name but ok
-
--- the second argument is always analyzed (saves time later on) and the original
--- gets passed as original but also as argument
-
-local function methodhandler(what,first,...) -- filename can be nil or false
- local method = registered[what]
- if method then
- local how, namespace = method.how, method.namespace
- if how == "uri" or how == "url" then
- local specification = splitmethod(first)
- local scheme = specification.scheme
- local resolver = namespace and namespace[scheme]
- if resolver then
- if trace_methods then
- report_methods("resolver: method=%s, how=%s, scheme=%s, argument=%s",what,how,scheme,first)
- end
- return resolver(specification,...)
- else
- resolver = namespace.default or namespace.file
- if resolver then
- if trace_methods then
- report_methods("resolver: method=%s, how=%s, default, argument=%s",what,how,first)
- end
- return resolver(specification,...)
- elseif trace_methods then
- report_methods("resolver: method=%s, how=%s, no handler",what,how)
- end
- end
- elseif how == "tag" then
- local resolver = namespace and namespace[first]
- if resolver then
- if trace_methods then
- report_methods("resolver: method=%s, how=%s, tag=%s",what,how,first)
- end
- return resolver(...)
- else
- resolver = namespace.default or namespace.file
- if resolver then
- if trace_methods then
- report_methods("resolver: method=%s, how=%s, default",what,how)
- end
- return resolver(...)
- elseif trace_methods then
- report_methods("resolver: method=%s, how=%s, unknown",what,how)
- end
- end
- end
- else
- report_methods("resolver: method=%s, unknown",what)
- end
-end
-
-resolvers.methodhandler = methodhandler
-
-function resolvers.registermethod(name,namespace,how)
- registered[name] = { how = how or "tag", namespace = namespace }
- namespace["byscheme"] = function(scheme,filename,...)
- if scheme == "file" then
- return methodhandler(name,filename,...)
- else
- return methodhandler(name,addurlscheme(filename,scheme),...)
- end
- end
-end
-
-local concatinators = allocate { notfound = file.join } -- concatinate paths
-local locators = allocate { notfound = function() end } -- locate databases
-local hashers = allocate { notfound = function() end } -- load databases
-local generators = allocate { notfound = function() end } -- generate databases
-
-resolvers.concatinators = concatinators
-resolvers.locators = locators
-resolvers.hashers = hashers
-resolvers.generators = generators
-
-local registermethod = resolvers.registermethod
-
-registermethod("concatinators",concatinators,"tag")
-registermethod("locators", locators, "uri")
-registermethod("hashers", hashers, "uri")
-registermethod("generators", generators, "uri")
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['data-res'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files",
-}
-
--- In practice we will work within one tds tree, but i want to keep
--- the option open to build tools that look at multiple trees, which is
--- why we keep the tree specific data in a table. We used to pass the
--- instance but for practical purposes we now avoid this and use a
--- instance variable. We always have one instance active (sort of global).
-
--- todo: cache:/// home:/// selfautoparent:/// (sometime end 2012)
-
-local format, gsub, find, lower, upper, match, gmatch = string.format, string.gsub, string.find, string.lower, string.upper, string.match, string.gmatch
-local concat, insert, sortedkeys = table.concat, table.insert, table.sortedkeys
-local next, type, rawget = next, type, rawget
-local os = os
-
-local P, S, R, C, Cc, Cs, Ct, Carg = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.Cc, lpeg.Cs, lpeg.Ct, lpeg.Carg
-local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
-
-local filedirname = file.dirname
-local filebasename = file.basename
-local fileextname = file.extname
-local filejoin = file.join
-local collapsepath = file.collapsepath
-local joinpath = file.joinpath
-local allocate = utilities.storage.allocate
-local setmetatableindex = table.setmetatableindex
-
-local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
-local trace_detail = false trackers.register("resolvers.details", function(v) trace_detail = v end)
-local trace_expansions = false trackers.register("resolvers.expansions", function(v) trace_expansions = v end)
-
-local report_resolving = logs.reporter("resolvers","resolving")
-
-local resolvers = resolvers
-
-local expandedpathfromlist = resolvers.expandedpathfromlist
-local checkedvariable = resolvers.checkedvariable
-local splitconfigurationpath = resolvers.splitconfigurationpath
-local methodhandler = resolvers.methodhandler
-
-local initializesetter = utilities.setters.initialize
-
-local ostype, osname, osenv, ossetenv, osgetenv = os.type, os.name, os.env, os.setenv, os.getenv
-
-resolvers.cacheversion = '1.0.1'
-resolvers.configbanner = ''
-resolvers.homedir = environment.homedir
-resolvers.criticalvars = allocate { "SELFAUTOLOC", "SELFAUTODIR", "SELFAUTOPARENT", "TEXMFCNF", "TEXMF", "TEXOS" }
-resolvers.luacnfname = 'texmfcnf.lua'
-resolvers.luacnfstate = "unknown"
-
--- The web2c tex binaries as well as kpse have built in paths for the configuration
--- files and there can be a depressing truckload of them. This is actually the weak
--- spot of a distribution. So we don't want:
---
--- resolvers.luacnfspec = '{$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,}/web2c}'
---
--- but instead use:
---
--- resolvers.luacnfspec = 'selfautoparent:{/texmf{-local,}{,/web2c}}'
---
--- which does not make texlive happy as there is a texmf-local tree one level up
--- (sigh), so we need this. We can assume web2c as mkiv does not run on older
--- texlives anyway.
---
--- texlive:
---
--- selfautodir:
--- selfautoparent:
--- selfautodir:share/texmf-local/web2c
--- selfautodir:share/texmf/web2c
--- selfautodir:texmf-local/web2c
--- selfautodir:texmf/web2c
--- selfautoparent:share/texmf-local/web2c
--- selfautoparent:share/texmf/web2c
--- selfautoparent:texmf-local/web2c
--- selfautoparent:texmf/web2c
---
--- minimals:
---
--- home:texmf/web2c
--- selfautoparent:texmf-local/web2c
--- selfautoparent:texmf-context/web2c
--- selfautoparent:texmf/web2c
-
-if environment.default_texmfcnf then
- -- unfortunately we now have quite some overkill in the spec (not so nice on a network)
- resolvers.luacnfspec = environment.default_texmfcnf
-else
- -- resolvers.luacnfspec = "selfautoparent:texmf{-local,-context,}/web2c"
- resolvers.luacnfspec = "{selfautoloc:,selfautodir:,selfautoparent:}{,/texmf{-local,}/web2c}"
-end
-
-resolvers.luacnfspec = 'home:texmf/web2c;' .. resolvers.luacnfspec
-
--- which (as we want users to use the web2c path) be can be simplified to this:
---
--- if environment and environment.ownpath and string.find(environment.ownpath,"[\\/]texlive[\\/]") then
--- resolvers.luacnfspec = 'selfautodir:/texmf-local/web2c,selfautoparent:/texmf-local/web2c,selfautoparent:/texmf/web2c'
--- else
--- resolvers.luacnfspec = 'selfautoparent:/texmf-local/web2c,selfautoparent:/texmf/web2c'
--- end
-
-
-
-local unset_variable = "unset"
-
-local formats = resolvers.formats
-local suffixes = resolvers.suffixes
-local dangerous = resolvers.dangerous
-local suffixmap = resolvers.suffixmap
-
-resolvers.defaultsuffixes = { "tex" } -- "mkiv", "cld" -- too tricky
-
-resolvers.instance = resolvers.instance or nil -- the current one (slow access)
-local instance = resolvers.instance or nil -- the current one (fast access)
-
--- An instance has an environment (coming from the outside, kept raw), variables
--- (coming from the configuration file), and expansions (variables with nested
--- variables replaced). One can push something into the outer environment and
--- its internal copy, but only the later one will be the raw unprefixed variant.
-
-function resolvers.setenv(key,value,raw)
- if instance then
- -- this one will be consulted first when we stay inside
- -- the current environment (prefixes are not resolved here)
- instance.environment[key] = value
- -- we feed back into the environment, and as this is used
- -- by other applications (via os.execute) we need to make
- -- sure that prefixes are resolve
- ossetenv(key,raw and value or resolvers.resolve(value))
- end
-end
-
--- Beware we don't want empty here as this one can be called early on
--- and therefore we use rawget.
-
-local function getenv(key)
- local value = rawget(instance.environment,key)
- if value and value ~= "" then
- return value
- else
- local e = osgetenv(key)
- return e ~= nil and e ~= "" and checkedvariable(e) or ""
- end
-end
-
-resolvers.getenv = getenv
-resolvers.env = getenv
-
--- We are going to use some metatable trickery where we backtrack from
--- expansion to variable to environment.
-
-local function resolve(k)
- return instance.expansions[k]
-end
-
-local dollarstripper = lpeg.stripper("$")
-local inhibitstripper = P("!")^0 * Cs(P(1)^0)
-local backslashswapper = lpeg.replacer("\\","/")
-
-local somevariable = P("$") / ""
-local somekey = C(R("az","AZ","09","__","--")^1)
-local somethingelse = P(";") * ((1-S("!{}/\\"))^1 * P(";") / "")
- + P(";") * (P(";") / "")
- + P(1)
-local variableexpander = Cs( (somevariable * (somekey/resolve) + somethingelse)^1 )
-
-local cleaner = P("\\") / "/" + P(";") * S("!{}/\\")^0 * P(";")^1 / ";"
-local variablecleaner = Cs((cleaner + P(1))^0)
-
-local somevariable = R("az","AZ","09","__","--")^1 / resolve
-local variable = (P("$")/"") * (somevariable + (P("{")/"") * somevariable * (P("}")/""))
-local variableresolver = Cs((variable + P(1))^0)
-
-local function expandedvariable(var)
- return lpegmatch(variableexpander,var) or var
-end
-
-function resolvers.newinstance() -- todo: all vars will become lowercase and alphanum only
-
- if trace_locating then
- report_resolving("creating instance")
- end
-
- local environment, variables, expansions, order = allocate(), allocate(), allocate(), allocate()
-
- local newinstance = {
- environment = environment,
- variables = variables,
- expansions = expansions,
- order = order,
- files = allocate(),
- setups = allocate(),
- found = allocate(),
- foundintrees = allocate(),
- hashes = allocate(),
- hashed = allocate(),
- specification = allocate(),
- lists = allocate(),
- data = allocate(), -- only for loading
- fakepaths = allocate(),
- remember = true,
- diskcache = true,
- renewcache = false,
- renewtree = false,
- loaderror = false,
- savelists = true,
- pattern = nil, -- lists
- force_suffixes = true,
- }
-
- setmetatableindex(variables,function(t,k)
- local v
- for i=1,#order do
- v = order[i][k]
- if v ~= nil then
- t[k] = v
- return v
- end
- end
- if v == nil then
- v = ""
- end
- t[k] = v
- return v
- end)
-
- setmetatableindex(environment, function(t,k)
- local v = osgetenv(k)
- if v == nil then
- v = variables[k]
- end
- if v ~= nil then
- v = checkedvariable(v) or ""
- end
- v = resolvers.repath(v) -- for taco who has a : separated osfontdir
- t[k] = v
- return v
- end)
-
- setmetatableindex(expansions, function(t,k)
- local v = environment[k]
- if type(v) == "string" then
- v = lpegmatch(variableresolver,v)
- v = lpegmatch(variablecleaner,v)
- end
- t[k] = v
- return v
- end)
-
- return newinstance
-
-end
-
-function resolvers.setinstance(someinstance) -- only one instance is active
- instance = someinstance
- resolvers.instance = someinstance
- return someinstance
-end
-
-function resolvers.reset()
- return resolvers.setinstance(resolvers.newinstance())
-end
-
-local function reset_hashes()
- instance.lists = { }
- instance.found = { }
-end
-
-local slash = P("/")
-
-local pathexpressionpattern = Cs (
- Cc("^") * (
- Cc("%") * S(".-")
- + slash^2 * P(-1) / "/.*"
- + slash^2 / "/.-/"
- + (1-slash) * P(-1) * Cc("/")
- + P(1)
- )^1 * Cc("$") -- yes or no $
-)
-
-local cache = { }
-
-local function makepathexpression(str)
- if str == "." then
- return "^%./$"
- else
- local c = cache[str]
- if not c then
- c = lpegmatch(pathexpressionpattern,str)
- cache[str] = c
- end
- return c
- end
-end
-
-local function reportcriticalvariables(cnfspec)
- if trace_locating then
- for i=1,#resolvers.criticalvars do
- local k = resolvers.criticalvars[i]
- local v = resolvers.getenv(k) or "unknown" -- this one will not resolve !
- report_resolving("variable '%s' set to '%s'",k,v)
- end
- report_resolving()
- if cnfspec then
- if type(cnfspec) == "table" then
- report_resolving("using configuration specification '%s'",concat(cnfspec,","))
- else
- report_resolving("using configuration specification '%s'",cnfspec)
- end
- end
- report_resolving()
- end
- reportcriticalvariables = function() end
-end
-
-local function identify_configuration_files()
- local specification = instance.specification
- if #specification == 0 then
- local cnfspec = getenv('TEXMFCNF')
- if cnfspec == "" then
- cnfspec = resolvers.luacnfspec
- resolvers.luacnfstate = "default"
- else
- resolvers.luacnfstate = "environment"
- end
- reportcriticalvariables(cnfspec)
- local cnfpaths = expandedpathfromlist(resolvers.splitpath(cnfspec))
- local luacnfname = resolvers.luacnfname
- for i=1,#cnfpaths do
- local filename = collapsepath(filejoin(cnfpaths[i],luacnfname))
- local realname = resolvers.resolve(filename)
- if lfs.isfile(realname) then
- specification[#specification+1] = filename
- if trace_locating then
- report_resolving("found configuration file '%s'",realname)
- end
- elseif trace_locating then
- report_resolving("unknown configuration file '%s'",realname)
- end
- end
- if trace_locating then
- report_resolving()
- end
- elseif trace_locating then
- report_resolving("configuration files already identified")
- end
-end
-
-local function load_configuration_files()
- local specification = instance.specification
- if #specification > 0 then
- local luacnfname = resolvers.luacnfname
- for i=1,#specification do
- local filename = specification[i]
- local pathname = filedirname(filename)
- local filename = filejoin(pathname,luacnfname)
- local realname = resolvers.resolve(filename) -- no shortcut
- local blob = loadfile(realname)
- if blob then
- local setups = instance.setups
- local data = blob()
- local parent = data and data.parent
- if parent then
- local filename = filejoin(pathname,parent)
- local realname = resolvers.resolve(filename) -- no shortcut
- local blob = loadfile(realname)
- if blob then
- local parentdata = blob()
- if parentdata then
- report_resolving("loading configuration file '%s'",filename)
- data = table.merged(parentdata,data)
- end
- end
- end
- data = data and data.content
- if data then
- if trace_locating then
- report_resolving("loading configuration file '%s'",filename)
- report_resolving()
- end
- local variables = data.variables or { }
- local warning = false
- for k, v in next, data do
- local variant = type(v)
- if variant == "table" then
- initializesetter(filename,k,v)
- elseif variables[k] == nil then
- if trace_locating and not warning then
- report_resolving("variables like '%s' in configuration file '%s' should move to the 'variables' subtable",
- k,resolvers.resolve(filename))
- warning = true
- end
- variables[k] = v
- end
- end
- setups[pathname] = variables
- if resolvers.luacnfstate == "default" then
- -- the following code is not tested
- local cnfspec = variables["TEXMFCNF"]
- if cnfspec then
- if trace_locating then
- report_resolving("reloading configuration due to TEXMF redefinition")
- end
- -- we push the value into the main environment (osenv) so
- -- that it takes precedence over the default one and therefore
- -- also over following definitions
- resolvers.setenv('TEXMFCNF',cnfspec) -- resolves prefixes
- -- we now identify and load the specified configuration files
- instance.specification = { }
- identify_configuration_files()
- load_configuration_files()
- -- we prevent further overload of the configuration variable
- resolvers.luacnfstate = "configuration"
- -- we quit the outer loop
- break
- end
- end
-
- else
- if trace_locating then
- report_resolving("skipping configuration file '%s' (no content)",filename)
- end
- setups[pathname] = { }
- instance.loaderror = true
- end
- elseif trace_locating then
- report_resolving("skipping configuration file '%s' (no valid format)",filename)
- end
- instance.order[#instance.order+1] = instance.setups[pathname]
- if instance.loaderror then
- break
- end
- end
- elseif trace_locating then
- report_resolving("warning: no lua configuration files found")
- end
-end
-
--- scheme magic ... database loading
-
-local function load_file_databases()
- instance.loaderror, instance.files = false, allocate()
- if not instance.renewcache then
- local hashes = instance.hashes
- for k=1,#hashes do
- local hash = hashes[k]
- resolvers.hashers.byscheme(hash.type,hash.name)
- if instance.loaderror then break end
- end
- end
-end
-
-local function locate_file_databases()
- -- todo: cache:// and tree:// (runtime)
- local texmfpaths = resolvers.expandedpathlist('TEXMF')
- if #texmfpaths > 0 then
- for i=1,#texmfpaths do
- local path = collapsepath(texmfpaths[i])
- local stripped = lpegmatch(inhibitstripper,path) -- the !! thing
- if stripped ~= "" then
- local runtime = stripped == path
- path = resolvers.cleanpath(path)
- local spec = resolvers.splitmethod(stripped)
- if runtime and (spec.noscheme or spec.scheme == "file") then
- stripped = "tree:///" .. stripped
- elseif spec.scheme == "cache" or spec.scheme == "file" then
- stripped = spec.path
- end
- if trace_locating then
- if runtime then
- report_resolving("locating list of '%s' (runtime) (%s)",path,stripped)
- else
- report_resolving("locating list of '%s' (cached)",path)
- end
- end
- methodhandler('locators',stripped)
- end
- end
- if trace_locating then
- report_resolving()
- end
- elseif trace_locating then
- report_resolving("no texmf paths are defined (using TEXMF)")
- end
-end
-
-local function generate_file_databases()
- local hashes = instance.hashes
- for k=1,#hashes do
- local hash = hashes[k]
- methodhandler('generators',hash.name)
- end
- if trace_locating then
- report_resolving()
- end
-end
-
-local function save_file_databases() -- will become cachers
- for i=1,#instance.hashes do
- local hash = instance.hashes[i]
- local cachename = hash.name
- if hash.cache then
- local content = instance.files[cachename]
- caches.collapsecontent(content)
- if trace_locating then
- report_resolving("saving tree '%s'",cachename)
- end
- caches.savecontent(cachename,"files",content)
- elseif trace_locating then
- report_resolving("not saving runtime tree '%s'",cachename)
- end
- end
-end
-
-function resolvers.renew(hashname)
- if hashname and hashname ~= "" then
- local expanded = resolvers.expansion(hashname) or ""
- if expanded ~= "" then
- if trace_locating then
- report_resolving("identifying tree '%s' from '%s'",expanded,hashname)
- end
- hashname = expanded
- else
- if trace_locating then
- report_resolving("identifying tree '%s'",hashname)
- end
- end
- local realpath = resolvers.resolve(hashname)
- if lfs.isdir(realpath) then
- if trace_locating then
- report_resolving("using path '%s'",realpath)
- end
- methodhandler('generators',hashname)
- -- could be shared
- local content = instance.files[hashname]
- caches.collapsecontent(content)
- if trace_locating then
- report_resolving("saving tree '%s'",hashname)
- end
- caches.savecontent(hashname,"files",content)
- -- till here
- else
- report_resolving("invalid path '%s'",realpath)
- end
- end
-end
-
-local function load_databases()
- locate_file_databases()
- if instance.diskcache and not instance.renewcache then
- load_file_databases()
- if instance.loaderror then
- generate_file_databases()
- save_file_databases()
- end
- else
- generate_file_databases()
- if instance.renewcache then
- save_file_databases()
- end
- end
-end
-
-function resolvers.appendhash(type,name,cache)
- -- safeguard ... tricky as it's actually a bug when seen twice
- if not instance.hashed[name] then
- if trace_locating then
- report_resolving("hash '%s' appended",name)
- end
- insert(instance.hashes, { type = type, name = name, cache = cache } )
- instance.hashed[name] = cache
- end
-end
-
-function resolvers.prependhash(type,name,cache)
- -- safeguard ... tricky as it's actually a bug when seen twice
- if not instance.hashed[name] then
- if trace_locating then
- report_resolving("hash '%s' prepended",name)
- end
- insert(instance.hashes, 1, { type = type, name = name, cache = cache } )
- instance.hashed[name] = cache
- end
+local function tagstostring(list)
+ if #list==0 then
+ return "no elements"
+ else
+ local t={}
+ for i=1,#list do
+ local li=list[i]
+ local ns,tg=li.ns,li.tg
+ if not ns or ns=="" then ns="*" end
+ if not tg or tg=="" then tg="*" end
+ t[i]=(tg=="@rt@" and "[root]") or format("%s:%s",ns,tg)
+ end
+ return concat(t," ")
+ end
+end
+xml.nodesettostring=nodesettostring
+local lpath
+local lshowoptions={ functions=false }
+local function lshow(parsed)
+ if type(parsed)=="string" then
+ parsed=lpath(parsed)
+ end
+ report_lpath("%s://%s => %s",parsed.protocol or xml.defaultprotocol,parsed.pattern,
+ table.serialize(parsed,false,lshowoptions))
end
-
-function resolvers.extendtexmfvariable(specification) -- crap, we could better prepend the hash
- local t = resolvers.splitpath(getenv('TEXMF'))
- insert(t,1,specification)
- local newspec = concat(t,";")
- if instance.environment["TEXMF"] then
- instance.environment["TEXMF"] = newspec
- elseif instance.variables["TEXMF"] then
- instance.variables["TEXMF"] = newspec
+xml.lshow=lshow
+local function add_comment(p,str)
+ local pc=p.comment
+ if not pc then
+ p.comment={ str }
+ else
+ pc[#pc+1]=str
+ end
+end
+lpath=function (pattern)
+ lpathcalls=lpathcalls+1
+ if type(pattern)=="table" then
+ return pattern
+ else
+ local parsed=cache[pattern]
+ if parsed then
+ lpathcached=lpathcached+1
else
- -- weird
- end
- reset_hashes()
-end
-
-function resolvers.splitexpansions()
- local ie = instance.expansions
- for k,v in next, ie do
- local t, tn, h, p = { }, 0, { }, splitconfigurationpath(v)
- for kk=1,#p do
- local vv = p[kk]
- if vv ~= "" and not h[vv] then
- tn = tn + 1
- t[tn] = vv
- h[vv] = true
- end
- end
- if #t > 1 then
- ie[k] = t
+ parsed=lpegmatch(pathparser,pattern)
+ if parsed then
+ parsed.pattern=pattern
+ local np=#parsed
+ if np==0 then
+ parsed={ pattern=pattern,register_self,state="parsing error" }
+ report_lpath("parsing error in pattern: %s",pattern)
+ lshow(parsed)
else
- ie[k] = t[1]
- end
+ local pi=parsed[1]
+ if pi.axis=="auto-child" then
+ if false then
+ add_comment(parsed,"auto-child replaced by auto-descendant-or-self")
+ parsed[1]=register_auto_descendant_or_self
+ else
+ add_comment(parsed,"auto-child replaced by auto-descendant")
+ parsed[1]=register_auto_descendant
+ end
+ elseif pi.axis=="initial-child" and np>1 and parsed[2].axis then
+ add_comment(parsed,"initial-child removed")
+ remove(parsed,1)
+ end
+ local np=#parsed
+ if np>1 then
+ local pnp=parsed[np]
+ if pnp.kind=="nodes" and pnp.nodetest==true then
+ local nodes=pnp.nodes
+ if nodes[1]==true and nodes[2]==false and nodes[3]==false then
+ add_comment(parsed,"redundant final wildcard filter removed")
+ remove(parsed,np)
+ end
+ end
+ end
+ end
+ else
+ parsed={ pattern=pattern }
+ end
+ cache[pattern]=parsed
+ if trace_lparse and not trace_lprofile then
+ lshow(parsed)
+ end
end
+ return parsed
+ end
end
-
--- end of split/join code
-
--- we used to have 'files' and 'configurations' so therefore the following
--- shared function
-
-function resolvers.datastate()
- return caches.contentstate()
+xml.lpath=lpath
+local profiled={} xml.profiled=profiled
+local function profiled_apply(list,parsed,nofparsed,order)
+ local p=profiled[parsed.pattern]
+ if p then
+ p.tested=p.tested+1
+ else
+ p={ tested=1,matched=0,finalized=0 }
+ profiled[parsed.pattern]=p
+ end
+ local collected=list
+ for i=1,nofparsed do
+ local pi=parsed[i]
+ local kind=pi.kind
+ if kind=="axis" then
+ collected=apply_axis[pi.axis](collected)
+ elseif kind=="nodes" then
+ collected=apply_nodes(collected,pi.nodetest,pi.nodes)
+ elseif kind=="expression" then
+ collected=apply_expression(collected,pi.evaluator,order)
+ elseif kind=="finalizer" then
+ collected=pi.finalizer(collected)
+ p.matched=p.matched+1
+ p.finalized=p.finalized+1
+ return collected
+ end
+ if not collected or #collected==0 then
+ local pn=i %s",(collected and #collected) or 0,pi.expression,pi.converted)
+ elseif kind=="finalizer" then
+ collected=pi.finalizer(collected)
+ report_lpath("% 10i : fi : %s : %s(%s)",(type(collected)=="table" and #collected) or 0,parsed.protocol or xml.defaultprotocol,pi.name,pi.arguments or "")
+ return collected
+ end
+ if not collected or #collected==0 then
+ local pn=i 0 then
- instance.lists, done = { }, { }
+local function selection(root,pattern,handle)
+ local collected=applylpath(root,pattern)
+ if collected then
+ if handle then
+ for c=1,#collected do
+ handle(collected[c])
+ end
+ else
+ return collected
end
+ end
end
-
-function resolvers.registerextrapath(paths,subpaths)
- local ep = instance.extra_paths or { }
- local oldn = #ep
- local newn = oldn
- if paths and paths ~= "" then
- if subpaths and subpaths ~= "" then
- for p in gmatch(paths,"[^,]+") do
- -- we gmatch each step again, not that fast, but used seldom
- for s in gmatch(subpaths,"[^,]+") do
- local ps = p .. "/" .. s
- if not done[ps] then
- newn = newn + 1
- ep[newn] = resolvers.cleanpath(ps)
- done[ps] = true
- end
- end
- end
+xml.traverse=traverse
+xml.selection=selection
+local function dofunction(collected,fnc,...)
+ if collected then
+ local f=functions[fnc]
+ if f then
+ for c=1,#collected do
+ f(collected[c],...)
+ end
+ else
+ report_lpath("unknown function %a",fnc)
+ end
+ end
+end
+finalizers.xml["function"]=dofunction
+finalizers.tex["function"]=dofunction
+expressions.text=function(e,n)
+ local rdt=e.__p__.dt
+ return rdt and rdt[n] or ""
+end
+expressions.name=function(e,n)
+ local found=false
+ n=tonumber(n) or 0
+ if n==0 then
+ found=type(e)=="table" and e
+ elseif n<0 then
+ local d,k=e.__p__.dt,e.ni
+ for i=k-1,1,-1 do
+ local di=d[i]
+ if type(di)=="table" then
+ if n==-1 then
+ found=di
+ break
else
- for p in gmatch(paths,"[^,]+") do
- if not done[p] then
- newn = newn + 1
- ep[newn] = resolvers.cleanpath(p)
- done[p] = true
- end
- end
- end
- elseif subpaths and subpaths ~= "" then
- for i=1,oldn do
- -- we gmatch each step again, not that fast, but used seldom
- for s in gmatch(subpaths,"[^,]+") do
- local ps = ep[i] .. "/" .. s
- if not done[ps] then
- newn = newn + 1
- ep[newn] = resolvers.cleanpath(ps)
- done[ps] = true
- end
- end
+ n=n+1
+ end
+ end
+ end
+ else
+ local d,k=e.__p__.dt,e.ni
+ for i=k+1,#d,1 do
+ local di=d[i]
+ if type(di)=="table" then
+ if n==1 then
+ found=di
+ break
+ else
+ n=n-1
end
+ end
end
- if newn > 0 then
- instance.extra_paths = ep -- register paths
- end
- if newn > oldn then
- instance.lists = { } -- erase the cache
- end
-end
-
-local function made_list(instance,list)
- local ep = instance.extra_paths
- if not ep or #ep == 0 then
- return list
+ end
+ if found then
+ local ns,tg=found.rn or found.ns or "",found.tg
+ if ns~="" then
+ return ns..":"..tg
else
- local done, new, newn = { }, { }, 0
- -- honour . .. ../.. but only when at the start
- for k=1,#list do
- local v = list[k]
- if not done[v] then
- if find(v,"^[%.%/]$") then
- done[v] = true
- newn = newn + 1
- new[newn] = v
- else
- break
- end
- end
- end
- -- first the extra paths
- for k=1,#ep do
- local v = ep[k]
- if not done[v] then
- done[v] = true
- newn = newn + 1
- new[newn] = v
- end
- end
- -- next the formal paths
- for k=1,#list do
- local v = list[k]
- if not done[v] then
- done[v] = true
- newn = newn + 1
- new[newn] = v
- end
- end
- return new
+ return tg
end
+ else
+ return ""
+ end
end
-
-function resolvers.cleanpathlist(str)
- local t = resolvers.expandedpathlist(str)
- if t then
- for i=1,#t do
- t[i] = collapsepath(resolvers.cleanpath(t[i]))
+expressions.tag=function(e,n)
+ if not e then
+ return ""
+ else
+ local found=false
+ n=tonumber(n) or 0
+ if n==0 then
+ found=(type(e)=="table") and e
+ elseif n<0 then
+ local d,k=e.__p__.dt,e.ni
+ for i=k-1,1,-1 do
+ local di=d[i]
+ if type(di)=="table" then
+ if n==-1 then
+ found=di
+ break
+ else
+ n=n+1
+ end
end
+ end
+ else
+ local d,k=e.__p__.dt,e.ni
+ for i=k+1,#d,1 do
+ local di=d[i]
+ if type(di)=="table" then
+ if n==1 then
+ found=di
+ break
+ else
+ n=n-1
+ end
+ end
+ end
+ end
+ return (found and found.tg) or ""
+ end
+end
+local dummy=function() end
+function xml.elements(root,pattern,reverse)
+ local collected=applylpath(root,pattern)
+ if not collected then
+ return dummy
+ elseif reverse then
+ local c=#collected+1
+ return function()
+ if c>1 then
+ c=c-1
+ local e=collected[c]
+ local r=e.__p__
+ return r,r.dt,e.ni
+ end
+ end
+ else
+ local n,c=#collected,0
+ return function()
+ if c1 then
+ c=c-1
+ return collected[c]
+ end
end
- return t
+ else
+ local n,c=#collected,0
+ return function()
+ if c"))^0
+local special=P("<")/"<"+P(">")/">"+P("&")/"&"
+local escaped=Cs(normal*(special*normal)^0)
+local normal=(1-S"&")^0
+local special=P("<")/"<"+P(">")/">"+P("&")/"&"
+local unescaped=Cs(normal*(special*normal)^0)
+local cleansed=Cs(((P("<")*(1-P(">"))^0*P(">"))/""+1)^0)
+xmlpatterns.escaped=escaped
+xmlpatterns.unescaped=unescaped
+xmlpatterns.cleansed=cleansed
+function xml.escaped (str) return lpegmatch(escaped,str) end
+function xml.unescaped(str) return lpegmatch(unescaped,str) end
+function xml.cleansed (str) return lpegmatch(cleansed,str) end
+function xml.fillin(root,pattern,str,check)
+ local e=xml.first(root,pattern)
+ if e then
+ local n=#e.dt
+ if not check or n==0 or (n==1 and e.dt[1]=="") then
+ e.dt={ str }
end
- return readable
+ end
end
--- name
--- name/name
-local function collect_files(names)
- local filelist, noffiles = { }, 0
- for k=1,#names do
- local fname = names[k]
- if trace_detail then
- report_resolving("checking name '%s'",fname)
- end
- local bname = filebasename(fname)
- local dname = filedirname(fname)
- if dname == "" or find(dname,"^%.") then
- dname = false
- else
-dname = gsub(dname,"*","%.*")
- dname = "/" .. dname .. "$"
- end
- local hashes = instance.hashes
- for h=1,#hashes do
- local hash = hashes[h]
- local blobpath = hash.name
- local files = blobpath and instance.files[blobpath]
- if files then
- if trace_detail then
- report_resolving("deep checking '%s' (%s)",blobpath,bname)
- end
- local blobfile = files[bname]
- if not blobfile then
- local rname = "remap:"..bname
- blobfile = files[rname]
- if blobfile then
- bname = files[rname]
- blobfile = files[bname]
- end
- end
- if blobfile then
- local blobroot = files.__path__ or blobpath
- if type(blobfile) == 'string' then
- if not dname or find(blobfile,dname) then
- local variant = hash.type
- -- local search = filejoin(blobpath,blobfile,bname)
- local search = filejoin(blobroot,blobfile,bname)
- local result = methodhandler('concatinators',hash.type,blobroot,blobfile,bname)
- if trace_detail then
- report_resolving("match: variant '%s', search '%s', result '%s'",variant,search,result)
- end
- noffiles = noffiles + 1
- filelist[noffiles] = { variant, search, result }
- end
- else
- for kk=1,#blobfile do
- local vv = blobfile[kk]
- if not dname or find(vv,dname) then
- local variant = hash.type
- -- local search = filejoin(blobpath,vv,bname)
- local search = filejoin(blobroot,vv,bname)
- local result = methodhandler('concatinators',hash.type,blobroot,vv,bname)
- if trace_detail then
- report_resolving("match: variant '%s', search '%s', result '%s'",variant,search,result)
- end
- noffiles = noffiles + 1
- filelist[noffiles] = { variant, search, result }
- end
- end
- end
- end
- elseif trace_locating then
- report_resolving("no match in '%s' (%s)",blobpath,bname)
- end
- end
- end
- return noffiles > 0 and filelist or nil
-end
+end -- of closure
-local fit = { }
+do -- create closure to overcome 200 locals limit
-function resolvers.registerintrees(filename,format,filetype,usedmethod,foundname)
- local foundintrees = instance.foundintrees
- if usedmethod == "direct" and filename == foundname and fit[foundname] then
- -- just an extra lookup after a test on presence
- else
- local t = {
- filename = filename,
- format = format ~= "" and format or nil,
- filetype = filetype ~= "" and filetype or nil,
- usedmethod = usedmethod,
- foundname = foundname,
- }
- fit[foundname] = t
- foundintrees[#foundintrees+1] = t
- end
-end
+package.loaded["lxml-aux"] = package.loaded["lxml-aux"] or true
--- split the next one up for readability (but this module needs a cleanup anyway)
+-- original size: 23804, stripped down to: 16817
-local function can_be_dir(name) -- can become local
- local fakepaths = instance.fakepaths
- if not fakepaths[name] then
- if lfs.isdir(name) then
- fakepaths[name] = 1 -- directory
- else
- fakepaths[name] = 2 -- no directory
+if not modules then modules={} end modules ['lxml-aux']={
+ version=1.001,
+ comment="this module is the basis for the lxml-* ones",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local trace_manipulations=false trackers.register("lxml.manipulations",function(v) trace_manipulations=v end)
+local report_xml=logs.reporter("xml")
+local xml=xml
+local xmlconvert,xmlcopy,xmlname=xml.convert,xml.copy,xml.name
+local xmlinheritedconvert=xml.inheritedconvert
+local xmlapplylpath=xml.applylpath
+local xmlfilter=xml.filter
+local type,setmetatable,getmetatable=type,setmetatable,getmetatable
+local insert,remove,fastcopy,concat=table.insert,table.remove,table.fastcopy,table.concat
+local gmatch,gsub,format,find,strip=string.gmatch,string.gsub,string.format,string.find,string.strip
+local utfbyte=utf.byte
+local function report(what,pattern,c,e)
+ report_xml("%s element %a, root %a, position %a, index %a, pattern %a",what,xmlname(e),xmlname(e.__p__),c,e.ni,pattern)
+end
+local function withelements(e,handle,depth)
+ if e and handle then
+ local edt=e.dt
+ if edt then
+ depth=depth or 0
+ for i=1,#edt do
+ local e=edt[i]
+ if type(e)=="table" then
+ handle(e,depth)
+ withelements(e,handle,depth+1)
end
+ end
end
- return fakepaths[name] == 1
+ end
end
-
-local preparetreepattern = Cs((P(".")/"%%." + P("-")/"%%-" + P(1))^0 * Cc("$"))
-
--- -- -- begin of main file search routing -- -- -- needs checking as previous has been patched
-
-local collect_instance_files
-
-local function find_analyze(filename,askedformat,allresults)
- local filetype, wantedfiles, ext = '', { }, fileextname(filename)
- -- too tricky as filename can be bla.1.2.3:
- --
- -- if not suffixmap[ext] then
- -- wantedfiles[#wantedfiles+1] = filename
- -- end
- wantedfiles[#wantedfiles+1] = filename
- if askedformat == "" then
- if ext == "" or not suffixmap[ext] then
- local defaultsuffixes = resolvers.defaultsuffixes
- for i=1,#defaultsuffixes do
- local forcedname = filename .. '.' .. defaultsuffixes[i]
- wantedfiles[#wantedfiles+1] = forcedname
- filetype = resolvers.formatofsuffix(forcedname)
- if trace_locating then
- report_resolving("forcing filetype '%s'",filetype)
- end
- end
- else
- filetype = resolvers.formatofsuffix(filename)
- if trace_locating then
- report_resolving("using suffix based filetype '%s'",filetype)
+xml.withelements=withelements
+function xml.withelement(e,n,handle)
+ if e and n~=0 and handle then
+ local edt=e.dt
+ if edt then
+ if n>0 then
+ for i=1,#edt do
+ local ei=edt[i]
+ if type(ei)=="table" then
+ if n==1 then
+ handle(ei)
+ return
+ else
+ n=n-1
end
+ end
end
- else
- if ext == "" or not suffixmap[ext] then
- local format_suffixes = suffixes[askedformat]
- if format_suffixes then
- for i=1,#format_suffixes do
- wantedfiles[#wantedfiles+1] = filename .. "." .. format_suffixes[i]
- end
+ elseif n<0 then
+ for i=#edt,1,-1 do
+ local ei=edt[i]
+ if type(ei)=="table" then
+ if n==-1 then
+ handle(ei)
+ return
+ else
+ n=n+1
end
+ end
end
- filetype = askedformat
- if trace_locating then
- report_resolving("using given filetype '%s'",filetype)
- end
+ end
end
- return filetype, wantedfiles
+ end
end
-
-local function find_direct(filename,allresults)
- if not dangerous[askedformat] and isreadable(filename) then
- if trace_detail then
- report_resolving("file '%s' found directly",filename)
- end
- return "direct", { filename }
+function xml.each(root,pattern,handle,reverse)
+ local collected=xmlapplylpath(root,pattern)
+ if collected then
+ if reverse then
+ for c=#collected,1,-1 do
+ handle(collected[c])
+ end
+ else
+ for c=1,#collected do
+ handle(collected[c])
+ end
end
+ return collected
+ end
end
-
-local function find_wildcard(filename,allresults)
- if find(filename,'%*') then
- if trace_locating then
- report_resolving("checking wildcard '%s'", filename)
- end
- local method, result = resolvers.findwildcardfiles(filename)
- if result then
- return "wildcard", result
- end
+function xml.processattributes(root,pattern,handle)
+ local collected=xmlapplylpath(root,pattern)
+ if collected and handle then
+ for c=1,#collected do
+ handle(collected[c].at)
end
+ end
+ return collected
end
-
-local function find_qualified(filename,allresults) -- this one will be split too
- if not file.is_qualified_path(filename) then
- return
+function xml.collect(root,pattern)
+ return xmlapplylpath(root,pattern)
+end
+function xml.collecttexts(root,pattern,flatten)
+ local collected=xmlapplylpath(root,pattern)
+ if collected and flatten then
+ local xmltostring=xml.tostring
+ for c=1,#collected do
+ collected[c]=xmltostring(collected[c].dt)
end
- if trace_locating then
- report_resolving("checking qualified name '%s'", filename)
+ end
+ return collected or {}
+end
+function xml.collect_tags(root,pattern,nonamespace)
+ local collected=xmlapplylpath(root,pattern)
+ if collected then
+ local t,n={},0
+ for c=1,#collected do
+ local e=collected[c]
+ local ns,tg=e.ns,e.tg
+ n=n+1
+ if nonamespace then
+ t[n]=tg
+ elseif ns=="" then
+ t[n]=tg
+ else
+ t[n]=ns..":"..tg
+ end
end
- if isreadable(filename) then
- if trace_detail then
- report_resolving("qualified file '%s' found", filename)
- end
- return "qualified", { filename }
+ return t
+ end
+end
+local no_root={ no_root=true }
+local function redo_ni(d)
+ for k=1,#d do
+ local dk=d[k]
+ if type(dk)=="table" then
+ dk.ni=k
end
- if trace_detail then
- report_resolving("locating qualified file '%s'", filename)
- end
- local forcedname, suffix = "", fileextname(filename)
- if suffix == "" then -- why
- local format_suffixes = askedformat == "" and resolvers.defaultsuffixes or suffixes[askedformat]
- if format_suffixes then
- for i=1,#format_suffixes do
- local s = format_suffixes[i]
- forcedname = filename .. "." .. s
- if isreadable(forcedname) then
- if trace_locating then
- report_resolving("no suffix, forcing format filetype '%s'", s)
- end
- return "qualified", { forcedname }
- end
- end
- end
+ end
+end
+local function xmltoelement(whatever,root)
+ if not whatever then
+ return nil
+ end
+ local element
+ if type(whatever)=="string" then
+ element=xmlinheritedconvert(whatever,root)
+ else
+ element=whatever
+ end
+ if element.error then
+ return whatever
+ end
+ if element then
+ end
+ return element
+end
+xml.toelement=xmltoelement
+local function copiedelement(element,newparent)
+ if type(element)=="string" then
+ return element
+ else
+ element=xmlcopy(element).dt
+ if newparent and type(element)=="table" then
+ element.__p__=newparent
end
- if suffix and suffix ~= "" then
- -- try to find in tree (no suffix manipulation), here we search for the
- -- matching last part of the name
- local basename = filebasename(filename)
- local pattern = lpegmatch(preparetreepattern,filename)
- -- messy .. to be sorted out
- local savedformat = askedformat
- local format = savedformat or ""
- if format == "" then
- askedformat = resolvers.formatofsuffix(suffix)
- end
- if not format then
- askedformat = "othertextfiles" -- kind of everything, maybe all
- end
- --
- if basename ~= filename then
- local resolved = collect_instance_files(basename,askedformat,allresults)
- if #resolved == 0 then
- local lowered = lower(basename)
- if filename ~= lowered then
- resolved = collect_instance_files(lowered,askedformat,allresults)
- end
- end
- resolvers.format = savedformat
- --
- if #resolved > 0 then
- local result = { }
- for r=1,#resolved do
- local rr = resolved[r]
- if find(rr,pattern) then
- result[#result+1] = rr
- end
- end
- if #result > 0 then
- return "qualified", result
- end
- end
+ return element
+ end
+end
+function xml.delete(root,pattern)
+ if not pattern or pattern=="" then
+ local p=root.__p__
+ if p then
+ if trace_manipulations then
+ report('deleting',"--",c,root)
+ end
+ local d=p.dt
+ remove(d,root.ni)
+ redo_ni(d)
+ end
+ else
+ local collected=xmlapplylpath(root,pattern)
+ if collected then
+ for c=1,#collected do
+ local e=collected[c]
+ local p=e.__p__
+ if p then
+ if trace_manipulations then
+ report('deleting',pattern,c,e)
+ end
+ local d=p.dt
+ remove(d,e.ni)
+ redo_ni(d)
end
- -- a real wildcard:
- --
- -- local filelist = collect_files({basename})
- -- result = { }
- -- for f=1,#filelist do
- -- local ff = filelist[f][3] or ""
- -- if find(ff,pattern) then
- -- result[#result+1], ok = ff, true
- -- end
- -- end
- -- if #result > 0 then
- -- return "qualified", result
- -- end
+ end
end
+ end
end
-
-local function check_subpath(fname)
- if isreadable(fname) then
- if trace_detail then
- report_resolving("found '%s' by deep scanning",fname)
+function xml.replace(root,pattern,whatever)
+ local element=root and xmltoelement(whatever,root)
+ local collected=element and xmlapplylpath(root,pattern)
+ if collected then
+ for c=1,#collected do
+ local e=collected[c]
+ local p=e.__p__
+ if p then
+ if trace_manipulations then
+ report('replacing',pattern,c,e)
end
- return fname
+ local d=p.dt
+ d[e.ni]=copiedelement(element,p)
+ redo_ni(d)
+ end
end
+ end
end
-
-local function find_intree(filename,filetype,wantedfiles,allresults)
- local typespec = resolvers.variableofformat(filetype)
- local pathlist = resolvers.expandedpathlist(typespec)
- local method = "intree"
- if pathlist and #pathlist > 0 then
- -- list search
- local filelist = collect_files(wantedfiles)
- local dirlist = { }
- if filelist then
- for i=1,#filelist do
- dirlist[i] = filedirname(filelist[i][3]) .. "/" -- was [2] .. gamble
- end
- end
- if trace_detail then
- report_resolving("checking filename '%s'",filename)
- end
- local result = { }
- for k=1,#pathlist do
- local path = pathlist[k]
- local pathname = lpegmatch(inhibitstripper,path)
- local doscan = path == pathname -- no ^!!
- if not find (pathname,'//$') then
- doscan = false -- we check directly on the path
- end
- local done = false
- -- using file list
- if filelist then -- database
- -- compare list entries with permitted pattern -- /xx /xx//
- local expression = makepathexpression(pathname)
- if trace_detail then
- report_resolving("using pattern '%s' for path '%s'",expression,pathname)
- end
- for k=1,#filelist do
- local fl = filelist[k]
- local f = fl[2]
- local d = dirlist[k]
- if find(d,expression) then
- -- todo, test for readable
- result[#result+1] = resolvers.resolve(fl[3]) -- no shortcut
- done = true
- if allresults then
- if trace_detail then
- report_resolving("match to '%s' in hash for file '%s' and path '%s', continue scanning",expression,f,d)
- end
- else
- if trace_detail then
- report_resolving("match to '%s' in hash for file '%s' and path '%s', quit scanning",expression,f,d)
- end
- break
- end
- elseif trace_detail then
- report_resolving("no match to '%s' in hash for file '%s' and path '%s'",expression,f,d)
- end
- end
- end
- if done then
- method = "database"
- else
- method = "filesystem" -- bonus, even when !! is specified
- pathname = gsub(pathname,"/+$","")
- pathname = resolvers.resolve(pathname)
- local scheme = url.hasscheme(pathname)
- if not scheme or scheme == "file" then
- local pname = gsub(pathname,"%.%*$",'')
- if not find(pname,"%*") then
- if can_be_dir(pname) then
- -- quick root scan first
- for k=1,#wantedfiles do
- local w = wantedfiles[k]
- local fname = check_subpath(filejoin(pname,w))
- if fname then
- result[#result+1] = fname
- done = true
- if not allresults then
- break
- end
- end
- end
- if not done and doscan then
- -- collect files in path (and cache the result)
- local files = resolvers.simplescanfiles(pname,false,true)
- for k=1,#wantedfiles do
- local w = wantedfiles[k]
- local subpath = files[w]
- if not subpath or subpath == "" then
- -- rootscan already done
- elseif type(subpath) == "string" then
- local fname = check_subpath(filejoin(pname,subpath,w))
- if fname then
- result[#result+1] = fname
- done = true
- if not allresults then
- break
- end
- end
- else
- for i=1,#subpath do
- local sp = subpath[i]
- if sp == "" then
- -- roottest already done
- else
- local fname = check_subpath(filejoin(pname,sp,w))
- if fname then
- result[#result+1] = fname
- done = true
- if not allresults then
- break
- end
- end
- end
- end
- if done and not allresults then
- break
- end
- end
- end
- end
- end
- else
- -- no access needed for non existing path, speedup (esp in large tree with lots of fake)
- end
- end
- end
- -- todo recursive scanning
- if done and not allresults then
- break
- end
- end
- if #result > 0 then
- return method, result
+local function wrap(e,wrapper)
+ local t={
+ rn=e.rn,
+ tg=e.tg,
+ ns=e.ns,
+ at=e.at,
+ dt=e.dt,
+ __p__=e,
+ }
+ setmetatable(t,getmetatable(e))
+ e.rn=wrapper.rn or e.rn or ""
+ e.tg=wrapper.tg or e.tg or ""
+ e.ns=wrapper.ns or e.ns or ""
+ e.at=fastcopy(wrapper.at)
+ e.dt={ t }
+end
+function xml.wrap(root,pattern,whatever)
+ if whatever then
+ local wrapper=xmltoelement(whatever,root)
+ local collected=xmlapplylpath(root,pattern)
+ if collected then
+ for c=1,#collected do
+ local e=collected[c]
+ if trace_manipulations then
+ report('wrapping',pattern,c,e)
end
+ wrap(e,wrapper)
+ end
+ end
+ else
+ wrap(root,xmltoelement(pattern))
+ end
+end
+local function inject_element(root,pattern,whatever,prepend)
+ local element=root and xmltoelement(whatever,root)
+ local collected=element and xmlapplylpath(root,pattern)
+ local function inject_e(e)
+ local r=e.__p__
+ local d,k,rri=r.dt,e.ni,r.ri
+ local edt=(rri and d[rri].dt) or (d and d[k] and d[k].dt)
+ if edt then
+ local be,af
+ local cp=copiedelement(element,e)
+ if prepend then
+ be,af=cp,edt
+ else
+ be,af=edt,cp
+ end
+ local bn=#be
+ for i=1,#af do
+ bn=bn+1
+ be[bn]=af[i]
+ end
+ if rri then
+ r.dt[rri].dt=be
+ else
+ d[k].dt=be
+ end
+ redo_ni(d)
+ end
+ end
+ if not collected then
+ elseif collected.tg then
+ inject_e(collected)
+ else
+ for c=1,#collected do
+ inject_e(collected[c])
+ end
+ end
+end
+local function insert_element(root,pattern,whatever,before)
+ local element=root and xmltoelement(whatever,root)
+ local collected=element and xmlapplylpath(root,pattern)
+ local function insert_e(e)
+ local r=e.__p__
+ local d,k=r.dt,e.ni
+ if not before then
+ k=k+1
+ end
+ insert(d,k,copiedelement(element,r))
+ redo_ni(d)
+ end
+ if not collected then
+ elseif collected.tg then
+ insert_e(collected)
+ else
+ for c=1,#collected do
+ insert_e(collected[c])
end
+ end
end
-
-local function find_onpath(filename,filetype,wantedfiles,allresults)
- if trace_detail then
- report_resolving("checking filename '%s', filetype '%s', wanted files '%s'",filename, filetype or '?',concat(wantedfiles," | "))
- end
- local result = { }
- for k=1,#wantedfiles do
- local fname = wantedfiles[k]
- if fname and isreadable(fname) then
- filename = fname
- result[#result+1] = filejoin('.',fname)
- if not allresults then
- break
- end
+xml.insert_element=insert_element
+xml.insertafter=insert_element
+xml.insertbefore=function(r,p,e) insert_element(r,p,e,true) end
+xml.injectafter=inject_element
+xml.injectbefore=function(r,p,e) inject_element(r,p,e,true) end
+local function include(xmldata,pattern,attribute,recursive,loaddata)
+ pattern=pattern or 'include'
+ loaddata=loaddata or io.loaddata
+ local collected=xmlapplylpath(xmldata,pattern)
+ if collected then
+ for c=1,#collected do
+ local ek=collected[c]
+ local name=nil
+ local ekdt=ek.dt
+ local ekat=ek.at
+ local epdt=ek.__p__.dt
+ if not attribute or attribute=="" then
+ name=(type(ekdt)=="table" and ekdt[1]) or ekdt
+ end
+ if not name then
+ for a in gmatch(attribute or "href","([^|]+)") do
+ name=ekat[a]
+ if name then break end
+ end
+ end
+ local data=(name and name~="" and loaddata(name)) or ""
+ if data=="" then
+ epdt[ek.ni]=""
+ elseif ekat["parse"]=="text" then
+ epdt[ek.ni]=xml.escaped(data)
+ else
+ local xi=xmlinheritedconvert(data,xmldata)
+ if not xi then
+ epdt[ek.ni]=""
+ else
+ if recursive then
+ include(xi,pattern,attribute,recursive,loaddata)
+ end
+ epdt[ek.ni]=xml.body(xi)
end
+ end
end
- if #result > 0 then
- return "onpath", result
- end
-end
-
-local function find_otherwise(filename,filetype,wantedfiles,allresults) -- other text files | any | whatever
- local filelist = collect_files(wantedfiles)
- local fl = filelist and filelist[1]
- if fl then
- return "otherwise", { resolvers.resolve(fl[3]) } -- filename
- end
-end
-
--- we could have a loop over the 6 functions but then we'd have to
--- always analyze
-
-collect_instance_files = function(filename,askedformat,allresults) -- uses nested
- askedformat = askedformat or ""
- filename = collapsepath(filename)
- if allresults then
- -- no need for caching, only used for tracing
- local filetype, wantedfiles = find_analyze(filename,askedformat)
- local results = {
- { find_direct (filename,true) },
- { find_wildcard (filename,true) },
- { find_qualified(filename,true) },
- { find_intree (filename,filetype,wantedfiles,true) },
- { find_onpath (filename,filetype,wantedfiles,true) },
- { find_otherwise(filename,filetype,wantedfiles,true) },
- }
- local result, status, done = { }, { }, { }
- for k, r in next, results do
- local method, list = r[1], r[2]
- if method and list then
- for i=1,#list do
- local c = collapsepath(list[i])
- if not done[c] then
- result[#result+1] = c
- done[c] = true
- end
- status[#status+1] = format("%-10s: %s",method,c)
- end
- end
- end
- if trace_detail then
- report_resolving("lookup status: %s",table.serialize(status,filename))
- end
- return result, status
+ end
+end
+xml.include=include
+local function stripelement(e,nolines,anywhere)
+ local edt=e.dt
+ if edt then
+ if anywhere then
+ local t,n={},0
+ for e=1,#edt do
+ local str=edt[e]
+ if type(str)~="string" then
+ n=n+1
+ t[n]=str
+ elseif str~="" then
+ if nolines then
+ str=gsub(str,"%s+"," ")
+ end
+ str=gsub(str,"^%s*(.-)%s*$","%1")
+ if str~="" then
+ n=n+1
+ t[n]=str
+ end
+ end
+ end
+ e.dt=t
else
- local method, result, stamp, filetype, wantedfiles
- if instance.remember then
- stamp = format("%s--%s", filename, askedformat)
- result = stamp and instance.found[stamp]
- if result then
- if trace_locating then
- report_resolving("remembered file '%s'",filename)
- end
- return result
- end
- end
- method, result = find_direct(filename)
- if not result then
- method, result = find_wildcard(filename)
- if not result then
- method, result = find_qualified(filename)
- if not result then
- filetype, wantedfiles = find_analyze(filename,askedformat)
- method, result = find_intree(filename,filetype,wantedfiles)
- if not result then
- method, result = find_onpath(filename,filetype,wantedfiles)
- if not result then
- method, result = find_otherwise(filename,filetype,wantedfiles)
- end
- end
- end
- end
- end
- if result and #result > 0 then
- local foundname = collapsepath(result[1])
- resolvers.registerintrees(filename,askedformat,filetype,method,foundname)
- result = { foundname }
+ if #edt>0 then
+ local str=edt[1]
+ if type(str)~="string" then
+ elseif str=="" then
+ remove(edt,1)
else
- result = { } -- maybe false
- end
- if stamp then
- if trace_locating then
- report_resolving("remembering file '%s'",filename)
- end
- instance.found[stamp] = result
- end
- return result
+ if nolines then
+ str=gsub(str,"%s+"," ")
+ end
+ str=gsub(str,"^%s+","")
+ if str=="" then
+ remove(edt,1)
+ else
+ edt[1]=str
+ end
+ end
+ end
+ local nedt=#edt
+ if nedt>0 then
+ local str=edt[nedt]
+ if type(str)~="string" then
+ elseif str=="" then
+ remove(edt)
+ else
+ if nolines then
+ str=gsub(str,"%s+"," ")
+ end
+ str=gsub(str,"%s+$","")
+ if str=="" then
+ remove(edt)
+ else
+ edt[nedt]=str
+ end
+ end
+ end
+ end
+ end
+ return e
+end
+xml.stripelement=stripelement
+function xml.strip(root,pattern,nolines,anywhere)
+ local collected=xmlapplylpath(root,pattern)
+ if collected then
+ for i=1,#collected do
+ stripelement(collected[i],nolines,anywhere)
+ end
+ end
+end
+local function renamespace(root,oldspace,newspace)
+ local ndt=#root.dt
+ for i=1,ndt or 0 do
+ local e=root[i]
+ if type(e)=="table" then
+ if e.ns==oldspace then
+ e.ns=newspace
+ if e.rn then
+ e.rn=newspace
+ end
+ end
+ local edt=e.dt
+ if edt then
+ renamespace(edt,oldspace,newspace)
+ end
+ end
+ end
+end
+xml.renamespace=renamespace
+function xml.remaptag(root,pattern,newtg)
+ local collected=xmlapplylpath(root,pattern)
+ if collected then
+ for c=1,#collected do
+ collected[c].tg=newtg
end
+ end
end
-
--- -- -- end of main file search routing -- -- --
-
-
-local function findfiles(filename,filetype,allresults)
- local result, status = collect_instance_files(filename,filetype or "",allresults)
- if not result or #result == 0 then
- local lowered = lower(filename)
- if filename ~= lowered then
- result, status = collect_instance_files(lowered,filetype or "",allresults)
- end
+function xml.remapnamespace(root,pattern,newns)
+ local collected=xmlapplylpath(root,pattern)
+ if collected then
+ for c=1,#collected do
+ collected[c].ns=newns
end
- return result or { }, status
+ end
end
-
-function resolvers.findfiles(filename,filetype)
- return findfiles(filename,filetype,true)
+function xml.checknamespace(root,pattern,newns)
+ local collected=xmlapplylpath(root,pattern)
+ if collected then
+ for c=1,#collected do
+ local e=collected[c]
+ if (not e.rn or e.rn=="") and e.ns=="" then
+ e.rn=newns
+ end
+ end
+ end
end
-
-function resolvers.findfile(filename,filetype)
- return findfiles(filename,filetype,false)[1] or ""
+function xml.remapname(root,pattern,newtg,newns,newrn)
+ local collected=xmlapplylpath(root,pattern)
+ if collected then
+ for c=1,#collected do
+ local e=collected[c]
+ e.tg,e.ns,e.rn=newtg,newns,newrn
+ end
+ end
end
-
-function resolvers.findpath(filename,filetype)
- return filedirname(findfiles(filename,filetype,false)[1] or "")
+function xml.cdatatotext(e)
+ local dt=e.dt
+ if #dt==1 then
+ local first=dt[1]
+ if first.tg=="@cd@" then
+ e.dt=first.dt
+ end
+ else
+ end
+end
+function xml.texttocdata(e)
+ local dt=e.dt
+ local s=xml.tostring(dt)
+ e.tg="@cd@"
+ e.special=true
+ e.ns=""
+ e.rn=""
+ e.dt={ s }
+ e.at=nil
+end
+function xml.elementtocdata(e)
+ local dt=e.dt
+ local s=xml.tostring(e)
+ e.tg="@cd@"
+ e.special=true
+ e.ns=""
+ e.rn=""
+ e.dt={ s }
+ e.at=nil
+end
+xml.builtinentities=table.tohash { "amp","quot","apos","lt","gt" }
+local entities=characters and characters.entities or nil
+local builtinentities=xml.builtinentities
+function xml.addentitiesdoctype(root,option)
+ if not entities then
+ require("char-ent")
+ entities=characters.entities
+ end
+ if entities and root and root.tg=="@rt@" and root.statistics then
+ local list={}
+ local hexify=option=="hexadecimal"
+ for k,v in table.sortedhash(root.statistics.entities.names) do
+ if not builtinentities[k] then
+ local e=entities[k]
+ if not e then
+ e=format("[%s]",k)
+ elseif hexify then
+ e=format("%05X;",utfbyte(k))
+ end
+ list[#list+1]=format(" ",k,e)
+ end
+ end
+ local dt=root.dt
+ local n=dt[1].tg=="@pi@" and 2 or 1
+ if #list>0 then
+ insert(dt,n,{ "\n" })
+ insert(dt,n,{
+ tg="@dt@",
+ dt={ format("Something [\n%s\n] ",concat(list)) },
+ ns="",
+ special=true,
+ })
+ insert(dt,n,{ "\n\n" })
+ else
+ end
+ end
+end
+xml.all=xml.each
+xml.insert=xml.insertafter
+xml.inject=xml.injectafter
+xml.after=xml.insertafter
+xml.before=xml.insertbefore
+xml.process=xml.each
+xml.obsolete=xml.obsolete or {}
+local obsolete=xml.obsolete
+xml.strip_whitespace=xml.strip obsolete.strip_whitespace=xml.strip
+xml.collect_elements=xml.collect obsolete.collect_elements=xml.collect
+xml.delete_element=xml.delete obsolete.delete_element=xml.delete
+xml.replace_element=xml.replace obsolete.replace_element=xml.replacet
+xml.each_element=xml.each obsolete.each_element=xml.each
+xml.process_elements=xml.process obsolete.process_elements=xml.process
+xml.insert_element_after=xml.insertafter obsolete.insert_element_after=xml.insertafter
+xml.insert_element_before=xml.insertbefore obsolete.insert_element_before=xml.insertbefore
+xml.inject_element_after=xml.injectafter obsolete.inject_element_after=xml.injectafter
+xml.inject_element_before=xml.injectbefore obsolete.inject_element_before=xml.injectbefore
+xml.process_attributes=xml.processattributes obsolete.process_attributes=xml.processattributes
+xml.collect_texts=xml.collecttexts obsolete.collect_texts=xml.collecttexts
+xml.inject_element=xml.inject obsolete.inject_element=xml.inject
+xml.remap_tag=xml.remaptag obsolete.remap_tag=xml.remaptag
+xml.remap_name=xml.remapname obsolete.remap_name=xml.remapname
+xml.remap_namespace=xml.remapnamespace obsolete.remap_namespace=xml.remapnamespace
+function xml.cdata(e)
+ if e then
+ local dt=e.dt
+ if dt and #dt==1 then
+ local first=dt[1]
+ return first.tg=="@cd@" and first.dt[1] or ""
+ end
+ end
+ return ""
end
-
-local function findgivenfiles(filename,allresults)
- local bname, result = filebasename(filename), { }
- local hashes = instance.hashes
- local noffound = 0
- for k=1,#hashes do
- local hash = hashes[k]
- local files = instance.files[hash.name] or { }
- local blist = files[bname]
- if not blist then
- local rname = "remap:"..bname
- blist = files[rname]
- if blist then
- bname = files[rname]
- blist = files[bname]
- end
- end
- if blist then
- if type(blist) == 'string' then
- local found = methodhandler('concatinators',hash.type,hash.name,blist,bname) or ""
- if found ~= "" then
- noffound = noffound + 1
- result[noffound] = resolvers.resolve(found)
- if not allresults then break end
- end
+function xml.finalizers.xml.cdata(collected)
+ if collected then
+ local e=collected[1]
+ if e then
+ local dt=e.dt
+ if dt and #dt==1 then
+ local first=dt[1]
+ return first.tg=="@cd@" and first.dt[1] or ""
+ end
+ end
+ end
+ return ""
+end
+function xml.insertcomment(e,str,n)
+ table.insert(e.dt,n or 1,{
+ tg="@cm@",
+ ns="",
+ special=true,
+ at={},
+ dt={ str },
+ })
+end
+function xml.setcdata(e,str)
+ e.dt={ {
+ tg="@cd@",
+ ns="",
+ special=true,
+ at={},
+ dt={ str },
+ } }
+end
+function xml.separate(x,pattern)
+ local collected=xmlapplylpath(x,pattern)
+ if collected then
+ for c=1,#collected do
+ local e=collected[c]
+ local d=e.dt
+ if d==x then
+ report_xml("warning: xml.separate changes root")
+ x=d
+ end
+ local t,n={ "\n" },1
+ local i,nd=1,#d
+ while i<=nd do
+ while i<=nd do
+ local di=d[i]
+ if type(di)=="string" then
+ if di=="\n" or find(di,"^%s+$") then
+ i=i+1
else
- for kk=1,#blist do
- local vv = blist[kk]
- local found = methodhandler('concatinators',hash.type,hash.name,vv,bname) or ""
- if found ~= "" then
- noffound = noffound + 1
- result[noffound] = resolvers.resolve(found)
- if not allresults then break end
- end
- end
+ d[i]=strip(di)
+ break
end
+ else
+ break
+ end
+ end
+ if i>nd then
+ break
+ end
+ t[n+1]="\n"
+ t[n+2]=d[i]
+ t[n+3]="\n"
+ n=n+3
+ i=i+1
+ end
+ t[n+1]="\n"
+ setmetatable(t,getmetatable(d))
+ e.dt=t
+ end
+ end
+ return x
+end
+local helpers=xml.helpers or {}
+xml.helpers=helpers
+local function normal(e,action)
+ local edt=e.dt
+ if edt then
+ for i=1,#edt do
+ local str=edt[i]
+ if type(str)=="string" and str~="" then
+ edt[i]=action(str)
+ end
+ end
+ end
+end
+local function recurse(e,action)
+ local edt=e.dt
+ if edt then
+ for i=1,#edt do
+ local str=edt[i]
+ if type(str)~="string" then
+ recurse(str,action,recursive)
+ elseif str~="" then
+ edt[i]=action(str)
+ end
+ end
+ end
+end
+function helpers.recursetext(collected,action,recursive)
+ if recursive then
+ for i=1,#collected do
+ recurse(collected[i],action)
+ end
+ else
+ for i=1,#collected do
+ normal(collected[i],action)
+ end
+ end
+end
+
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
+package.loaded["lxml-xml"] = package.loaded["lxml-xml"] or true
+
+-- original size: 10274, stripped down to: 7538
+
+if not modules then modules={} end modules ['lxml-xml']={
+ version=1.001,
+ comment="this module is the basis for the lxml-* ones",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local concat=table.concat
+local find,lower,upper=string.find,string.lower,string.upper
+local xml=xml
+local finalizers=xml.finalizers.xml
+local xmlfilter=xml.filter
+local xmltostring=xml.tostring
+local xmlserialize=xml.serialize
+local xmlcollected=xml.collected
+local xmlnewhandlers=xml.newhandlers
+local function first(collected)
+ return collected and collected[1]
+end
+local function last(collected)
+ return collected and collected[#collected]
+end
+local function all(collected)
+ return collected
+end
+local reverse=table.reversed
+local function attribute(collected,name)
+ if collected and #collected>0 then
+ local at=collected[1].at
+ return at and at[name]
+ end
+end
+local function att(id,name)
+ local at=id.at
+ return at and at[name]
+end
+local function count(collected)
+ return collected and #collected or 0
+end
+local function position(collected,n)
+ if not collected then
+ return 0
+ end
+ local nc=#collected
+ if nc==0 then
+ return 0
+ end
+ n=tonumber(n) or 0
+ if n<0 then
+ return collected[nc+n+1]
+ elseif n>0 then
+ return collected[n]
+ else
+ return collected[1].mi or 0
+ end
+end
+local function match(collected)
+ return collected and #collected>0 and collected[1].mi or 0
+end
+local function index(collected)
+ return collected and #collected>0 and collected[1].ni or 0
+end
+local function attributes(collected,arguments)
+ if collected and #collected>0 then
+ local at=collected[1].at
+ if arguments then
+ return at[arguments]
+ elseif next(at) then
+ return at
+ end
+ end
+end
+local function chainattribute(collected,arguments)
+ if collected and #collected>0 then
+ local e=collected[1]
+ while e do
+ local at=e.at
+ if at then
+ local a=at[arguments]
+ if a then
+ return a
end
+ else
+ break
+ end
+ e=e.__p__
end
+ end
+ return ""
+end
+local function raw(collected)
+ if collected and #collected>0 then
+ local e=collected[1] or collected
+ return e and xmltostring(e) or ""
+ else
+ return ""
+ end
+end
+local xmltexthandler=xmlnewhandlers {
+ name="string",
+ initialize=function()
+ result={}
return result
+ end,
+ finalize=function()
+ return concat(result)
+ end,
+ handle=function(...)
+ result[#result+1]=concat {... }
+ end,
+ escape=false,
+}
+local function xmltotext(root)
+ local dt=root.dt
+ if not dt then
+ return ""
+ end
+ local nt=#dt
+ if nt==0 then
+ return ""
+ elseif nt==1 and type(dt[1])=="string" then
+ return dt[1]
+ else
+ return xmlserialize(root,xmltexthandler) or ""
+ end
+end
+local function text(collected)
+ if collected then
+ local e=collected[1] or collected
+ return e and xmltotext(e) or ""
+ else
+ return ""
+ end
end
-
-function resolvers.findgivenfiles(filename)
- return findgivenfiles(filename,true)
+local function texts(collected)
+ if not collected then
+ return {}
+ end
+ local nc=#collected
+ if nc==0 then
+ return {}
+ end
+ local t,n={},0
+ for c=1,nc do
+ local e=collected[c]
+ if e and e.dt then
+ n=n+1
+ t[n]=e.dt
+ end
+ end
+ return t
end
-
-function resolvers.findgivenfile(filename)
- return findgivenfiles(filename,false)[1] or ""
+local function tag(collected,n)
+ if not collected then
+ return
+ end
+ local nc=#collected
+ if nc==0 then
+ return
+ end
+ local c
+ if n==0 or not n then
+ c=collected[1]
+ elseif n>1 then
+ c=collected[n]
+ else
+ c=collected[nc-n+1]
+ end
+ return c and c.tg
end
-
-local function doit(path,blist,bname,tag,variant,result,allresults)
- local done = false
- if blist and variant then
- local resolve = resolvers.resolve -- added
- if type(blist) == 'string' then
- -- make function and share code
- if find(lower(blist),path) then
- local full = methodhandler('concatinators',variant,tag,blist,bname) or ""
- result[#result+1] = resolve(full)
- done = true
- end
+local function name(collected,n)
+ if not collected then
+ return
+ end
+ local nc=#collected
+ if nc==0 then
+ return
+ end
+ local c
+ if n==0 or not n then
+ c=collected[1]
+ elseif n>1 then
+ c=collected[n]
+ else
+ c=collected[nc-n+1]
+ end
+ if not c then
+ elseif c.ns=="" then
+ return c.tg
+ else
+ return c.ns..":"..c.tg
+ end
+end
+local function tags(collected,nonamespace)
+ if not collected then
+ return
+ end
+ local nc=#collected
+ if nc==0 then
+ return
+ end
+ local t,n={},0
+ for c=1,nc do
+ local e=collected[c]
+ local ns,tg=e.ns,e.tg
+ n=n+1
+ if nonamespace or ns=="" then
+ t[n]=tg
+ else
+ t[n]=ns..":"..tg
+ end
+ end
+ return t
+end
+local function empty(collected,spacesonly)
+ if not collected then
+ return true
+ end
+ local nc=#collected
+ if nc==0 then
+ return true
+ end
+ for c=1,nc do
+ local e=collected[c]
+ if e then
+ local edt=e.dt
+ if edt then
+ local n=#edt
+ if n==1 then
+ local edk=edt[1]
+ local typ=type(edk)
+ if typ=="table" then
+ return false
+ elseif edk~="" then
+ return false
+ elseif spacesonly and not find(edk,"%S") then
+ return false
+ end
+ elseif n>1 then
+ return false
+ end
+ end
+ end
+ end
+ return true
+end
+finalizers.first=first
+finalizers.last=last
+finalizers.all=all
+finalizers.reverse=reverse
+finalizers.elements=all
+finalizers.default=all
+finalizers.attribute=attribute
+finalizers.att=att
+finalizers.count=count
+finalizers.position=position
+finalizers.match=match
+finalizers.index=index
+finalizers.attributes=attributes
+finalizers.chainattribute=chainattribute
+finalizers.text=text
+finalizers.texts=texts
+finalizers.tag=tag
+finalizers.name=name
+finalizers.tags=tags
+finalizers.empty=empty
+function xml.first(id,pattern)
+ return first(xmlfilter(id,pattern))
+end
+function xml.last(id,pattern)
+ return last(xmlfilter(id,pattern))
+end
+function xml.count(id,pattern)
+ return count(xmlfilter(id,pattern))
+end
+function xml.attribute(id,pattern,a,default)
+ return attribute(xmlfilter(id,pattern),a,default)
+end
+function xml.raw(id,pattern)
+ if pattern then
+ return raw(xmlfilter(id,pattern))
+ else
+ return raw(id)
+ end
+end
+function xml.text(id,pattern)
+ if pattern then
+ local collected=xmlfilter(id,pattern)
+ return collected and #collected>0 and xmltotext(collected[1]) or ""
+ elseif id then
+ return xmltotext(id) or ""
+ else
+ return ""
+ end
+end
+xml.content=text
+function xml.position(id,pattern,n)
+ return position(xmlfilter(id,pattern),n)
+end
+function xml.match(id,pattern)
+ return match(xmlfilter(id,pattern))
+end
+function xml.empty(id,pattern,spacesonly)
+ return empty(xmlfilter(id,pattern),spacesonly)
+end
+xml.all=xml.filter
+xml.index=xml.position
+xml.found=xml.filter
+local function totable(x)
+ local t={}
+ for e in xmlcollected(x[1] or x,"/*") do
+ t[e.tg]=xmltostring(e.dt) or ""
+ end
+ return next(t) and t or nil
+end
+xml.table=totable
+finalizers.table=totable
+local function textonly(e,t)
+ if e then
+ local edt=e.dt
+ if edt then
+ for i=1,#edt do
+ local e=edt[i]
+ if type(e)=="table" then
+ textonly(e,t)
else
- for kk=1,#blist do
- local vv = blist[kk]
- if find(lower(vv),path) then
- local full = methodhandler('concatinators',variant,tag,vv,bname) or ""
- result[#result+1] = resolve(full)
- done = true
- if not allresults then break end
- end
- end
+ t[#t+1]=e
end
+ end
end
- return done
+ end
+ return t
end
-
-
-local makewildcard = Cs(
- (P("^")^0 * P("/") * P(-1) + P(-1)) /".*"
- + (P("^")^0 * P("/") / "")^0 * (P("*")/".*" + P("-")/"%%-" + P(".")/"%%." + P("?")/"."+ P("\\")/"/" + P(1))^0
-)
-
-function resolvers.wildcardpattern(pattern)
- return lpegmatch(makewildcard,pattern) or pattern
-end
-
-local function findwildcardfiles(filename,allresults,result) -- todo: remap: and lpeg
- result = result or { }
- local base = filebasename(filename)
- local dirn = filedirname(filename)
- local path = lower(lpegmatch(makewildcard,dirn) or dirn)
- local name = lower(lpegmatch(makewildcard,base) or base)
- local files, done = instance.files, false
- if find(name,"%*") then
- local hashes = instance.hashes
- for k=1,#hashes do
- local hash = hashes[k]
- local hashname, hashtype = hash.name, hash.type
- for kk, hh in next, files[hashname] do
- if not find(kk,"^remap:") then
- if find(lower(kk),name) then
- if doit(path,hh,kk,hashname,hashtype,result,allresults) then done = true end
- if done and not allresults then break end
- end
- end
- end
+function xml.textonly(e)
+ return concat(textonly(e,{}))
+end
+function finalizers.lowerall(collected)
+ for c=1,#collected do
+ local e=collected[c]
+ if not e.special then
+ e.tg=lower(e.tg)
+ local eat=e.at
+ if eat then
+ local t={}
+ for k,v in next,eat do
+ t[lower(k)]=v
end
- else
- local hashes = instance.hashes
- for k=1,#hashes do
- local hash = hashes[k]
- local hashname, hashtype = hash.name, hash.type
- if doit(path,files[hashname][bname],bname,hashname,hashtype,result,allresults) then done = true end
- if done and not allresults then break end
+ e.at=t
+ end
+ end
+ end
+end
+function finalizers.upperall(collected)
+ for c=1,#collected do
+ local e=collected[c]
+ if not e.special then
+ e.tg=upper(e.tg)
+ local eat=e.at
+ if eat then
+ local t={}
+ for k,v in next,eat do
+ t[upper(k)]=v
end
+ e.at=t
+ end
end
- -- we can consider also searching the paths not in the database, but then
- -- we end up with a messy search (all // in all path specs)
- return result
+ end
end
-function resolvers.findwildcardfiles(filename,result)
- return findwildcardfiles(filename,true,result)
-end
-function resolvers.findwildcardfile(filename)
- return findwildcardfiles(filename,false)[1] or ""
-end
+end -- of closure
--- main user functions
+do -- create closure to overcome 200 locals limit
-function resolvers.automount()
- -- implemented later
-end
+package.loaded["trac-xml"] = package.loaded["trac-xml"] or true
-function resolvers.load(option)
- statistics.starttiming(instance)
- identify_configuration_files()
- load_configuration_files()
- if option ~= "nofiles" then
- load_databases()
- resolvers.automount()
- end
- statistics.stoptiming(instance)
- local files = instance.files
- return files and next(files) and true
-end
+-- original size: 6351, stripped down to: 4919
-function resolvers.loadtime()
- return statistics.elapsedtime(instance)
+if not modules then modules={} end modules ['trac-xml']={
+ version=1.001,
+ comment="companion to trac-log.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local formatters=string.formatters
+local reporters=logs.reporters
+local xmlserialize=xml.serialize
+local xmlcollected=xml.collected
+local xmltext=xml.text
+local xmlfirst=xml.first
+local function showhelp(specification,...)
+ local root=xml.convert(specification.helpinfo or "")
+ if not root then
+ return
+ end
+ local xs=xml.gethandlers("string")
+ xml.sethandlersfunction(xs,"short",function(e,handler) xmlserialize(e.dt,handler) end)
+ xml.sethandlersfunction(xs,"ref",function(e,handler) handler.handle("--"..e.at.name) end)
+ local wantedcategories=select("#",...)==0 and true or table.tohash {... }
+ local nofcategories=xml.count(root,"/application/flags/category")
+ local report=specification.report
+ for category in xmlcollected(root,"/application/flags/category") do
+ local categoryname=category.at.name or ""
+ if wantedcategories==true or wantedcategories[categoryname] then
+ if nofcategories>1 then
+ report("%s options:",categoryname)
+ report()
+ end
+ for subcategory in xmlcollected(category,"/subcategory") do
+ for flag in xmlcollected(subcategory,"/flag") do
+ local name=flag.at.name
+ local value=flag.at.value
+ local short=xmltext(xmlfirst(flag,"/short"))
+ if value then
+ report("--%-20s %s",formatters["%s=%s"](name,value),short)
+ else
+ report("--%-20s %s",name,short)
+ end
+ end
+ report()
+ end
+ end
+ end
+ for category in xmlcollected(root,"/application/examples/category") do
+ local title=xmltext(xmlfirst(category,"/title"))
+ if title and title~="" then
+ report()
+ report(title)
+ report()
+ end
+ for subcategory in xmlcollected(category,"/subcategory") do
+ for example in xmlcollected(subcategory,"/example") do
+ local command=xmltext(xmlfirst(example,"/command"))
+ local comment=xmltext(xmlfirst(example,"/comment"))
+ report(command)
+ end
+ report()
+ end
+ end
+ for comment in xmlcollected(root,"/application/comments/comment") do
+ local comment=xmltext(comment)
+ report()
+ report(comment)
+ report()
+ end
end
-
-local function report(str)
- if trace_locating then
- report_resolving(str) -- has already verbose
+local reporthelp=reporters.help
+local exporthelp=reporters.export
+local function xmlfound(t)
+ local helpinfo=t.helpinfo
+ if type(helpinfo)=="table" then
+ return false
+ end
+ if type(helpinfo)~="string" then
+ helpinfo="Warning: no helpinfo found."
+ t.helpinfo=helpinfo
+ return false
+ end
+ if string.find(helpinfo,".xml$") then
+ local ownscript=environment.ownscript
+ local helpdata=false
+ if ownscript then
+ local helpfile=file.join(file.pathpart(ownscript),helpinfo)
+ helpdata=io.loaddata(helpfile)
+ if helpdata=="" then
+ helpdata=false
+ end
+ end
+ if not helpdata then
+ local helpfile=resolvers.findfile(helpinfo,"tex")
+ helpdata=helpfile and io.loaddata(helpfile)
+ end
+ if helpdata and helpdata~="" then
+ helpinfo=helpdata
+ else
+ helpinfo=formatters["Warning: help file %a is not found."](helpinfo)
+ end
+ end
+ t.helpinfo=helpinfo
+ return string.find(t.helpinfo,"^<%?xml") and true or false
+end
+function reporters.help(t,...)
+ if xmlfound(t) then
+ showhelp(t,...)
+ else
+ reporthelp(t,...)
+ end
+end
+function reporters.export(t,methods,filename)
+ if not xmlfound(t) then
+ return exporthelp(t)
+ end
+ if not methods or methods=="" then
+ methods=environment.arguments["exporthelp"]
+ end
+ if not filename or filename=="" then
+ filename=environment.files[1]
+ end
+ dofile(resolvers.findfile("trac-exp.lua","tex"))
+ local exporters=logs.exporters
+ if not exporters or not methods then
+ return exporthelp(t)
+ end
+ if methods=="all" then
+ methods=table.keys(exporters)
+ elseif type(methods)=="string" then
+ methods=utilities.parsers.settings_to_array(methods)
+ else
+ return exporthelp(t)
+ end
+ if type(filename)~="string" or filename=="" then
+ filename=false
+ elseif file.pathpart(filename)=="" then
+ t.report("export file %a will not be saved on the current path (safeguard)",filename)
+ return
+ end
+ for i=1,#methods do
+ local method=methods[i]
+ local exporter=exporters[method]
+ if exporter then
+ local result=exporter(t,method)
+ if result and result~="" then
+ if filename then
+ local fullname=file.replacesuffix(filename,method)
+ t.report("saving export in %a",fullname)
+ io.savedata(fullname,result)
+ else
+ reporters.lines(t,result)
+ end
+ else
+ t.report("no output from exporter %a",method)
+ end
else
- print(str)
+ t.report("unknown exporter %a",method)
end
+ end
end
-function resolvers.dowithfilesandreport(command, files, ...) -- will move
- if files and #files > 0 then
- if trace_locating then
- report('') -- ?
- end
- if type(files) == "string" then
- files = { files }
- end
- for f=1,#files do
- local file = files[f]
- local result = command(file,...)
- if type(result) == 'string' then
- report(result)
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
+package.loaded["data-ini"] = package.loaded["data-ini"] or true
+
+-- original size: 7898, stripped down to: 5501
+
+if not modules then modules={} end modules ['data-ini']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files",
+}
+local gsub,find,gmatch,char=string.gsub,string.find,string.gmatch,string.char
+local next,type=next,type
+local filedirname,filebasename,filejoin=file.dirname,file.basename,file.join
+local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end)
+local trace_detail=false trackers.register("resolvers.details",function(v) trace_detail=v end)
+local trace_expansions=false trackers.register("resolvers.expansions",function(v) trace_expansions=v end)
+local report_initialization=logs.reporter("resolvers","initialization")
+local ostype,osname,ossetenv,osgetenv=os.type,os.name,os.setenv,os.getenv
+resolvers=resolvers or {}
+local resolvers=resolvers
+texconfig.kpse_init=false
+texconfig.shell_escape='t'
+if not (environment and environment.default_texmfcnf) and kpse and kpse.default_texmfcnf then
+ local default_texmfcnf=kpse.default_texmfcnf()
+ default_texmfcnf=gsub(default_texmfcnf,"$SELFAUTOLOC","selfautoloc:")
+ default_texmfcnf=gsub(default_texmfcnf,"$SELFAUTODIR","selfautodir:")
+ default_texmfcnf=gsub(default_texmfcnf,"$SELFAUTOPARENT","selfautoparent:")
+ default_texmfcnf=gsub(default_texmfcnf,"$HOME","home:")
+ environment.default_texmfcnf=default_texmfcnf
+end
+kpse={ original=kpse }
+setmetatable(kpse,{
+ __index=function(kp,name)
+ report_initialization("fatal error: kpse library is accessed (key: %s)",name)
+ os.exit()
+ end
+} )
+do
+ local osfontdir=osgetenv("OSFONTDIR")
+ if osfontdir and osfontdir~="" then
+ elseif osname=="windows" then
+ ossetenv("OSFONTDIR","c:/windows/fonts//")
+ elseif osname=="macosx" then
+ ossetenv("OSFONTDIR","$HOME/Library/Fonts//;/Library/Fonts//;/System/Library/Fonts//")
+ end
+end
+do
+ local homedir=osgetenv(ostype=="windows" and 'USERPROFILE' or 'HOME') or ''
+ if not homedir or homedir=="" then
+ homedir=char(127)
+ end
+ homedir=file.collapsepath(homedir)
+ ossetenv("HOME",homedir)
+ ossetenv("USERPROFILE",homedir)
+ environment.homedir=homedir
+end
+do
+ local args=environment.originalarguments or arg
+ if not environment.ownmain then
+ environment.ownmain=status and string.match(string.lower(status.banner),"this is ([%a]+)") or "luatex"
+ end
+ local ownbin=environment.ownbin or args[-2] or arg[-2] or args[-1] or arg[-1] or arg[0] or "luatex"
+ local ownpath=environment.ownpath or os.selfdir
+ ownbin=file.collapsepath(ownbin)
+ ownpath=file.collapsepath(ownpath)
+ if not ownpath or ownpath=="" or ownpath=="unset" then
+ ownpath=args[-1] or arg[-1]
+ ownpath=ownpath and filedirname(gsub(ownpath,"\\","/"))
+ if not ownpath or ownpath=="" then
+ ownpath=args[-0] or arg[-0]
+ ownpath=ownpath and filedirname(gsub(ownpath,"\\","/"))
+ end
+ local binary=ownbin
+ if not ownpath or ownpath=="" then
+ ownpath=ownpath and filedirname(binary)
+ end
+ if not ownpath or ownpath=="" then
+ if os.binsuffix~="" then
+ binary=file.replacesuffix(binary,os.binsuffix)
+ end
+ local path=osgetenv("PATH")
+ if path then
+ for p in gmatch(path,"[^"..io.pathseparator.."]+") do
+ local b=filejoin(p,binary)
+ if lfs.isfile(b) then
+ local olddir=lfs.currentdir()
+ if lfs.chdir(p) then
+ local pp=lfs.currentdir()
+ if trace_locating and p~=pp then
+ report_initialization("following symlink %a to %a",p,pp)
+ end
+ ownpath=pp
+ lfs.chdir(olddir)
else
- for i=1,#result do
- report(result[i]) -- could be unpack
- end
+ if trace_locating then
+ report_initialization("unable to check path %a",p)
+ end
+ ownpath=p
end
+ break
+ end
end
+ end
+ end
+ if not ownpath or ownpath=="" then
+ ownpath="."
+ report_initialization("forcing fallback to ownpath %a",ownpath)
+ elseif trace_locating then
+ report_initialization("using ownpath %a",ownpath)
end
+ end
+ environment.ownbin=ownbin
+ environment.ownpath=ownpath
+end
+resolvers.ownpath=environment.ownpath
+function resolvers.getownpath()
+ return environment.ownpath
+end
+do
+ local ownpath=environment.ownpath or dir.current()
+ if ownpath then
+ ossetenv('SELFAUTOLOC',file.collapsepath(ownpath))
+ ossetenv('SELFAUTODIR',file.collapsepath(ownpath.."/.."))
+ ossetenv('SELFAUTOPARENT',file.collapsepath(ownpath.."/../.."))
+ else
+ report_initialization("error: unable to locate ownpath")
+ os.exit()
+ end
+end
+local texos=environment.texos or osgetenv("TEXOS")
+local texmfos=environment.texmfos or osgetenv('SELFAUTODIR')
+if not texos or texos=="" then
+ texos=file.basename(texmfos)
+end
+ossetenv('TEXMFOS',texmfos)
+ossetenv('TEXOS',texos)
+ossetenv('SELFAUTOSYSTEM',os.platform)
+environment.texos=texos
+environment.texmfos=texmfos
+local texroot=environment.texroot or osgetenv("TEXROOT")
+if not texroot or texroot=="" then
+ texroot=osgetenv('SELFAUTOPARENT')
+ ossetenv('TEXROOT',texroot)
+end
+environment.texroot=file.collapsepath(texroot)
+if profiler then
+ directives.register("system.profile",function()
+ profiler.start("luatex-profile.log")
+ end)
+end
+if not resolvers.resolve then
+ function resolvers.resolve (s) return s end
+ function resolvers.unresolve(s) return s end
+ function resolvers.repath (s) return s end
end
--- obsolete
--- resolvers.varvalue = resolvers.variable -- output the value of variable $STRING.
--- resolvers.expandvar = resolvers.expansion -- output variable expansion of STRING.
+end -- of closure
-function resolvers.showpath(str) -- output search path for file type NAME
- return joinpath(resolvers.expandedpathlist(resolvers.formatofvariable(str)))
-end
+do -- create closure to overcome 200 locals limit
-function resolvers.registerfile(files, name, path)
- if files[name] then
- if type(files[name]) == 'string' then
- files[name] = { files[name], path }
- else
- files[name] = path
- end
- else
- files[name] = path
+package.loaded["data-exp"] = package.loaded["data-exp"] or true
+
+-- original size: 14643, stripped down to: 9517
+
+if not modules then modules={} end modules ['data-exp']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files",
+}
+local format,find,gmatch,lower,char,sub=string.format,string.find,string.gmatch,string.lower,string.char,string.sub
+local concat,sort=table.concat,table.sort
+local lpegmatch,lpegpatterns=lpeg.match,lpeg.patterns
+local Ct,Cs,Cc,P,C,S=lpeg.Ct,lpeg.Cs,lpeg.Cc,lpeg.P,lpeg.C,lpeg.S
+local type,next=type,next
+local ostype=os.type
+local collapsepath=file.collapsepath
+local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end)
+local trace_expansions=false trackers.register("resolvers.expansions",function(v) trace_expansions=v end)
+local report_expansions=logs.reporter("resolvers","expansions")
+local resolvers=resolvers
+local function f_first(a,b)
+ local t,n={},0
+ for s in gmatch(b,"[^,]+") do
+ n=n+1;t[n]=a..s
+ end
+ return concat(t,",")
+end
+local function f_second(a,b)
+ local t,n={},0
+ for s in gmatch(a,"[^,]+") do
+ n=n+1;t[n]=s..b
+ end
+ return concat(t,",")
+end
+local function f_both(a,b)
+ local t,n={},0
+ for sb in gmatch(b,"[^,]+") do
+ for sa in gmatch(a,"[^,]+") do
+ n=n+1;t[n]=sa..sb
+ end
+ end
+ return concat(t,",")
+end
+local left=P("{")
+local right=P("}")
+local var=P((1-S("{}" ))^0)
+local set=P((1-S("{},"))^0)
+local other=P(1)
+local l_first=Cs((Cc("{")*(C(set)*left*C(var)*right/f_first)*Cc("}")+other )^0 )
+local l_second=Cs((Cc("{")*(left*C(var)*right*C(set)/f_second)*Cc("}")+other )^0 )
+local l_both=Cs((Cc("{")*(left*C(var)*right*left*C(var)*right/f_both)*Cc("}")+other )^0 )
+local l_rest=Cs((left*var*(left/"")*var*(right/"")*var*right+other )^0 )
+local stripper_1=lpeg.stripper ("{}@")
+local replacer_1=lpeg.replacer { { ",}",",@}" },{ "{,","{@," },}
+local function splitpathexpr(str,newlist,validate)
+ if trace_expansions then
+ report_expansions("expanding variable %a",str)
+ end
+ local t,ok,done=newlist or {},false,false
+ local n=#t
+ str=lpegmatch(replacer_1,str)
+ repeat
+ local old=str
+ repeat
+ local old=str
+ str=lpegmatch(l_first,str)
+ until old==str
+ repeat
+ local old=str
+ str=lpegmatch(l_second,str)
+ until old==str
+ repeat
+ local old=str
+ str=lpegmatch(l_both,str)
+ until old==str
+ repeat
+ local old=str
+ str=lpegmatch(l_rest,str)
+ until old==str
+ until old==str
+ str=lpegmatch(stripper_1,str)
+ if validate then
+ for s in gmatch(str,"[^,]+") do
+ s=validate(s)
+ if s then
+ n=n+1
+ t[n]=s
+ end
+ end
+ else
+ for s in gmatch(str,"[^,]+") do
+ n=n+1
+ t[n]=s
+ end
+ end
+ if trace_expansions then
+ for k=1,#t do
+ report_expansions("% 4i: %s",k,t[k])
end
+ end
+ return t
end
-
-function resolvers.dowithpath(name,func)
- local pathlist = resolvers.expandedpathlist(name)
- for i=1,#pathlist do
- func("^"..resolvers.cleanpath(pathlist[i]))
+local function validate(s)
+ s=collapsepath(s)
+ return s~="" and not find(s,"^!*unset/*$") and s
+end
+resolvers.validatedpath=validate
+function resolvers.expandedpathfromlist(pathlist)
+ local newlist={}
+ for k=1,#pathlist do
+ splitpathexpr(pathlist[k],newlist,validate)
+ end
+ return newlist
+end
+local cleanup=lpeg.replacer {
+ { "!","" },
+ { "\\","/" },
+}
+function resolvers.cleanpath(str)
+ local doslashes=(P("\\")/"/"+1)^0
+ local donegation=(P("!")/"" )^0
+ local homedir=lpegmatch(Cs(donegation*doslashes),environment.homedir or "")
+ if homedir=="~" or homedir=="" or not lfs.isdir(homedir) then
+ if trace_expansions then
+ report_expansions("no home dir set, ignoring dependent paths")
+ end
+ function resolvers.cleanpath(str)
+ if not str or find(str,"~") then
+ return ""
+ else
+ return lpegmatch(cleanup,str)
+ end
+ end
+ else
+ local dohome=((P("~")+P("$HOME"))/homedir)^0
+ local cleanup=Cs(donegation*dohome*doslashes)
+ function resolvers.cleanpath(str)
+ return str and lpegmatch(cleanup,str) or ""
+ end
+ end
+ return resolvers.cleanpath(str)
+end
+local expandhome=P("~")/"$HOME"
+local dodouble=P('"')/""*(expandhome+(1-P('"')))^0*P('"')/""
+local dosingle=P("'")/""*(expandhome+(1-P("'")))^0*P("'")/""
+local dostring=(expandhome+1 )^0
+local stripper=Cs(
+ lpegpatterns.unspacer*(dosingle+dodouble+dostring)*lpegpatterns.unspacer
+)
+function resolvers.checkedvariable(str)
+ return type(str)=="string" and lpegmatch(stripper,str) or str
+end
+local cache={}
+local splitter=lpeg.tsplitat(";")
+local backslashswapper=lpeg.replacer("\\","/")
+local function splitconfigurationpath(str)
+ if str then
+ local found=cache[str]
+ if not found then
+ if str=="" then
+ found={}
+ else
+ local split=lpegmatch(splitter,lpegmatch(backslashswapper,str))
+ found={}
+ local noffound=0
+ for i=1,#split do
+ local s=split[i]
+ if not find(s,"^{*unset}*") then
+ noffound=noffound+1
+ found[noffound]=s
+ end
+ end
+ if trace_expansions then
+ report_expansions("splitting path specification %a",str)
+ for k=1,noffound do
+ report_expansions("% 4i: %s",k,found[k])
+ end
+ end
+ cache[str]=found
+ end
end
+ return found
+ end
end
-
-function resolvers.dowithvariable(name,func)
- func(expandedvariable(name))
+resolvers.splitconfigurationpath=splitconfigurationpath
+function resolvers.splitpath(str)
+ if type(str)=='table' then
+ return str
+ else
+ return splitconfigurationpath(str)
+ end
end
-
-function resolvers.locateformat(name)
- local barename = file.removesuffix(name) -- gsub(name,"%.%a+$","")
- local fmtname = caches.getfirstreadablefile(barename..".fmt","formats") or ""
- if fmtname == "" then
- fmtname = resolvers.findfile(barename..".fmt")
- fmtname = resolvers.cleanpath(fmtname)
- end
- if fmtname ~= "" then
- local barename = file.removesuffix(fmtname)
- local luaname, lucname, luiname = barename .. ".lua", barename .. ".luc", barename .. ".lui"
- if lfs.isfile(luiname) then
- return barename, luiname
- elseif lfs.isfile(lucname) then
- return barename, lucname
- elseif lfs.isfile(luaname) then
- return barename, luaname
+function resolvers.joinpath(str)
+ if type(str)=='table' then
+ return file.joinpath(str)
+ else
+ return str
+ end
+end
+local attributes,directory=lfs.attributes,lfs.dir
+local weird=P(".")^1+lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+local timer={}
+local scanned={}
+local nofscans=0
+local scancache={}
+local function scan(files,spec,path,n,m,r)
+ local full=(path=="" and spec) or (spec..path..'/')
+ local dirs={}
+ local nofdirs=0
+ for name in directory(full) do
+ if not lpegmatch(weird,name) then
+ local mode=attributes(full..name,'mode')
+ if mode=='file' then
+ n=n+1
+ local f=files[name]
+ if f then
+ if type(f)=='string' then
+ files[name]={ f,path }
+ else
+ f[#f+1]=path
+ end
+ else
+ files[name]=path
+ local lower=lower(name)
+ if name~=lower then
+ files["remap:"..lower]=name
+ r=r+1
+ end
+ end
+ elseif mode=='directory' then
+ m=m+1
+ nofdirs=nofdirs+1
+ if path~="" then
+ dirs[nofdirs]=path..'/'..name
+ else
+ dirs[nofdirs]=name
end
+ end
end
- return nil, nil
-end
-
-function resolvers.booleanvariable(str,default)
- local b = resolvers.expansion(str)
- if b == "" then
- return default
- else
- b = toboolean(b)
- return (b == nil and default) or b
+ end
+ if nofdirs>0 then
+ sort(dirs)
+ for i=1,nofdirs do
+ files,n,m,r=scan(files,spec,dirs[i],n,m,r)
end
+ end
+ scancache[sub(full,1,-2)]=files
+ return files,n,m,r
end
-
-function resolvers.dowithfilesintree(pattern,handle,before,after) -- will move, can be a nice iterator instead
- local instance = resolvers.instance
- local hashes = instance.hashes
- for i=1,#hashes do
- local hash = hashes[i]
- local blobtype = hash.type
- local blobpath = hash.name
- if blobpath then
- if before then
- before(blobtype,blobpath,pattern)
- end
- local files = instance.files[blobpath]
- local total, checked, done = 0, 0, 0
- if files then
- for k,v in next, files do
- total = total + 1
- if find(k,"^remap:") then
- k = files[k]
- v = k -- files[k] -- chained
- end
- if find(k,pattern) then
- if type(v) == "string" then
- checked = checked + 1
- if handle(blobtype,blobpath,v,k) then
- done = done + 1
- end
- else
- checked = checked + #v
- for i=1,#v do
- if handle(blobtype,blobpath,v[i],k) then
- done = done + 1
- end
- end
- end
- end
- end
- end
- if after then
- after(blobtype,blobpath,pattern,total,checked,done)
- end
+local fullcache={}
+function resolvers.scanfiles(path,branch,usecache)
+ statistics.starttiming(timer)
+ local realpath=resolvers.resolve(path)
+ if usecache then
+ local files=fullcache[realpath]
+ if files then
+ if trace_locating then
+ report_expansions("using caches scan of path %a, branch %a",path,branch or path)
+ end
+ return files
+ end
+ end
+ if trace_locating then
+ report_expansions("scanning path %a, branch %a",path,branch or path)
+ end
+ local files,n,m,r=scan({},realpath..'/',"",0,0,0)
+ files.__path__=path
+ files.__files__=n
+ files.__directories__=m
+ files.__remappings__=r
+ if trace_locating then
+ report_expansions("%s files found on %s directories with %s uppercase remappings",n,m,r)
+ end
+ if usecache then
+ scanned[#scanned+1]=realpath
+ fullcache[realpath]=files
+ end
+ nofscans=nofscans+1
+ statistics.stoptiming(timer)
+ return files
+end
+local function simplescan(files,spec,path)
+ local full=(path=="" and spec) or (spec..path..'/')
+ local dirs={}
+ local nofdirs=0
+ for name in directory(full) do
+ if not lpegmatch(weird,name) then
+ local mode=attributes(full..name,'mode')
+ if mode=='file' then
+ if not files[name] then
+ files[name]=path
+ end
+ elseif mode=='directory' then
+ nofdirs=nofdirs+1
+ if path~="" then
+ dirs[nofdirs]=path..'/'..name
+ else
+ dirs[nofdirs]=name
end
+ end
end
+ end
+ if nofdirs>0 then
+ sort(dirs)
+ for i=1,nofdirs do
+ files=simplescan(files,spec,dirs[i])
+ end
+ end
+ return files
+end
+local simplecache={}
+local nofsharedscans=0
+function resolvers.simplescanfiles(path,branch,usecache)
+ statistics.starttiming(timer)
+ local realpath=resolvers.resolve(path)
+ if usecache then
+ local files=simplecache[realpath]
+ if not files then
+ files=scancache[realpath]
+ if files then
+ nofsharedscans=nofsharedscans+1
+ end
+ end
+ if files then
+ if trace_locating then
+ report_expansions("using caches scan of path %a, branch %a",path,branch or path)
+ end
+ return files
+ end
+ end
+ if trace_locating then
+ report_expansions("scanning path %a, branch %a",path,branch or path)
+ end
+ local files=simplescan({},realpath..'/',"")
+ if trace_locating then
+ report_expansions("%s files found",table.count(files))
+ end
+ if usecache then
+ scanned[#scanned+1]=realpath
+ simplecache[realpath]=files
+ end
+ nofscans=nofscans+1
+ statistics.stoptiming(timer)
+ return files
+end
+function resolvers.scandata()
+ table.sort(scanned)
+ return {
+ n=nofscans,
+ shared=nofsharedscans,
+ time=statistics.elapsedtime(timer),
+ paths=scanned,
+ }
end
-
-resolvers.obsolete = resolvers.obsolete or { }
-local obsolete = resolvers.obsolete
-
-resolvers.find_file = resolvers.findfile obsolete.find_file = resolvers.findfile
-resolvers.find_files = resolvers.findfiles obsolete.find_files = resolvers.findfiles
end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['data-pre'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- It could be interesting to hook the resolver in the file
--- opener so that unresolved prefixes travel around and we
--- get more abstraction.
-
--- As we use this beforehand we will move this up in the chain
--- of loading.
-
-
-local resolvers = resolvers
-local prefixes = utilities.storage.allocate()
-resolvers.prefixes = prefixes
+package.loaded["data-env"] = package.loaded["data-env"] or true
-local gsub = string.gsub
-local cleanpath, findgivenfile, expansion = resolvers.cleanpath, resolvers.findgivenfile, resolvers.expansion
-local getenv = resolvers.getenv -- we can probably also use resolvers.expansion
-local P, Cs, lpegmatch = lpeg.P, lpeg.Cs, lpeg.match
+-- original size: 8762, stripped down to: 6484
--- getenv = function(...) return resolvers.getenv(...) end -- needs checking (definitions changes later on)
-
-prefixes.environment = function(str)
- return cleanpath(expansion(str))
+if not modules then modules={} end modules ['data-env']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files",
+}
+local lower,gsub=string.lower,string.gsub
+local resolvers=resolvers
+local allocate=utilities.storage.allocate
+local setmetatableindex=table.setmetatableindex
+local suffixonly=file.suffixonly
+local formats=allocate()
+local suffixes=allocate()
+local dangerous=allocate()
+local suffixmap=allocate()
+resolvers.formats=formats
+resolvers.suffixes=suffixes
+resolvers.dangerous=dangerous
+resolvers.suffixmap=suffixmap
+local luasuffixes=utilities.lua.suffixes
+local relations=allocate {
+ core={
+ ofm={
+ names={ "ofm","omega font metric","omega font metrics" },
+ variable='OFMFONTS',
+ suffixes={ 'ofm','tfm' },
+ },
+ ovf={
+ names={ "ovf","omega virtual font","omega virtual fonts" },
+ variable='OVFFONTS',
+ suffixes={ 'ovf','vf' },
+ },
+ tfm={
+ names={ "tfm","tex font metric","tex font metrics" },
+ variable='TFMFONTS',
+ suffixes={ 'tfm' },
+ },
+ vf={
+ names={ "vf","virtual font","virtual fonts" },
+ variable='VFFONTS',
+ suffixes={ 'vf' },
+ },
+ otf={
+ names={ "otf","opentype","opentype font","opentype fonts"},
+ variable='OPENTYPEFONTS',
+ suffixes={ 'otf' },
+ },
+ ttf={
+ names={ "ttf","truetype","truetype font","truetype fonts","truetype collection","truetype collections","truetype dictionary","truetype dictionaries" },
+ variable='TTFONTS',
+ suffixes={ 'ttf','ttc','dfont' },
+ },
+ afm={
+ names={ "afm","adobe font metric","adobe font metrics" },
+ variable="AFMFONTS",
+ suffixes={ "afm" },
+ },
+ pfb={
+ names={ "pfb","type1","type 1","type1 font","type 1 font","type1 fonts","type 1 fonts" },
+ variable='T1FONTS',
+ suffixes={ 'pfb','pfa' },
+ },
+ fea={
+ names={ "fea","font feature","font features","font feature file","font feature files" },
+ variable='FONTFEATURES',
+ suffixes={ 'fea' },
+ },
+ cid={
+ names={ "cid","cid map","cid maps","cid file","cid files" },
+ variable='FONTCIDMAPS',
+ suffixes={ 'cid','cidmap' },
+ },
+ fmt={
+ names={ "fmt","format","tex format" },
+ variable='TEXFORMATS',
+ suffixes={ 'fmt' },
+ },
+ mem={
+ names={ 'mem',"metapost format" },
+ variable='MPMEMS',
+ suffixes={ 'mem' },
+ },
+ mp={
+ names={ "mp" },
+ variable='MPINPUTS',
+ suffixes={ 'mp','mpvi','mpiv','mpii' },
+ },
+ tex={
+ names={ "tex" },
+ variable='TEXINPUTS',
+ suffixes={ 'tex',"mkvi","mkiv","mkii" },
+ },
+ icc={
+ names={ "icc","icc profile","icc profiles" },
+ variable='ICCPROFILES',
+ suffixes={ 'icc' },
+ },
+ texmfscripts={
+ names={ "texmfscript","texmfscripts","script","scripts" },
+ variable='TEXMFSCRIPTS',
+ suffixes={ 'rb','pl','py' },
+ },
+ lua={
+ names={ "lua" },
+ variable='LUAINPUTS',
+ suffixes={ luasuffixes.lua,luasuffixes.luc,luasuffixes.tma,luasuffixes.tmc },
+ },
+ lib={
+ names={ "lib" },
+ variable='CLUAINPUTS',
+ suffixes=os.libsuffix and { os.libsuffix } or { 'dll','so' },
+ },
+ bib={
+ names={ 'bib' },
+ suffixes={ 'bib' },
+ },
+ bst={
+ names={ 'bst' },
+ suffixes={ 'bst' },
+ },
+ fontconfig={
+ names={ 'fontconfig','fontconfig file','fontconfig files' },
+ variable='FONTCONFIG_PATH',
+ },
+ },
+ obsolete={
+ enc={
+ names={ "enc","enc files","enc file","encoding files","encoding file" },
+ variable='ENCFONTS',
+ suffixes={ 'enc' },
+ },
+ map={
+ names={ "map","map files","map file" },
+ variable='TEXFONTMAPS',
+ suffixes={ 'map' },
+ },
+ lig={
+ names={ "lig files","lig file","ligature file","ligature files" },
+ variable='LIGFONTS',
+ suffixes={ 'lig' },
+ },
+ opl={
+ names={ "opl" },
+ variable='OPLFONTS',
+ suffixes={ 'opl' },
+ },
+ ovp={
+ names={ "ovp" },
+ variable='OVPFONTS',
+ suffixes={ 'ovp' },
+ },
+ },
+ kpse={
+ base={
+ names={ 'base',"metafont format" },
+ variable='MFBASES',
+ suffixes={ 'base','bas' },
+ },
+ cmap={
+ names={ 'cmap','cmap files','cmap file' },
+ variable='CMAPFONTS',
+ suffixes={ 'cmap' },
+ },
+ cnf={
+ names={ 'cnf' },
+ suffixes={ 'cnf' },
+ },
+ web={
+ names={ 'web' },
+ suffixes={ 'web','ch' }
+ },
+ cweb={
+ names={ 'cweb' },
+ suffixes={ 'w','web','ch' },
+ },
+ gf={
+ names={ 'gf' },
+ suffixes={ 'gf' },
+ },
+ mf={
+ names={ 'mf' },
+ variable='MFINPUTS',
+ suffixes={ 'mf' },
+ },
+ mft={
+ names={ 'mft' },
+ suffixes={ 'mft' },
+ },
+ pk={
+ names={ 'pk' },
+ suffixes={ 'pk' },
+ },
+ },
+}
+resolvers.relations=relations
+function resolvers.updaterelations()
+ for category,categories in next,relations do
+ for name,relation in next,categories do
+ local rn=relation.names
+ local rv=relation.variable
+ local rs=relation.suffixes
+ if rn and rv then
+ for i=1,#rn do
+ local rni=lower(gsub(rn[i]," ",""))
+ formats[rni]=rv
+ if rs then
+ suffixes[rni]=rs
+ for i=1,#rs do
+ local rsi=rs[i]
+ suffixmap[rsi]=rni
+ end
+ end
+ end
+ end
+ if rs then
+ end
+ end
+ end
+end
+resolvers.updaterelations()
+local function simplified(t,k)
+ return k and rawget(t,lower(gsub(k," ",""))) or nil
end
-
-prefixes.relative = function(str,n) -- lfs.isfile
- if io.exists(str) then
- -- nothing
- elseif io.exists("./" .. str) then
- str = "./" .. str
- else
- local p = "../"
- for i=1,n or 2 do
- if io.exists(p .. str) then
- str = p .. str
- break
- else
- p = p .. "../"
- end
- end
- end
- return cleanpath(str)
+setmetatableindex(formats,simplified)
+setmetatableindex(suffixes,simplified)
+setmetatableindex(suffixmap,simplified)
+function resolvers.suffixofformat(str)
+ local s=suffixes[str]
+ return s and s[1] or ""
end
-
-prefixes.auto = function(str)
- local fullname = prefixes.relative(str)
- if not lfs.isfile(fullname) then
- fullname = prefixes.locate(str)
- end
- return fullname
+function resolvers.suffixofformat(str)
+ return suffixes[str] or {}
end
-
-prefixes.locate = function(str)
- local fullname = findgivenfile(str) or ""
- return cleanpath((fullname ~= "" and fullname) or str)
+for name,format in next,formats do
+ dangerous[name]=true
end
-
-prefixes.filename = function(str)
- local fullname = findgivenfile(str) or ""
- return cleanpath(file.basename((fullname ~= "" and fullname) or str)) -- no cleanpath needed here
+dangerous.tex=nil
+function resolvers.formatofvariable(str)
+ return formats[str] or ''
end
-
-prefixes.pathname = function(str)
- local fullname = findgivenfile(str) or ""
- return cleanpath(file.dirname((fullname ~= "" and fullname) or str))
+function resolvers.formatofsuffix(str)
+ return suffixmap[suffixonly(str)] or 'tex'
end
-
-prefixes.selfautoloc = function(str)
- return cleanpath(file.join(getenv('SELFAUTOLOC'),str))
+function resolvers.variableofformat(str)
+ return formats[str] or ''
end
-
-prefixes.selfautoparent = function(str)
- return cleanpath(file.join(getenv('SELFAUTOPARENT'),str))
+function resolvers.variableofformatorsuffix(str)
+ local v=formats[str]
+ if v then
+ return v
+ end
+ v=suffixmap[suffixonly(str)]
+ if v then
+ return formats[v]
+ end
+ return ''
end
-prefixes.selfautodir = function(str)
- return cleanpath(file.join(getenv('SELFAUTODIR'),str))
-end
-prefixes.home = function(str)
- return cleanpath(file.join(getenv('HOME'),str))
-end
+end -- of closure
-prefixes.env = prefixes.environment
-prefixes.rel = prefixes.relative
-prefixes.loc = prefixes.locate
-prefixes.kpse = prefixes.locate
-prefixes.full = prefixes.locate
-prefixes.file = prefixes.filename
-prefixes.path = prefixes.pathname
+do -- create closure to overcome 200 locals limit
-function resolvers.allprefixes(separator)
- local all = table.sortedkeys(prefixes)
- if separator then
- for i=1,#all do
- all[i] = all[i] .. ":"
+package.loaded["data-tmp"] = package.loaded["data-tmp"] or true
+
+-- original size: 14308, stripped down to: 10956
+
+if not modules then modules={} end modules ['data-tmp']={
+ version=1.100,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local format,lower,gsub,concat=string.format,string.lower,string.gsub,table.concat
+local serialize,serializetofile=table.serialize,table.tofile
+local mkdirs,isdir,isfile=dir.mkdirs,lfs.isdir,lfs.isfile
+local addsuffix,is_writable,is_readable=file.addsuffix,file.is_writable,file.is_readable
+local formatters=string.formatters
+local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end)
+local trace_cache=false trackers.register("resolvers.cache",function(v) trace_cache=v end)
+local report_caches=logs.reporter("resolvers","caches")
+local report_resolvers=logs.reporter("resolvers","caching")
+local resolvers=resolvers
+local directive_cleanup=false directives.register("system.compile.cleanup",function(v) directive_cleanup=v end)
+local directive_strip=false directives.register("system.compile.strip",function(v) directive_strip=v end)
+local compile=utilities.lua.compile
+function utilities.lua.compile(luafile,lucfile,cleanup,strip)
+ if cleanup==nil then cleanup=directive_cleanup end
+ if strip==nil then strip=directive_strip end
+ return compile(luafile,lucfile,cleanup,strip)
+end
+caches=caches or {}
+local caches=caches
+local luasuffixes=utilities.lua.suffixes
+caches.base=caches.base or "luatex-cache"
+caches.more=caches.more or "context"
+caches.direct=false
+caches.tree=false
+caches.force=true
+caches.ask=false
+caches.relocate=false
+caches.defaults={ "TMPDIR","TEMPDIR","TMP","TEMP","HOME","HOMEPATH" }
+local writable,readables,usedreadables=nil,{},{}
+local function identify()
+ local texmfcaches=resolvers.cleanpathlist("TEXMFCACHE")
+ if texmfcaches then
+ for k=1,#texmfcaches do
+ local cachepath=texmfcaches[k]
+ if cachepath~="" then
+ cachepath=resolvers.resolve(cachepath)
+ cachepath=resolvers.cleanpath(cachepath)
+ cachepath=file.collapsepath(cachepath)
+ local valid=isdir(cachepath)
+ if valid then
+ if is_readable(cachepath) then
+ readables[#readables+1]=cachepath
+ if not writable and is_writable(cachepath) then
+ writable=cachepath
+ end
+ end
+ elseif not writable and caches.force then
+ local cacheparent=file.dirname(cachepath)
+ if is_writable(cacheparent) and true then
+ if not caches.ask or io.ask(format("\nShould I create the cache path %s?",cachepath),"no",{ "yes","no" })=="yes" then
+ mkdirs(cachepath)
+ if isdir(cachepath) and is_writable(cachepath) then
+ report_caches("path %a created",cachepath)
+ writable=cachepath
+ readables[#readables+1]=cachepath
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ local texmfcaches=caches.defaults
+ if texmfcaches then
+ for k=1,#texmfcaches do
+ local cachepath=texmfcaches[k]
+ cachepath=resolvers.expansion(cachepath)
+ if cachepath~="" then
+ cachepath=resolvers.resolve(cachepath)
+ cachepath=resolvers.cleanpath(cachepath)
+ local valid=isdir(cachepath)
+ if valid and is_readable(cachepath) then
+ if not writable and is_writable(cachepath) then
+ readables[#readables+1]=cachepath
+ writable=cachepath
+ break
+ end
end
+ end
+ end
+ end
+ if not writable then
+ report_caches("fatal error: there is no valid writable cache path defined")
+ os.exit()
+ elseif #readables==0 then
+ report_caches("fatal error: there is no valid readable cache path defined")
+ os.exit()
+ end
+ writable=dir.expandname(resolvers.cleanpath(writable))
+ local base,more,tree=caches.base,caches.more,caches.tree or caches.treehash()
+ if tree then
+ caches.tree=tree
+ writable=mkdirs(writable,base,more,tree)
+ for i=1,#readables do
+ readables[i]=file.join(readables[i],base,more,tree)
+ end
+ else
+ writable=mkdirs(writable,base,more)
+ for i=1,#readables do
+ readables[i]=file.join(readables[i],base,more)
end
- return all
+ end
+ if trace_cache then
+ for i=1,#readables do
+ report_caches("using readable path %a (order %s)",readables[i],i)
+ end
+ report_caches("using writable path %a",writable)
+ end
+ identify=function()
+ return writable,readables
+ end
+ return writable,readables
end
-
-local function _resolve_(method,target)
- local action = prefixes[method]
- if action then
- return action(target)
- else
- return method .. ":" .. target
+function caches.usedpaths()
+ local writable,readables=identify()
+ if #readables>1 then
+ local result={}
+ for i=1,#readables do
+ local readable=readables[i]
+ if usedreadables[i] or readable==writable then
+ result[#result+1]=formatters["readable: %a (order %s)"](readable,i)
+ end
end
+ result[#result+1]=formatters["writable: %a"](writable)
+ return result
+ else
+ return writable
+ end
end
-
-local resolved, abstract = { }, { }
-
-function resolvers.resetresolve(str)
- resolved, abstract = { }, { }
+function caches.configfiles()
+ return concat(resolvers.instance.specification,";")
end
-
-local function resolve(str) -- use schemes, this one is then for the commandline only
- if type(str) == "table" then
- local t = { }
- for i=1,#str do
- t[i] = resolve(str[i])
- end
- return t
+function caches.hashed(tree)
+ tree=gsub(tree,"[\\/]+$","")
+ tree=lower(tree)
+ local hash=md5.hex(tree)
+ if trace_cache or trace_locating then
+ report_caches("hashing tree %a, hash %a",tree,hash)
+ end
+ return hash
+end
+function caches.treehash()
+ local tree=caches.configfiles()
+ if not tree or tree=="" then
+ return false
+ else
+ return caches.hashed(tree)
+ end
+end
+local r_cache,w_cache={},{}
+local function getreadablepaths(...)
+ local tags={... }
+ local hash=concat(tags,"/")
+ local done=r_cache[hash]
+ if not done then
+ local writable,readables=identify()
+ if #tags>0 then
+ done={}
+ for i=1,#readables do
+ done[i]=file.join(readables[i],...)
+ end
else
- local res = resolved[str]
- if not res then
- res = gsub(str,"([a-z][a-z]+):([^ \"\';,]*)",_resolve_) -- home:xx;selfautoparent:xx; etc (comma added)
- resolved[str] = res
- abstract[res] = str
- end
- return res
+ done=readables
end
+ r_cache[hash]=done
+ end
+ return done
end
-
-local function unresolve(str)
- return abstract[str] or str
+local function getwritablepath(...)
+ local tags={... }
+ local hash=concat(tags,"/")
+ local done=w_cache[hash]
+ if not done then
+ local writable,readables=identify()
+ if #tags>0 then
+ done=mkdirs(writable,...)
+ else
+ done=writable
+ end
+ w_cache[hash]=done
+ end
+ return done
end
-
-resolvers.resolve = resolve
-resolvers.unresolve = unresolve
-
-if os.uname then
-
- for k, v in next, os.uname() do
- if not prefixes[k] then
- prefixes[k] = function() return v end
- end
+caches.getreadablepaths=getreadablepaths
+caches.getwritablepath=getwritablepath
+function caches.getfirstreadablefile(filename,...)
+ local rd=getreadablepaths(...)
+ for i=1,#rd do
+ local path=rd[i]
+ local fullname=file.join(path,filename)
+ if is_readable(fullname) then
+ usedreadables[i]=true
+ return fullname,path
end
-
+ end
+ return caches.setfirstwritablefile(filename,...)
end
-
-if os.type == "unix" then
-
- local pattern
-
- local function makepattern(t,k,v)
- local colon = P(":")
- local p
- for k, v in table.sortedpairs(prefixes) do
- if p then
- p = P(k) + p
- else
- p = P(k)
- end
- end
- pattern = Cs((p * colon + colon/";" + P(1))^0)
- if t then
- t[k] = v
+function caches.setfirstwritablefile(filename,...)
+ local wr=getwritablepath(...)
+ local fullname=file.join(wr,filename)
+ return fullname,wr
+end
+function caches.define(category,subcategory)
+ return function()
+ return getwritablepath(category,subcategory)
+ end
+end
+function caches.setluanames(path,name)
+ return format("%s/%s.%s",path,name,luasuffixes.tma),format("%s/%s.%s",path,name,luasuffixes.tmc)
+end
+function caches.loaddata(readables,name)
+ if type(readables)=="string" then
+ readables={ readables }
+ end
+ for i=1,#readables do
+ local path=readables[i]
+ local tmaname,tmcname=caches.setluanames(path,name)
+ local loader=false
+ if isfile(tmcname) then
+ loader=loadfile(tmcname)
+ end
+ if not loader and isfile(tmaname) then
+ utilities.lua.compile(tmaname,tmcname)
+ if isfile(tmcname) then
+ loader=loadfile(tmcname)
+ end
+ if not loader then
+ loader=loadfile(tmaname)
+ end
+ end
+ if loader then
+ loader=loader()
+ collectgarbage("step")
+ return loader
+ end
+ end
+ return false
+end
+function caches.is_writable(filepath,filename)
+ local tmaname,tmcname=caches.setluanames(filepath,filename)
+ return is_writable(tmaname)
+end
+local saveoptions={ compact=true }
+function caches.savedata(filepath,filename,data,raw)
+ local tmaname,tmcname=caches.setluanames(filepath,filename)
+ local reduce,simplify=true,true
+ if raw then
+ reduce,simplify=false,false
+ end
+ data.cache_uuid=os.uuid()
+ if caches.direct then
+ file.savedata(tmaname,serialize(data,true,saveoptions))
+ else
+ serializetofile(tmaname,data,true,saveoptions)
+ end
+ utilities.lua.compile(tmaname,tmcname)
+end
+local content_state={}
+function caches.contentstate()
+ return content_state or {}
+end
+function caches.loadcontent(cachename,dataname)
+ local name=caches.hashed(cachename)
+ local full,path=caches.getfirstreadablefile(addsuffix(name,luasuffixes.lua),"trees")
+ local filename=file.join(path,name)
+ local blob=loadfile(addsuffix(filename,luasuffixes.luc)) or loadfile(addsuffix(filename,luasuffixes.lua))
+ if blob then
+ local data=blob()
+ if data and data.content then
+ if data.type==dataname then
+ if data.version==resolvers.cacheversion then
+ content_state[#content_state+1]=data.uuid
+ if trace_locating then
+ report_resolvers("loading %a for %a from %a",dataname,cachename,filename)
+ end
+ return data.content
+ else
+ report_resolvers("skipping %a for %a from %a (version mismatch)",dataname,cachename,filename)
end
+ else
+ report_resolvers("skipping %a for %a from %a (datatype mismatch)",dataname,cachename,filename)
+ end
+ elseif trace_locating then
+ report_resolvers("skipping %a for %a from %a (no content)",dataname,cachename,filename)
end
-
- makepattern()
-
- getmetatable(prefixes).__newindex = makepattern
-
- function resolvers.repath(str)
- return lpegmatch(pattern,str)
+ elseif trace_locating then
+ report_resolvers("skipping %a for %a from %a (invalid file)",dataname,cachename,filename)
+ end
+end
+function caches.collapsecontent(content)
+ for k,v in next,content do
+ if type(v)=="table" and #v==1 then
+ content[k]=v[1]
end
-
-else -- already the default:
-
- function resolvers.repath(str)
- return str
+ end
+end
+function caches.savecontent(cachename,dataname,content)
+ local name=caches.hashed(cachename)
+ local full,path=caches.setfirstwritablefile(addsuffix(name,luasuffixes.lua),"trees")
+ local filename=file.join(path,name)
+ local luaname=addsuffix(filename,luasuffixes.lua)
+ local lucname=addsuffix(filename,luasuffixes.luc)
+ if trace_locating then
+ report_resolvers("preparing %a for %a",dataname,cachename)
+ end
+ local data={
+ type=dataname,
+ root=cachename,
+ version=resolvers.cacheversion,
+ date=os.date("%Y-%m-%d"),
+ time=os.date("%H:%M:%S"),
+ content=content,
+ uuid=os.uuid(),
+ }
+ local ok=io.savedata(luaname,serialize(data,true))
+ if ok then
+ if trace_locating then
+ report_resolvers("category %a, cachename %a saved in %a",dataname,cachename,luaname)
end
-
+ if utilities.lua.compile(luaname,lucname) then
+ if trace_locating then
+ report_resolvers("%a compiled to %a",dataname,lucname)
+ end
+ return true
+ else
+ if trace_locating then
+ report_resolvers("compiling failed for %a, deleting file %a",dataname,lucname)
+ end
+ os.remove(lucname)
+ end
+ elseif trace_locating then
+ report_resolvers("unable to save %a in %a (access error)",dataname,luaname)
+ end
end
@@ -14237,1074 +12513,2555 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['data-inp'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local allocate = utilities.storage.allocate
-local resolvers = resolvers
-
-local methodhandler = resolvers.methodhandler
-local registermethod = resolvers.registermethod
-
-local finders = allocate { helpers = { }, notfound = function() end }
-local openers = allocate { helpers = { }, notfound = function() end }
-local loaders = allocate { helpers = { }, notfound = function() return false, nil, 0 end }
-
-registermethod("finders", finders, "uri")
-registermethod("openers", openers, "uri")
-registermethod("loaders", loaders, "uri")
-
-resolvers.finders = finders
-resolvers.openers = openers
-resolvers.loaders = loaders
+package.loaded["data-met"] = package.loaded["data-met"] or true
+-- original size: 4915, stripped down to: 3942
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['data-out'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
+if not modules then modules={} end modules ['data-met']={
+ version=1.100,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
}
-
-local allocate = utilities.storage.allocate
-local resolvers = resolvers
-
-local registermethod = resolvers.registermethod
-
-local savers = allocate { helpers = { } }
-
-resolvers.savers = savers
-
-registermethod("savers", savers, "uri")
+local find,format=string.find,string.format
+local sequenced=table.sequenced
+local addurlscheme,urlhashed=url.addscheme,url.hashed
+local trace_locating=false
+trackers.register("resolvers.locating",function(v) trace_methods=v end)
+trackers.register("resolvers.methods",function(v) trace_methods=v end)
+local report_methods=logs.reporter("resolvers","methods")
+local allocate=utilities.storage.allocate
+local resolvers=resolvers
+local registered={}
+local function splitmethod(filename)
+ if not filename then
+ return { scheme="unknown",original=filename }
+ end
+ if type(filename)=="table" then
+ return filename
+ end
+ filename=file.collapsepath(filename)
+ if not find(filename,"://") then
+ return { scheme="file",path=filename,original=filename,filename=filename }
+ end
+ local specification=url.hashed(filename)
+ if not specification.scheme or specification.scheme=="" then
+ return { scheme="file",path=filename,original=filename,filename=filename }
+ else
+ return specification
+ end
+end
+resolvers.splitmethod=splitmethod
+local function methodhandler(what,first,...)
+ local method=registered[what]
+ if method then
+ local how,namespace=method.how,method.namespace
+ if how=="uri" or how=="url" then
+ local specification=splitmethod(first)
+ local scheme=specification.scheme
+ local resolver=namespace and namespace[scheme]
+ if resolver then
+ if trace_methods then
+ report_methods("resolving, method %a, how %a, handler %a, argument %a",what,how,scheme,first)
+ end
+ return resolver(specification,...)
+ else
+ resolver=namespace.default or namespace.file
+ if resolver then
+ if trace_methods then
+ report_methods("resolving, method %a, how %a, handler %a, argument %a",what,how,"default",first)
+ end
+ return resolver(specification,...)
+ elseif trace_methods then
+ report_methods("resolving, method %a, how %a, handler %a, argument %a",what,how,"unset")
+ end
+ end
+ elseif how=="tag" then
+ local resolver=namespace and namespace[first]
+ if resolver then
+ if trace_methods then
+ report_methods("resolving, method %a, how %a, tag %a",what,how,first)
+ end
+ return resolver(...)
+ else
+ resolver=namespace.default or namespace.file
+ if resolver then
+ if trace_methods then
+ report_methods("resolving, method %a, how %a, tag %a",what,how,"default")
+ end
+ return resolver(...)
+ elseif trace_methods then
+ report_methods("resolving, method %a, how %a, tag %a",what,how,"unset")
+ end
+ end
+ end
+ else
+ report_methods("resolving, invalid method %a")
+ end
+end
+resolvers.methodhandler=methodhandler
+function resolvers.registermethod(name,namespace,how)
+ registered[name]={ how=how or "tag",namespace=namespace }
+ namespace["byscheme"]=function(scheme,filename,...)
+ if scheme=="file" then
+ return methodhandler(name,filename,...)
+ else
+ return methodhandler(name,addurlscheme(filename,scheme),...)
+ end
+ end
+end
+local concatinators=allocate { notfound=file.join }
+local locators=allocate { notfound=function() end }
+local hashers=allocate { notfound=function() end }
+local generators=allocate { notfound=function() end }
+resolvers.concatinators=concatinators
+resolvers.locators=locators
+resolvers.hashers=hashers
+resolvers.generators=generators
+local registermethod=resolvers.registermethod
+registermethod("concatinators",concatinators,"tag")
+registermethod("locators",locators,"uri")
+registermethod("hashers",hashers,"uri")
+registermethod("generators",generators,"uri")
end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['data-fil'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
-
-local report_files = logs.reporter("resolvers","files")
-
-local resolvers = resolvers
+package.loaded["data-res"] = package.loaded["data-res"] or true
-local finders, openers, loaders, savers = resolvers.finders, resolvers.openers, resolvers.loaders, resolvers.savers
-local locators, hashers, generators, concatinators = resolvers.locators, resolvers.hashers, resolvers.generators, resolvers.concatinators
+-- original size: 60821, stripped down to: 42503
-local checkgarbage = utilities.garbagecollector and utilities.garbagecollector.check
-
-function locators.file(specification)
- local name = specification.filename
- local realname = resolvers.resolve(name) -- no shortcut
- if realname and realname ~= '' and lfs.isdir(realname) then
+if not modules then modules={} end modules ['data-res']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files",
+}
+local gsub,find,lower,upper,match,gmatch=string.gsub,string.find,string.lower,string.upper,string.match,string.gmatch
+local concat,insert,sortedkeys=table.concat,table.insert,table.sortedkeys
+local next,type,rawget=next,type,rawget
+local os=os
+local P,S,R,C,Cc,Cs,Ct,Carg=lpeg.P,lpeg.S,lpeg.R,lpeg.C,lpeg.Cc,lpeg.Cs,lpeg.Ct,lpeg.Carg
+local lpegmatch,lpegpatterns=lpeg.match,lpeg.patterns
+local formatters=string.formatters
+local filedirname=file.dirname
+local filebasename=file.basename
+local suffixonly=file.suffixonly
+local filejoin=file.join
+local collapsepath=file.collapsepath
+local joinpath=file.joinpath
+local allocate=utilities.storage.allocate
+local settings_to_array=utilities.parsers.settings_to_array
+local setmetatableindex=table.setmetatableindex
+local luasuffixes=utilities.lua.suffixes
+local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end)
+local trace_detail=false trackers.register("resolvers.details",function(v) trace_detail=v end)
+local trace_expansions=false trackers.register("resolvers.expansions",function(v) trace_expansions=v end)
+local report_resolving=logs.reporter("resolvers","resolving")
+local resolvers=resolvers
+local expandedpathfromlist=resolvers.expandedpathfromlist
+local checkedvariable=resolvers.checkedvariable
+local splitconfigurationpath=resolvers.splitconfigurationpath
+local methodhandler=resolvers.methodhandler
+local initializesetter=utilities.setters.initialize
+local ostype,osname,osenv,ossetenv,osgetenv=os.type,os.name,os.env,os.setenv,os.getenv
+resolvers.cacheversion='1.0.1'
+resolvers.configbanner=''
+resolvers.homedir=environment.homedir
+resolvers.criticalvars=allocate { "SELFAUTOLOC","SELFAUTODIR","SELFAUTOPARENT","TEXMFCNF","TEXMF","TEXOS" }
+resolvers.luacnfname="texmfcnf.lua"
+resolvers.luacnfstate="unknown"
+if environment.default_texmfcnf then
+ resolvers.luacnfspec=environment.default_texmfcnf
+else
+ resolvers.luacnfspec="{selfautoloc:,selfautodir:,selfautoparent:}{,/texmf{-local,}/web2c}"
+end
+resolvers.luacnfspec='home:texmf/web2c;'..resolvers.luacnfspec
+local unset_variable="unset"
+local formats=resolvers.formats
+local suffixes=resolvers.suffixes
+local dangerous=resolvers.dangerous
+local suffixmap=resolvers.suffixmap
+resolvers.defaultsuffixes={ "tex" }
+resolvers.instance=resolvers.instance or nil
+local instance=resolvers.instance or nil
+function resolvers.setenv(key,value,raw)
+ if instance then
+ instance.environment[key]=value
+ ossetenv(key,raw and value or resolvers.resolve(value))
+ end
+end
+local function getenv(key)
+ local value=rawget(instance.environment,key)
+ if value and value~="" then
+ return value
+ else
+ local e=osgetenv(key)
+ return e~=nil and e~="" and checkedvariable(e) or ""
+ end
+end
+resolvers.getenv=getenv
+resolvers.env=getenv
+local function resolve(k)
+ return instance.expansions[k]
+end
+local dollarstripper=lpeg.stripper("$")
+local inhibitstripper=P("!")^0*Cs(P(1)^0)
+local backslashswapper=lpeg.replacer("\\","/")
+local somevariable=P("$")/""
+local somekey=C(R("az","AZ","09","__","--")^1)
+local somethingelse=P(";")*((1-S("!{}/\\"))^1*P(";")/"")+P(";")*(P(";")/"")+P(1)
+local variableexpander=Cs((somevariable*(somekey/resolve)+somethingelse)^1 )
+local cleaner=P("\\")/"/"+P(";")*S("!{}/\\")^0*P(";")^1/";"
+local variablecleaner=Cs((cleaner+P(1))^0)
+local somevariable=R("az","AZ","09","__","--")^1/resolve
+local variable=(P("$")/"")*(somevariable+(P("{")/"")*somevariable*(P("}")/""))
+local variableresolver=Cs((variable+P(1))^0)
+local function expandedvariable(var)
+ return lpegmatch(variableexpander,var) or var
+end
+function resolvers.newinstance()
+ if trace_locating then
+ report_resolving("creating instance")
+ end
+ local environment,variables,expansions,order=allocate(),allocate(),allocate(),allocate()
+ local newinstance={
+ environment=environment,
+ variables=variables,
+ expansions=expansions,
+ order=order,
+ files=allocate(),
+ setups=allocate(),
+ found=allocate(),
+ foundintrees=allocate(),
+ hashes=allocate(),
+ hashed=allocate(),
+ specification=allocate(),
+ lists=allocate(),
+ data=allocate(),
+ fakepaths=allocate(),
+ remember=true,
+ diskcache=true,
+ renewcache=false,
+ renewtree=false,
+ loaderror=false,
+ savelists=true,
+ pattern=nil,
+ force_suffixes=true,
+ }
+ setmetatableindex(variables,function(t,k)
+ local v
+ for i=1,#order do
+ v=order[i][k]
+ if v~=nil then
+ t[k]=v
+ return v
+ end
+ end
+ if v==nil then
+ v=""
+ end
+ t[k]=v
+ return v
+ end)
+ setmetatableindex(environment,function(t,k)
+ local v=osgetenv(k)
+ if v==nil then
+ v=variables[k]
+ end
+ if v~=nil then
+ v=checkedvariable(v) or ""
+ end
+ v=resolvers.repath(v)
+ t[k]=v
+ return v
+ end)
+ setmetatableindex(expansions,function(t,k)
+ local v=environment[k]
+ if type(v)=="string" then
+ v=lpegmatch(variableresolver,v)
+ v=lpegmatch(variablecleaner,v)
+ end
+ t[k]=v
+ return v
+ end)
+ return newinstance
+end
+function resolvers.setinstance(someinstance)
+ instance=someinstance
+ resolvers.instance=someinstance
+ return someinstance
+end
+function resolvers.reset()
+ return resolvers.setinstance(resolvers.newinstance())
+end
+local function reset_hashes()
+ instance.lists={}
+ instance.found={}
+end
+local slash=P("/")
+local pathexpressionpattern=Cs (
+ Cc("^")*(
+ Cc("%")*S(".-")+slash^2*P(-1)/"/.*"
++slash^2/"/[^/]*/*"+(1-slash)*P(-1)*Cc("/")+P(1)
+ )^1*Cc("$")
+)
+local cache={}
+local function makepathexpression(str)
+ if str=="." then
+ return "^%./$"
+ else
+ local c=cache[str]
+ if not c then
+ c=lpegmatch(pathexpressionpattern,str)
+ cache[str]=c
+ end
+ return c
+ end
+end
+local function reportcriticalvariables(cnfspec)
+ if trace_locating then
+ for i=1,#resolvers.criticalvars do
+ local k=resolvers.criticalvars[i]
+ local v=resolvers.getenv(k) or "unknown"
+ report_resolving("variable %a set to %a",k,v)
+ end
+ report_resolving()
+ if cnfspec then
+ report_resolving("using configuration specification %a",type(cnfspec)=="table" and concat(cnfspec,",") or cnfspec)
+ end
+ report_resolving()
+ end
+ reportcriticalvariables=function() end
+end
+local function identify_configuration_files()
+ local specification=instance.specification
+ if #specification==0 then
+ local cnfspec=getenv("TEXMFCNF")
+ if cnfspec=="" then
+ cnfspec=resolvers.luacnfspec
+ resolvers.luacnfstate="default"
+ else
+ resolvers.luacnfstate="environment"
+ end
+ reportcriticalvariables(cnfspec)
+ local cnfpaths=expandedpathfromlist(resolvers.splitpath(cnfspec))
+ local luacnfname=resolvers.luacnfname
+ for i=1,#cnfpaths do
+ local filename=collapsepath(filejoin(cnfpaths[i],luacnfname))
+ local realname=resolvers.resolve(filename)
+ if lfs.isfile(realname) then
+ specification[#specification+1]=filename
+ if trace_locating then
+ report_resolving("found configuration file %a",realname)
+ end
+ elseif trace_locating then
+ report_resolving("unknown configuration file %a",realname)
+ end
+ end
+ if trace_locating then
+ report_resolving()
+ end
+ elseif trace_locating then
+ report_resolving("configuration files already identified")
+ end
+end
+local function load_configuration_files()
+ local specification=instance.specification
+ if #specification>0 then
+ local luacnfname=resolvers.luacnfname
+ for i=1,#specification do
+ local filename=specification[i]
+ local pathname=filedirname(filename)
+ local filename=filejoin(pathname,luacnfname)
+ local realname=resolvers.resolve(filename)
+ local blob=loadfile(realname)
+ if blob then
+ local setups=instance.setups
+ local data=blob()
+ local parent=data and data.parent
+ if parent then
+ local filename=filejoin(pathname,parent)
+ local realname=resolvers.resolve(filename)
+ local blob=loadfile(realname)
+ if blob then
+ local parentdata=blob()
+ if parentdata then
+ report_resolving("loading configuration file %a",filename)
+ data=table.merged(parentdata,data)
+ end
+ end
+ end
+ data=data and data.content
+ if data then
+ if trace_locating then
+ report_resolving("loading configuration file %a",filename)
+ report_resolving()
+ end
+ local variables=data.variables or {}
+ local warning=false
+ for k,v in next,data do
+ local variant=type(v)
+ if variant=="table" then
+ initializesetter(filename,k,v)
+ elseif variables[k]==nil then
+ if trace_locating and not warning then
+ report_resolving("variables like %a in configuration file %a should move to the 'variables' subtable",
+ k,resolvers.resolve(filename))
+ warning=true
+ end
+ variables[k]=v
+ end
+ end
+ setups[pathname]=variables
+ if resolvers.luacnfstate=="default" then
+ local cnfspec=variables["TEXMFCNF"]
+ if cnfspec then
+ if trace_locating then
+ report_resolving("reloading configuration due to TEXMF redefinition")
+ end
+ resolvers.setenv("TEXMFCNF",cnfspec)
+ instance.specification={}
+ identify_configuration_files()
+ load_configuration_files()
+ resolvers.luacnfstate="configuration"
+ break
+ end
+ end
+ else
+ if trace_locating then
+ report_resolving("skipping configuration file %a (no content)",filename)
+ end
+ setups[pathname]={}
+ instance.loaderror=true
+ end
+ elseif trace_locating then
+ report_resolving("skipping configuration file %a (no valid format)",filename)
+ end
+ instance.order[#instance.order+1]=instance.setups[pathname]
+ if instance.loaderror then
+ break
+ end
+ end
+ elseif trace_locating then
+ report_resolving("warning: no lua configuration files found")
+ end
+end
+local function load_file_databases()
+ instance.loaderror,instance.files=false,allocate()
+ if not instance.renewcache then
+ local hashes=instance.hashes
+ for k=1,#hashes do
+ local hash=hashes[k]
+ resolvers.hashers.byscheme(hash.type,hash.name)
+ if instance.loaderror then break end
+ end
+ end
+end
+local function locate_file_databases()
+ local texmfpaths=resolvers.expandedpathlist("TEXMF")
+ if #texmfpaths>0 then
+ for i=1,#texmfpaths do
+ local path=collapsepath(texmfpaths[i])
+ path=gsub(path,"/+$","")
+ local stripped=lpegmatch(inhibitstripper,path)
+ if stripped~="" then
+ local runtime=stripped==path
+ path=resolvers.cleanpath(path)
+ local spec=resolvers.splitmethod(stripped)
+ if runtime and (spec.noscheme or spec.scheme=="file") then
+ stripped="tree:///"..stripped
+ elseif spec.scheme=="cache" or spec.scheme=="file" then
+ stripped=spec.path
+ end
if trace_locating then
- report_files("file locator '%s' found as '%s'",name,realname)
+ if runtime then
+ report_resolving("locating list of %a (runtime) (%s)",path,stripped)
+ else
+ report_resolving("locating list of %a (cached)",path)
+ end
end
- resolvers.appendhash('file',name,true) -- cache
+ methodhandler('locators',stripped)
+ end
+ end
+ if trace_locating then
+ report_resolving()
+ end
+ elseif trace_locating then
+ report_resolving("no texmf paths are defined (using TEXMF)")
+ end
+end
+local function generate_file_databases()
+ local hashes=instance.hashes
+ for k=1,#hashes do
+ local hash=hashes[k]
+ methodhandler('generators',hash.name)
+ end
+ if trace_locating then
+ report_resolving()
+ end
+end
+local function save_file_databases()
+ for i=1,#instance.hashes do
+ local hash=instance.hashes[i]
+ local cachename=hash.name
+ if hash.cache then
+ local content=instance.files[cachename]
+ caches.collapsecontent(content)
+ if trace_locating then
+ report_resolving("saving tree %a",cachename)
+ end
+ caches.savecontent(cachename,"files",content)
elseif trace_locating then
- report_files("file locator '%s' not found",name)
+ report_resolving("not saving runtime tree %a",cachename)
end
+ end
end
-
-function hashers.file(specification)
- local name = specification.filename
- local content = caches.loadcontent(name,'files')
- resolvers.registerfilehash(name,content,content==nil)
+function resolvers.renew(hashname)
+ if hashname and hashname~="" then
+ local expanded=resolvers.expansion(hashname) or ""
+ if expanded~="" then
+ if trace_locating then
+ report_resolving("identifying tree %a from %a",expanded,hashname)
+ end
+ hashname=expanded
+ else
+ if trace_locating then
+ report_resolving("identifying tree %a",hashname)
+ end
+ end
+ local realpath=resolvers.resolve(hashname)
+ if lfs.isdir(realpath) then
+ if trace_locating then
+ report_resolving("using path %a",realpath)
+ end
+ methodhandler('generators',hashname)
+ local content=instance.files[hashname]
+ caches.collapsecontent(content)
+ if trace_locating then
+ report_resolving("saving tree %a",hashname)
+ end
+ caches.savecontent(hashname,"files",content)
+ else
+ report_resolving("invalid path %a",realpath)
+ end
+ end
end
-
-function generators.file(specification)
- local path = specification.filename
- local content = resolvers.scanfiles(path,false,true) -- scan once
- resolvers.registerfilehash(path,content,true)
+local function load_databases()
+ locate_file_databases()
+ if instance.diskcache and not instance.renewcache then
+ load_file_databases()
+ if instance.loaderror then
+ generate_file_databases()
+ save_file_databases()
+ end
+ else
+ generate_file_databases()
+ if instance.renewcache then
+ save_file_databases()
+ end
+ end
end
-
-concatinators.file = file.join
-
-function finders.file(specification,filetype)
- local filename = specification.filename
- local foundname = resolvers.findfile(filename,filetype)
- if foundname and foundname ~= "" then
- if trace_locating then
- report_files("file finder: '%s' found",filename)
- end
- return foundname
+function resolvers.appendhash(type,name,cache)
+ if not instance.hashed[name] then
+ if trace_locating then
+ report_resolving("hash %a appended",name)
+ end
+ insert(instance.hashes,{ type=type,name=name,cache=cache } )
+ instance.hashed[name]=cache
+ end
+end
+function resolvers.prependhash(type,name,cache)
+ if not instance.hashed[name] then
+ if trace_locating then
+ report_resolving("hash %a prepended",name)
+ end
+ insert(instance.hashes,1,{ type=type,name=name,cache=cache } )
+ instance.hashed[name]=cache
+ end
+end
+function resolvers.extendtexmfvariable(specification)
+ local t=resolvers.splitpath(getenv("TEXMF"))
+ insert(t,1,specification)
+ local newspec=concat(t,",")
+ if instance.environment["TEXMF"] then
+ instance.environment["TEXMF"]=newspec
+ elseif instance.variables["TEXMF"] then
+ instance.variables["TEXMF"]=newspec
+ else
+ end
+ reset_hashes()
+end
+function resolvers.splitexpansions()
+ local ie=instance.expansions
+ for k,v in next,ie do
+ local t,tn,h,p={},0,{},splitconfigurationpath(v)
+ for kk=1,#p do
+ local vv=p[kk]
+ if vv~="" and not h[vv] then
+ tn=tn+1
+ t[tn]=vv
+ h[vv]=true
+ end
+ end
+ if #t>1 then
+ ie[k]=t
else
- if trace_locating then
- report_files("file finder: %s' not found",filename)
- end
- return finders.notfound()
+ ie[k]=t[1]
end
+ end
end
-
--- The default textopener will be overloaded later on.
-
-function openers.helpers.textopener(tag,filename,f)
- return {
- reader = function() return f:read () end,
- close = function() logs.show_close(filename) return f:close() end,
- }
+function resolvers.datastate()
+ return caches.contentstate()
end
-
-function openers.file(specification,filetype)
- local filename = specification.filename
- if filename and filename ~= "" then
- local f = io.open(filename,"r")
- if f then
- if trace_locating then
- report_files("file opener, '%s' opened",filename)
- end
- return openers.helpers.textopener("file",filename,f)
+function resolvers.variable(name)
+ local name=name and lpegmatch(dollarstripper,name)
+ local result=name and instance.variables[name]
+ return result~=nil and result or ""
+end
+function resolvers.expansion(name)
+ local name=name and lpegmatch(dollarstripper,name)
+ local result=name and instance.expansions[name]
+ return result~=nil and result or ""
+end
+function resolvers.unexpandedpathlist(str)
+ local pth=resolvers.variable(str)
+ local lst=resolvers.splitpath(pth)
+ return expandedpathfromlist(lst)
+end
+function resolvers.unexpandedpath(str)
+ return joinpath(resolvers.unexpandedpathlist(str))
+end
+local done={}
+function resolvers.resetextrapath()
+ local ep=instance.extra_paths
+ if not ep then
+ ep,done={},{}
+ instance.extra_paths=ep
+ elseif #ep>0 then
+ instance.lists,done={},{}
+ end
+end
+function resolvers.registerextrapath(paths,subpaths)
+ paths=settings_to_array(paths)
+ subpaths=settings_to_array(subpaths)
+ local ep=instance.extra_paths or {}
+ local oldn=#ep
+ local newn=oldn
+ local nofpaths=#paths
+ local nofsubpaths=#subpaths
+ if nofpaths>0 then
+ if nofsubpaths>0 then
+ for i=1,nofpaths do
+ local p=paths[i]
+ for j=1,nofsubpaths do
+ local s=subpaths[j]
+ local ps=p.."/"..s
+ if not done[ps] then
+ newn=newn+1
+ ep[newn]=resolvers.cleanpath(ps)
+ done[ps]=true
+ end
+ end
+ end
+ else
+ for i=1,nofpaths do
+ local p=paths[i]
+ if not done[p] then
+ newn=newn+1
+ ep[newn]=resolvers.cleanpath(p)
+ done[p]=true
+ end
+ end
+ end
+ elseif nofsubpaths>0 then
+ for i=1,oldn do
+ for j=1,nofsubpaths do
+ local s=subpaths[j]
+ local ps=ep[i].."/"..s
+ if not done[ps] then
+ newn=newn+1
+ ep[newn]=resolvers.cleanpath(ps)
+ done[ps]=true
+ end
+ end
+ end
+ end
+ if newn>0 then
+ instance.extra_paths=ep
+ end
+ if newn>oldn then
+ instance.lists={}
+ end
+end
+local function made_list(instance,list)
+ local ep=instance.extra_paths
+ if not ep or #ep==0 then
+ return list
+ else
+ local done,new,newn={},{},0
+ for k=1,#list do
+ local v=list[k]
+ if not done[v] then
+ if find(v,"^[%.%/]$") then
+ done[v]=true
+ newn=newn+1
+ new[newn]=v
+ else
+ break
end
+ end
end
- if trace_locating then
- report_files("file opener, '%s' not found",filename)
+ for k=1,#ep do
+ local v=ep[k]
+ if not done[v] then
+ done[v]=true
+ newn=newn+1
+ new[newn]=v
+ end
+ end
+ for k=1,#list do
+ local v=list[k]
+ if not done[v] then
+ done[v]=true
+ newn=newn+1
+ new[newn]=v
+ end
end
- return openers.notfound()
+ return new
+ end
end
-
-function loaders.file(specification,filetype)
- local filename = specification.filename
- if filename and filename ~= "" then
- local f = io.open(filename,"rb")
- if f then
- logs.show_load(filename)
- if trace_locating then
- report_files("file loader, '%s' loaded",filename)
- end
- local s = f:read("*a")
- if checkgarbage then
- checkgarbage(#s)
- end
- f:close()
- if s then
- return true, s, #s
- end
- end
+function resolvers.cleanpathlist(str)
+ local t=resolvers.expandedpathlist(str)
+ if t then
+ for i=1,#t do
+ t[i]=collapsepath(resolvers.cleanpath(t[i]))
end
- if trace_locating then
- report_files("file loader, '%s' not found",filename)
+ end
+ return t
+end
+function resolvers.expandpath(str)
+ return joinpath(resolvers.expandedpathlist(str))
+end
+function resolvers.expandedpathlist(str)
+ if not str then
+ return {}
+ elseif instance.savelists then
+ str=lpegmatch(dollarstripper,str)
+ local lists=instance.lists
+ local lst=lists[str]
+ if not lst then
+ local l=made_list(instance,resolvers.splitpath(resolvers.expansion(str)))
+ lst=expandedpathfromlist(l)
+ lists[str]=lst
end
- return loaders.notfound()
+ return lst
+ else
+ local lst=resolvers.splitpath(resolvers.expansion(str))
+ return made_list(instance,expandedpathfromlist(lst))
+ end
end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['data-con'] = {
- version = 1.100,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local format, lower, gsub = string.format, string.lower, string.gsub
-
-local trace_cache = false trackers.register("resolvers.cache", function(v) trace_cache = v end)
-local trace_containers = false trackers.register("resolvers.containers", function(v) trace_containers = v end)
-local trace_storage = false trackers.register("resolvers.storage", function(v) trace_storage = v end)
-
---[[ldx--
-Once we found ourselves defining similar cache constructs
-several times, containers were introduced. Containers are used
-to collect tables in memory and reuse them when possible based
-on (unique) hashes (to be provided by the calling function).
-
-Caching to disk is disabled by default. Version numbers are
-stored in the saved table which makes it possible to change the
-table structures without bothering about the disk cache.
-
-Examples of usage can be found in the font related code.
---ldx]]--
-
-containers = containers or { }
-local containers = containers
-containers.usecache = true
-
-local report_containers = logs.reporter("resolvers","containers")
-
-local function report(container,tag,name)
- if trace_cache or trace_containers then
- report_containers("container: %s, tag: %s, name: %s",container.subcategory,tag,name or 'invalid')
+function resolvers.expandedpathlistfromvariable(str)
+ str=lpegmatch(dollarstripper,str)
+ local tmp=resolvers.variableofformatorsuffix(str)
+ return resolvers.expandedpathlist(tmp~="" and tmp or str)
+end
+function resolvers.expandpathfromvariable(str)
+ return joinpath(resolvers.expandedpathlistfromvariable(str))
+end
+function resolvers.expandbraces(str)
+ local ori=str
+ local pth=expandedpathfromlist(resolvers.splitpath(ori))
+ return joinpath(pth)
+end
+function resolvers.registerfilehash(name,content,someerror)
+ if content then
+ instance.files[name]=content
+ else
+ instance.files[name]={}
+ if somerror==true then
+ instance.loaderror=someerror
end
+ end
end
-
-local allocated = { }
-
-local mt = {
- __index = function(t,k)
- if k == "writable" then
- local writable = caches.getwritablepath(t.category,t.subcategory) or { "." }
- t.writable = writable
- return writable
- elseif k == "readables" then
- local readables = caches.getreadablepaths(t.category,t.subcategory) or { "." }
- t.readables = readables
- return readables
- end
- end,
- __storage__ = true
-}
-
-function containers.define(category, subcategory, version, enabled)
- if category and subcategory then
- local c = allocated[category]
- if not c then
- c = { }
- allocated[category] = c
- end
- local s = c[subcategory]
- if not s then
- s = {
- category = category,
- subcategory = subcategory,
- storage = { },
- enabled = enabled,
- version = version or math.pi, -- after all, this is TeX
- trace = false,
- -- writable = caches.getwritablepath and caches.getwritablepath (category,subcategory) or { "." },
- -- readables = caches.getreadablepaths and caches.getreadablepaths(category,subcategory) or { "." },
- }
- setmetatable(s,mt)
- c[subcategory] = s
+local function isreadable(name)
+ local readable=lfs.isfile(name)
+ if trace_detail then
+ if readable then
+ report_resolving("file %a is readable",name)
+ else
+ report_resolving("file %a is not readable",name)
+ end
+ end
+ return readable
+end
+local function collect_files(names)
+ local filelist,noffiles={},0
+ for k=1,#names do
+ local fname=names[k]
+ if trace_detail then
+ report_resolving("checking name %a",fname)
+ end
+ local bname=filebasename(fname)
+ local dname=filedirname(fname)
+ if dname=="" or find(dname,"^%.") then
+ dname=false
+ else
+ dname=gsub(dname,"%*",".*")
+ dname="/"..dname.."$"
+ end
+ local hashes=instance.hashes
+ for h=1,#hashes do
+ local hash=hashes[h]
+ local blobpath=hash.name
+ local files=blobpath and instance.files[blobpath]
+ if files then
+ if trace_detail then
+ report_resolving("deep checking %a, base %a, pattern %a",blobpath,bname,dname)
+ end
+ local blobfile=files[bname]
+ if not blobfile then
+ local rname="remap:"..bname
+ blobfile=files[rname]
+ if blobfile then
+ bname=files[rname]
+ blobfile=files[bname]
+ end
+ end
+ if blobfile then
+ local blobroot=files.__path__ or blobpath
+ if type(blobfile)=='string' then
+ if not dname or find(blobfile,dname) then
+ local variant=hash.type
+ local search=filejoin(blobroot,blobfile,bname)
+ local result=methodhandler('concatinators',hash.type,blobroot,blobfile,bname)
+ if trace_detail then
+ report_resolving("match: variant %a, search %a, result %a",variant,search,result)
+ end
+ noffiles=noffiles+1
+ filelist[noffiles]={ variant,search,result }
+ end
+ else
+ for kk=1,#blobfile do
+ local vv=blobfile[kk]
+ if not dname or find(vv,dname) then
+ local variant=hash.type
+ local search=filejoin(blobroot,vv,bname)
+ local result=methodhandler('concatinators',hash.type,blobroot,vv,bname)
+ if trace_detail then
+ report_resolving("match: variant %a, search %a, result %a",variant,search,result)
+ end
+ noffiles=noffiles+1
+ filelist[noffiles]={ variant,search,result }
+ end
+ end
+ end
end
- return s
+ elseif trace_locating then
+ report_resolving("no match in %a (%s)",blobpath,bname)
+ end
end
+ end
+ return noffiles>0 and filelist or nil
end
-
-function containers.is_usable(container, name)
- return container.enabled and caches and caches.is_writable(container.writable, name)
+local fit={}
+function resolvers.registerintrees(filename,format,filetype,usedmethod,foundname)
+ local foundintrees=instance.foundintrees
+ if usedmethod=="direct" and filename==foundname and fit[foundname] then
+ else
+ local t={
+ filename=filename,
+ format=format~="" and format or nil,
+ filetype=filetype~="" and filetype or nil,
+ usedmethod=usedmethod,
+ foundname=foundname,
+ }
+ fit[foundname]=t
+ foundintrees[#foundintrees+1]=t
+ end
end
-
-function containers.is_valid(container, name)
- if name and name ~= "" then
- local storage = container.storage[name]
- return storage and storage.cache_version == container.version
+local function can_be_dir(name)
+ local fakepaths=instance.fakepaths
+ if not fakepaths[name] then
+ if lfs.isdir(name) then
+ fakepaths[name]=1
else
- return false
+ fakepaths[name]=2
end
+ end
+ return fakepaths[name]==1
end
-
-function containers.read(container,name)
- local storage = container.storage
- local stored = storage[name]
- if not stored and container.enabled and caches and containers.usecache then
- stored = caches.loaddata(container.readables,name)
- if stored and stored.cache_version == container.version then
- report(container,"loaded",name)
- else
- stored = nil
+local preparetreepattern=Cs((P(".")/"%%."+P("-")/"%%-"+P(1))^0*Cc("$"))
+local collect_instance_files
+local function find_analyze(filename,askedformat,allresults)
+ local filetype,wantedfiles,ext='',{},suffixonly(filename)
+ wantedfiles[#wantedfiles+1]=filename
+ if askedformat=="" then
+ if ext=="" or not suffixmap[ext] then
+ local defaultsuffixes=resolvers.defaultsuffixes
+ for i=1,#defaultsuffixes do
+ local forcedname=filename..'.'..defaultsuffixes[i]
+ wantedfiles[#wantedfiles+1]=forcedname
+ filetype=resolvers.formatofsuffix(forcedname)
+ if trace_locating then
+ report_resolving("forcing filetype %a",filetype)
end
- storage[name] = stored
- elseif stored then
- report(container,"reusing",name)
+ end
+ else
+ filetype=resolvers.formatofsuffix(filename)
+ if trace_locating then
+ report_resolving("using suffix based filetype %a",filetype)
+ end
end
- return stored
-end
-
-function containers.write(container, name, data)
- if data then
- data.cache_version = container.version
- if container.enabled and caches then
- local unique, shared = data.unique, data.shared
- data.unique, data.shared = nil, nil
- caches.savedata(container.writable, name, data)
- report(container,"saved",name)
- data.unique, data.shared = unique, shared
+ else
+ if ext=="" or not suffixmap[ext] then
+ local format_suffixes=suffixes[askedformat]
+ if format_suffixes then
+ for i=1,#format_suffixes do
+ wantedfiles[#wantedfiles+1]=filename.."."..format_suffixes[i]
end
- report(container,"stored",name)
- container.storage[name] = data
+ end
end
- return data
+ filetype=askedformat
+ if trace_locating then
+ report_resolving("using given filetype %a",filetype)
+ end
+ end
+ return filetype,wantedfiles
end
-
-function containers.content(container,name)
- return container.storage[name]
+local function find_direct(filename,allresults)
+ if not dangerous[askedformat] and isreadable(filename) then
+ if trace_detail then
+ report_resolving("file %a found directly",filename)
+ end
+ return "direct",{ filename }
+ end
end
-
-function containers.cleanname(name)
- return (gsub(lower(name),"[^%w%d]+","-"))
+local function find_wildcard(filename,allresults)
+ if find(filename,'%*') then
+ if trace_locating then
+ report_resolving("checking wildcard %a",filename)
+ end
+ local method,result=resolvers.findwildcardfiles(filename)
+ if result then
+ return "wildcard",result
+ end
+ end
+end
+local function find_qualified(filename,allresults,askedformat,alsostripped)
+ if not file.is_qualified_path(filename) then
+ return
+ end
+ if trace_locating then
+ report_resolving("checking qualified name %a",filename)
+ end
+ if isreadable(filename) then
+ if trace_detail then
+ report_resolving("qualified file %a found",filename)
+ end
+ return "qualified",{ filename }
+ end
+ if trace_detail then
+ report_resolving("locating qualified file %a",filename)
+ end
+ local forcedname,suffix="",suffixonly(filename)
+ if suffix=="" then
+ local format_suffixes=askedformat=="" and resolvers.defaultsuffixes or suffixes[askedformat]
+ if format_suffixes then
+ for i=1,#format_suffixes do
+ local s=format_suffixes[i]
+ forcedname=filename.."."..s
+ if isreadable(forcedname) then
+ if trace_locating then
+ report_resolving("no suffix, forcing format filetype %a",s)
+ end
+ return "qualified",{ forcedname }
+ end
+ end
+ end
+ end
+ if alsostripped and suffix and suffix~="" then
+ local basename=filebasename(filename)
+ local pattern=lpegmatch(preparetreepattern,filename)
+ local savedformat=askedformat
+ local format=savedformat or ""
+ if format=="" then
+ askedformat=resolvers.formatofsuffix(suffix)
+ end
+ if not format then
+ askedformat="othertextfiles"
+ end
+ if basename~=filename then
+ local resolved=collect_instance_files(basename,askedformat,allresults)
+ if #resolved==0 then
+ local lowered=lower(basename)
+ if filename~=lowered then
+ resolved=collect_instance_files(lowered,askedformat,allresults)
+ end
+ end
+ resolvers.format=savedformat
+ if #resolved>0 then
+ local result={}
+ for r=1,#resolved do
+ local rr=resolved[r]
+ if find(rr,pattern) then
+ result[#result+1]=rr
+ end
+ end
+ if #result>0 then
+ return "qualified",result
+ end
+ end
+ end
+ end
end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['data-use'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local format, lower, gsub, find = string.format, string.lower, string.gsub, string.find
-
-local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
-
-local report_mounts = logs.reporter("resolvers","mounts")
-
-local resolvers = resolvers
-
--- we will make a better format, maybe something xml or just text or lua
-
-resolvers.automounted = resolvers.automounted or { }
-
-function resolvers.automount(usecache)
- local mountpaths = resolvers.cleanpathlist(resolvers.expansion('TEXMFMOUNT'))
- if (not mountpaths or #mountpaths == 0) and usecache then
- mountpaths = caches.getreadablepaths("mount")
- end
- if mountpaths and #mountpaths > 0 then
- statistics.starttiming(resolvers.instance)
- for k=1,#mountpaths do
- local root = mountpaths[k]
- local f = io.open(root.."/url.tmi")
- if f then
- for line in f:lines() do
- if line then
- if find(line,"^[%%#%-]") then -- or %W
- -- skip
- elseif find(line,"^zip://") then
- if trace_locating then
- report_mounts("mounting %s",line)
- end
- table.insert(resolvers.automounted,line)
- resolvers.usezipfile(line)
+local function check_subpath(fname)
+ if isreadable(fname) then
+ if trace_detail then
+ report_resolving("found %a by deep scanning",fname)
+ end
+ return fname
+ end
+end
+local function find_intree(filename,filetype,wantedfiles,allresults)
+ local typespec=resolvers.variableofformat(filetype)
+ local pathlist=resolvers.expandedpathlist(typespec)
+ local method="intree"
+ if pathlist and #pathlist>0 then
+ local filelist=collect_files(wantedfiles)
+ local dirlist={}
+ if filelist then
+ for i=1,#filelist do
+ dirlist[i]=filedirname(filelist[i][3]).."/"
+ end
+ end
+ if trace_detail then
+ report_resolving("checking filename %a",filename)
+ end
+ local resolve=resolvers.resolve
+ local result={}
+ for k=1,#pathlist do
+ local path=pathlist[k]
+ local pathname=lpegmatch(inhibitstripper,path)
+ local doscan=path==pathname
+ if not find (pathname,'//$') then
+ doscan=false
+ end
+ local done=false
+ if filelist then
+ local expression=makepathexpression(pathname)
+ if trace_detail then
+ report_resolving("using pattern %a for path %a",expression,pathname)
+ end
+ for k=1,#filelist do
+ local fl=filelist[k]
+ local f=fl[2]
+ local d=dirlist[k]
+ if find(d,expression) or find(resolve(d),expression) then
+ result[#result+1]=resolve(fl[3])
+ done=true
+ if allresults then
+ if trace_detail then
+ report_resolving("match to %a in hash for file %a and path %a, continue scanning",expression,f,d)
+ end
+ else
+ if trace_detail then
+ report_resolving("match to %a in hash for file %a and path %a, quit scanning",expression,f,d)
+ end
+ break
+ end
+ elseif trace_detail then
+ report_resolving("no match to %a in hash for file %a and path %a",expression,f,d)
+ end
+ end
+ end
+ if done then
+ method="database"
+ else
+ method="filesystem"
+ pathname=gsub(pathname,"/+$","")
+ pathname=resolve(pathname)
+ local scheme=url.hasscheme(pathname)
+ if not scheme or scheme=="file" then
+ local pname=gsub(pathname,"%.%*$",'')
+ if not find(pname,"%*") then
+ if can_be_dir(pname) then
+ for k=1,#wantedfiles do
+ local w=wantedfiles[k]
+ local fname=check_subpath(filejoin(pname,w))
+ if fname then
+ result[#result+1]=fname
+ done=true
+ if not allresults then
+ break
+ end
+ end
+ end
+ if not done and doscan then
+ local files=resolvers.simplescanfiles(pname,false,true)
+ for k=1,#wantedfiles do
+ local w=wantedfiles[k]
+ local subpath=files[w]
+ if not subpath or subpath=="" then
+ elseif type(subpath)=="string" then
+ local fname=check_subpath(filejoin(pname,subpath,w))
+ if fname then
+ result[#result+1]=fname
+ done=true
+ if not allresults then
+ break
+ end
+ end
+ else
+ for i=1,#subpath do
+ local sp=subpath[i]
+ if sp=="" then
+ else
+ local fname=check_subpath(filejoin(pname,sp,w))
+ if fname then
+ result[#result+1]=fname
+ done=true
+ if not allresults then
+ break
+ end
end
+ end
+ end
+ if done and not allresults then
+ break
end
+ end
end
- f:close()
+ end
end
+ else
+ end
end
- statistics.stoptiming(resolvers.instance)
+ end
+ if done and not allresults then
+ break
+ end
end
-end
-
--- status info
-
-statistics.register("used config file", function() return caches.configfiles() end)
-statistics.register("used cache path", function() return caches.usedpaths() end)
-
--- experiment (code will move)
-
-function statistics.savefmtstatus(texname,formatbanner,sourcefile) -- texname == formatname
- local enginebanner = status.list().banner
- if formatbanner and enginebanner and sourcefile then
- local luvname = file.replacesuffix(texname,"luv")
- local luvdata = {
- enginebanner = enginebanner,
- formatbanner = formatbanner,
- sourcehash = md5.hex(io.loaddata(resolvers.findfile(sourcefile)) or "unknown"),
- sourcefile = sourcefile,
- }
- io.savedata(luvname,table.serialize(luvdata,true))
+ if #result>0 then
+ return method,result
end
+ end
end
-
-function statistics.checkfmtstatus(texname)
- local enginebanner = status.list().banner
- if enginebanner and texname then
- local luvname = file.replacesuffix(texname,"luv")
- if lfs.isfile(luvname) then
- local luv = dofile(luvname)
- if luv and luv.sourcefile then
- local sourcehash = md5.hex(io.loaddata(resolvers.findfile(luv.sourcefile)) or "unknown")
- local luvbanner = luv.enginebanner or "?"
- if luvbanner ~= enginebanner then
- return format("engine mismatch (luv: %s <> bin: %s)",luvbanner,enginebanner)
- end
- local luvhash = luv.sourcehash or "?"
- if luvhash ~= sourcehash then
- return format("source mismatch (luv: %s <> bin: %s)",luvhash,sourcehash)
- end
- else
- return "invalid status file"
- end
- else
- return "missing status file"
+local function find_onpath(filename,filetype,wantedfiles,allresults)
+ if trace_detail then
+ report_resolving("checking filename %a, filetype %a, wanted files %a",filename,filetype,concat(wantedfiles," | "))
+ end
+ local result={}
+ for k=1,#wantedfiles do
+ local fname=wantedfiles[k]
+ if fname and isreadable(fname) then
+ filename=fname
+ result[#result+1]=filejoin('.',fname)
+ if not allresults then
+ break
+ end
+ end
+ end
+ if #result>0 then
+ return "onpath",result
+ end
+end
+local function find_otherwise(filename,filetype,wantedfiles,allresults)
+ local filelist=collect_files(wantedfiles)
+ local fl=filelist and filelist[1]
+ if fl then
+ return "otherwise",{ resolvers.resolve(fl[3]) }
+ end
+end
+collect_instance_files=function(filename,askedformat,allresults)
+ askedformat=askedformat or ""
+ filename=collapsepath(filename)
+ if allresults then
+ local filetype,wantedfiles=find_analyze(filename,askedformat)
+ local results={
+ { find_direct (filename,true) },
+ { find_wildcard (filename,true) },
+ { find_qualified(filename,true,askedformat) },
+ { find_intree (filename,filetype,wantedfiles,true) },
+ { find_onpath (filename,filetype,wantedfiles,true) },
+ { find_otherwise(filename,filetype,wantedfiles,true) },
+ }
+ local result,status,done={},{},{}
+ for k,r in next,results do
+ local method,list=r[1],r[2]
+ if method and list then
+ for i=1,#list do
+ local c=collapsepath(list[i])
+ if not done[c] then
+ result[#result+1]=c
+ done[c]=true
+ end
+ status[#status+1]=formatters["%-10s: %s"](method,c)
+ end
+ end
+ end
+ if trace_detail then
+ report_resolving("lookup status: %s",table.serialize(status,filename))
+ end
+ return result,status
+ else
+ local method,result,stamp,filetype,wantedfiles
+ if instance.remember then
+ stamp=formatters["%s--%s"](filename,askedformat)
+ result=stamp and instance.found[stamp]
+ if result then
+ if trace_locating then
+ report_resolving("remembered file %a",filename)
end
+ return result
+ end
end
- return true
-end
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
-if not modules then modules = { } end modules ['data-zip'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- partly redone .. needs testing
-
-local format, find, match = string.format, string.find, string.match
-
-local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
-
-local report_zip = logs.reporter("resolvers","zip")
-
--- zip:///oeps.zip?name=bla/bla.tex
--- zip:///oeps.zip?tree=tex/texmf-local
--- zip:///texmf.zip?tree=/tex/texmf
--- zip:///texmf.zip?tree=/tex/texmf-local
--- zip:///texmf-mine.zip?tree=/tex/texmf-projects
-
-local resolvers = resolvers
-
-zip = zip or { }
-local zip = zip
-
-zip.archives = zip.archives or { }
-local archives = zip.archives
-
-zip.registeredfiles = zip.registeredfiles or { }
-local registeredfiles = zip.registeredfiles
-
-local limited = false
-
-directives.register("system.inputmode", function(v)
- if not limited then
- local i_limiter = io.i_limiter(v)
- if i_limiter then
- zip.open = i_limiter.protect(zip.open)
- limited = true
+ method,result=find_direct(filename)
+ if not result then
+ method,result=find_wildcard(filename)
+ if not result then
+ method,result=find_qualified(filename,false,askedformat)
+ if not result then
+ filetype,wantedfiles=find_analyze(filename,askedformat)
+ method,result=find_intree(filename,filetype,wantedfiles)
+ if not result then
+ method,result=find_onpath(filename,filetype,wantedfiles)
+ if not result then
+ method,result=find_otherwise(filename,filetype,wantedfiles)
+ end
+ end
end
+ end
end
-end)
-
-local function validzip(str) -- todo: use url splitter
- if not find(str,"^zip://") then
- return "zip:///" .. str
+ if result and #result>0 then
+ local foundname=collapsepath(result[1])
+ resolvers.registerintrees(filename,askedformat,filetype,method,foundname)
+ result={ foundname }
else
- return str
+ result={}
end
-end
-
-function zip.openarchive(name)
- if not name or name == "" then
- return nil
- else
- local arch = archives[name]
- if not arch then
- local full = resolvers.findfile(name) or ""
- arch = (full ~= "" and zip.open(full)) or false
- archives[name] = arch
- end
- return arch
+ if stamp then
+ if trace_locating then
+ report_resolving("remembering file %a",filename)
+ end
+ instance.found[stamp]=result
end
+ return result
+ end
end
-
-function zip.closearchive(name)
- if not name or (name == "" and archives[name]) then
- zip.close(archives[name])
- archives[name] = nil
+local function findfiles(filename,filetype,allresults)
+ local result,status=collect_instance_files(filename,filetype or "",allresults)
+ if not result or #result==0 then
+ local lowered=lower(filename)
+ if filename~=lowered then
+ result,status=collect_instance_files(lowered,filetype or "",allresults)
end
+ end
+ return result or {},status
+end
+function resolvers.findfiles(filename,filetype)
+ return findfiles(filename,filetype,true)
+end
+function resolvers.findfile(filename,filetype)
+ return findfiles(filename,filetype,false)[1] or ""
+end
+function resolvers.findpath(filename,filetype)
+ return filedirname(findfiles(filename,filetype,false)[1] or "")
end
-
-function resolvers.locators.zip(specification)
- local archive = specification.filename
- local zipfile = archive and archive ~= "" and zip.openarchive(archive) -- tricky, could be in to be initialized tree
- if trace_locating then
- if zipfile then
- report_zip("locator, archive '%s' found",archive)
- else
- report_zip("locator, archive '%s' not found",archive)
+local function findgivenfiles(filename,allresults)
+ local bname,result=filebasename(filename),{}
+ local hashes=instance.hashes
+ local noffound=0
+ for k=1,#hashes do
+ local hash=hashes[k]
+ local files=instance.files[hash.name] or {}
+ local blist=files[bname]
+ if not blist then
+ local rname="remap:"..bname
+ blist=files[rname]
+ if blist then
+ bname=files[rname]
+ blist=files[bname]
+ end
+ end
+ if blist then
+ if type(blist)=='string' then
+ local found=methodhandler('concatinators',hash.type,hash.name,blist,bname) or ""
+ if found~="" then
+ noffound=noffound+1
+ result[noffound]=resolvers.resolve(found)
+ if not allresults then
+ break
+ end
+ end
+ else
+ for kk=1,#blist do
+ local vv=blist[kk]
+ local found=methodhandler('concatinators',hash.type,hash.name,vv,bname) or ""
+ if found~="" then
+ noffound=noffound+1
+ result[noffound]=resolvers.resolve(found)
+ if not allresults then break end
+ end
end
+ end
end
+ end
+ return result
end
-
-function resolvers.hashers.zip(specification)
- local archive = specification.filename
- if trace_locating then
- report_zip("loading file '%s'",archive)
- end
- resolvers.usezipfile(specification.original)
+function resolvers.findgivenfiles(filename)
+ return findgivenfiles(filename,true)
end
-
-function resolvers.concatinators.zip(zipfile,path,name) -- ok ?
- if not path or path == "" then
- return format('%s?name=%s',zipfile,name)
- else
- return format('%s?name=%s/%s',zipfile,path,name)
- end
+function resolvers.findgivenfile(filename)
+ return findgivenfiles(filename,false)[1] or ""
end
-
-function resolvers.finders.zip(specification)
- local original = specification.original
- local archive = specification.filename
- if archive then
- local query = url.query(specification.query)
- local queryname = query.name
- if queryname then
- local zfile = zip.openarchive(archive)
- if zfile then
- if trace_locating then
- report_zip("finder, archive '%s' found",archive)
- end
- local dfile = zfile:open(queryname)
- if dfile then
- dfile = zfile:close()
- if trace_locating then
- report_zip("finder, file '%s' found",queryname)
- end
- return specification.original
- elseif trace_locating then
- report_zip("finder, file '%s' not found",queryname)
- end
- elseif trace_locating then
- report_zip("finder, unknown archive '%s'",archive)
- end
+local function doit(path,blist,bname,tag,variant,result,allresults)
+ local done=false
+ if blist and variant then
+ local resolve=resolvers.resolve
+ if type(blist)=='string' then
+ if find(lower(blist),path) then
+ local full=methodhandler('concatinators',variant,tag,blist,bname) or ""
+ result[#result+1]=resolve(full)
+ done=true
+ end
+ else
+ for kk=1,#blist do
+ local vv=blist[kk]
+ if find(lower(vv),path) then
+ local full=methodhandler('concatinators',variant,tag,vv,bname) or ""
+ result[#result+1]=resolve(full)
+ done=true
+ if not allresults then break end
end
+ end
end
- if trace_locating then
- report_zip("finder, '%s' not found",original)
- end
- return resolvers.finders.notfound()
+ end
+ return done
end
-
-function resolvers.openers.zip(specification)
- local original = specification.original
- local archive = specification.filename
- if archive then
- local query = url.query(specification.query)
- local queryname = query.name
- if queryname then
- local zfile = zip.openarchive(archive)
- if zfile then
- if trace_locating then
- report_zip("opener, archive '%s' opened",archive)
- end
- local dfile = zfile:open(queryname)
- if dfile then
- if trace_locating then
- report_zip("opener, file '%s' found",queryname)
- end
- return resolvers.openers.helpers.textopener('zip',original,dfile)
- elseif trace_locating then
- report_zip("opener, file '%s' not found",queryname)
- end
- elseif trace_locating then
- report_zip("opener, unknown archive '%s'",archive)
- end
+local makewildcard=Cs(
+ (P("^")^0*P("/")*P(-1)+P(-1))/".*"+(P("^")^0*P("/")/"")^0*(P("*")/".*"+P("-")/"%%-"+P(".")/"%%."+P("?")/"."+P("\\")/"/"+P(1))^0
+)
+function resolvers.wildcardpattern(pattern)
+ return lpegmatch(makewildcard,pattern) or pattern
+end
+local function findwildcardfiles(filename,allresults,result)
+ result=result or {}
+ local base=filebasename(filename)
+ local dirn=filedirname(filename)
+ local path=lower(lpegmatch(makewildcard,dirn) or dirn)
+ local name=lower(lpegmatch(makewildcard,base) or base)
+ local files,done=instance.files,false
+ if find(name,"%*") then
+ local hashes=instance.hashes
+ for k=1,#hashes do
+ local hash=hashes[k]
+ local hashname,hashtype=hash.name,hash.type
+ for kk,hh in next,files[hashname] do
+ if not find(kk,"^remap:") then
+ if find(lower(kk),name) then
+ if doit(path,hh,kk,hashname,hashtype,result,allresults) then done=true end
+ if done and not allresults then break end
+ end
end
+ end
end
- if trace_locating then
- report_zip("opener, '%s' not found",original)
+ else
+ local hashes=instance.hashes
+ for k=1,#hashes do
+ local hash=hashes[k]
+ local hashname,hashtype=hash.name,hash.type
+ if doit(path,files[hashname][bname],bname,hashname,hashtype,result,allresults) then done=true end
+ if done and not allresults then break end
end
- return resolvers.openers.notfound()
+ end
+ return result
end
-
-function resolvers.loaders.zip(specification)
- local original = specification.original
- local archive = specification.filename
- if archive then
- local query = url.query(specification.query)
- local queryname = query.name
- if queryname then
- local zfile = zip.openarchive(archive)
- if zfile then
- if trace_locating then
- report_zip("loader, archive '%s' opened",archive)
- end
- local dfile = zfile:open(queryname)
- if dfile then
- logs.show_load(original)
- if trace_locating then
- report_zip("loader, file '%s' loaded",original)
- end
- local s = dfile:read("*all")
- dfile:close()
- return true, s, #s
- elseif trace_locating then
- report_zip("loader, file '%s' not found",queryname)
- end
- elseif trace_locating then
- report_zip("loader, unknown archive '%s'",archive)
- end
- end
- end
+function resolvers.findwildcardfiles(filename,result)
+ return findwildcardfiles(filename,true,result)
+end
+function resolvers.findwildcardfile(filename)
+ return findwildcardfiles(filename,false)[1] or ""
+end
+function resolvers.automount()
+end
+function resolvers.load(option)
+ statistics.starttiming(instance)
+ identify_configuration_files()
+ load_configuration_files()
+ if option~="nofiles" then
+ load_databases()
+ resolvers.automount()
+ end
+ statistics.stoptiming(instance)
+ local files=instance.files
+ return files and next(files) and true
+end
+function resolvers.loadtime()
+ return statistics.elapsedtime(instance)
+end
+local function report(str)
+ if trace_locating then
+ report_resolving(str)
+ else
+ print(str)
+ end
+end
+function resolvers.dowithfilesandreport(command,files,...)
+ if files and #files>0 then
if trace_locating then
- report_zip("loader, '%s' not found",original)
+ report('')
end
- return resolvers.openers.notfound()
-end
-
--- zip:///somefile.zip
--- zip:///somefile.zip?tree=texmf-local -> mount
-
-function resolvers.usezipfile(archive)
- local specification = resolvers.splitmethod(archive) -- to be sure
- local archive = specification.filename
- if archive and not registeredfiles[archive] then
- local z = zip.openarchive(archive)
- if z then
- local instance = resolvers.instance
- local tree = url.query(specification.query).tree or ""
- if trace_locating then
- report_zip("registering, registering archive '%s'",archive)
- end
- statistics.starttiming(instance)
- resolvers.prependhash('zip',archive)
- resolvers.extendtexmfvariable(archive) -- resets hashes too
- registeredfiles[archive] = z
- instance.files[archive] = resolvers.registerzipfile(z,tree)
- statistics.stoptiming(instance)
- elseif trace_locating then
- report_zip("registering, unknown archive '%s'",archive)
+ if type(files)=="string" then
+ files={ files }
+ end
+ for f=1,#files do
+ local file=files[f]
+ local result=command(file,...)
+ if type(result)=='string' then
+ report(result)
+ else
+ for i=1,#result do
+ report(result[i])
end
- elseif trace_locating then
- report_zip("registering, '%s' not found",archive)
+ end
end
+ end
end
-
-function resolvers.registerzipfile(z,tree)
- local files, filter = { }, ""
- if tree == "" then
- filter = "^(.+)/(.-)$"
+function resolvers.showpath(str)
+ return joinpath(resolvers.expandedpathlist(resolvers.formatofvariable(str)))
+end
+function resolvers.registerfile(files,name,path)
+ if files[name] then
+ if type(files[name])=='string' then
+ files[name]={ files[name],path }
else
- filter = format("^%s/(.+)/(.-)$",tree)
+ files[name]=path
end
- if trace_locating then
- report_zip("registering, using filter '%s'",filter)
- end
- local register, n = resolvers.registerfile, 0
- for i in z:files() do
- local path, name = match(i.filename,filter)
- if path then
- if name and name ~= '' then
- register(files, name, path)
- n = n + 1
+ else
+ files[name]=path
+ end
+end
+function resolvers.dowithpath(name,func)
+ local pathlist=resolvers.expandedpathlist(name)
+ for i=1,#pathlist do
+ func("^"..resolvers.cleanpath(pathlist[i]))
+ end
+end
+function resolvers.dowithvariable(name,func)
+ func(expandedvariable(name))
+end
+function resolvers.locateformat(name)
+ local engine=environment.ownmain or "luatex"
+ local barename=file.removesuffix(name)
+ local fullname=file.addsuffix(barename,"fmt")
+ local fmtname=caches.getfirstreadablefile(fullname,"formats",engine) or ""
+ if fmtname=="" then
+ fmtname=resolvers.findfile(fullname)
+ fmtname=resolvers.cleanpath(fmtname)
+ end
+ if fmtname~="" then
+ local barename=file.removesuffix(fmtname)
+ local luaname=file.addsuffix(barename,luasuffixes.lua)
+ local lucname=file.addsuffix(barename,luasuffixes.luc)
+ local luiname=file.addsuffix(barename,luasuffixes.lui)
+ if lfs.isfile(luiname) then
+ return barename,luiname
+ elseif lfs.isfile(lucname) then
+ return barename,lucname
+ elseif lfs.isfile(luaname) then
+ return barename,luaname
+ end
+ end
+ return nil,nil
+end
+function resolvers.booleanvariable(str,default)
+ local b=resolvers.expansion(str)
+ if b=="" then
+ return default
+ else
+ b=toboolean(b)
+ return (b==nil and default) or b
+ end
+end
+function resolvers.dowithfilesintree(pattern,handle,before,after)
+ local instance=resolvers.instance
+ local hashes=instance.hashes
+ for i=1,#hashes do
+ local hash=hashes[i]
+ local blobtype=hash.type
+ local blobpath=hash.name
+ if blobpath then
+ if before then
+ before(blobtype,blobpath,pattern)
+ end
+ local files=instance.files[blobpath]
+ local total,checked,done=0,0,0
+ if files then
+ for k,v in table.sortedhash(files) do
+ total=total+1
+ if find(k,"^remap:") then
+ elseif find(k,pattern) then
+ if type(v)=="string" then
+ checked=checked+1
+ if handle(blobtype,blobpath,v,k) then
+ done=done+1
+ end
else
- -- directory
+ checked=checked+#v
+ for i=1,#v do
+ if handle(blobtype,blobpath,v[i],k) then
+ done=done+1
+ end
+ end
end
- else
- register(files, i.filename, '')
- n = n + 1
+ end
end
+ end
+ if after then
+ after(blobtype,blobpath,pattern,total,checked,done)
+ end
end
- report_zip("registering, %s files registered",n)
- return files
+ end
end
+resolvers.obsolete=resolvers.obsolete or {}
+local obsolete=resolvers.obsolete
+resolvers.find_file=resolvers.findfile obsolete.find_file=resolvers.findfile
+resolvers.find_files=resolvers.findfiles obsolete.find_files=resolvers.findfiles
end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['data-tre'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- \input tree://oeps1/**/oeps.tex
+package.loaded["data-pre"] = package.loaded["data-pre"] or true
-local find, gsub, format = string.find, string.gsub, string.format
+-- original size: 6430, stripped down to: 4219
-local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
-
-local report_trees = logs.reporter("resolvers","trees")
-
-local resolvers = resolvers
-
-local done, found, notfound = { }, { }, resolvers.finders.notfound
-
-function resolvers.finders.tree(specification)
- local spec = specification.filename
- local fnd = found[spec]
- if fnd == nil then
- if spec ~= "" then
- local path, name = file.dirname(spec), file.basename(spec)
- if path == "" then path = "." end
- local hash = done[path]
- if not hash then
- local pattern = path .. "/*" -- we will use the proper splitter
- hash = dir.glob(pattern)
- done[path] = hash
- end
- local pattern = "/" .. gsub(name,"([%.%-%+])", "%%%1") .. "$"
- for k=1,#hash do
- local v = hash[k]
- if find(v,pattern) then
- found[spec] = v
- return v
- end
- end
- end
- fnd = notfound() -- false
- found[spec] = fnd
+if not modules then modules={} end modules ['data-pre']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local resolvers=resolvers
+local prefixes=utilities.storage.allocate()
+resolvers.prefixes=prefixes
+local cleanpath,findgivenfile,expansion=resolvers.cleanpath,resolvers.findgivenfile,resolvers.expansion
+local getenv=resolvers.getenv
+local P,S,R,C,Cs,lpegmatch=lpeg.P,lpeg.S,lpeg.R,lpeg.C,lpeg.Cs,lpeg.match
+local joinpath,basename,dirname=file.join,file.basename,file.dirname
+local getmetatable,rawset,type=getmetatable,rawset,type
+prefixes.environment=function(str)
+ return cleanpath(expansion(str))
+end
+prefixes.relative=function(str,n)
+ if io.exists(str) then
+ elseif io.exists("./"..str) then
+ str="./"..str
+ else
+ local p="../"
+ for i=1,n or 2 do
+ if io.exists(p..str) then
+ str=p..str
+ break
+ else
+ p=p.."../"
+ end
+ end
+ end
+ return cleanpath(str)
+end
+prefixes.auto=function(str)
+ local fullname=prefixes.relative(str)
+ if not lfs.isfile(fullname) then
+ fullname=prefixes.locate(str)
+ end
+ return fullname
+end
+prefixes.locate=function(str)
+ local fullname=findgivenfile(str) or ""
+ return cleanpath((fullname~="" and fullname) or str)
+end
+prefixes.filename=function(str)
+ local fullname=findgivenfile(str) or ""
+ return cleanpath(basename((fullname~="" and fullname) or str))
+end
+prefixes.pathname=function(str)
+ local fullname=findgivenfile(str) or ""
+ return cleanpath(dirname((fullname~="" and fullname) or str))
+end
+prefixes.selfautoloc=function(str)
+ return cleanpath(joinpath(getenv('SELFAUTOLOC'),str))
+end
+prefixes.selfautoparent=function(str)
+ return cleanpath(joinpath(getenv('SELFAUTOPARENT'),str))
+end
+prefixes.selfautodir=function(str)
+ return cleanpath(joinpath(getenv('SELFAUTODIR'),str))
+end
+prefixes.home=function(str)
+ return cleanpath(joinpath(getenv('HOME'),str))
+end
+local function toppath()
+ local inputstack=resolvers.inputstack
+ if not inputstack then
+ return "."
+ end
+ local pathname=dirname(inputstack[#inputstack] or "")
+ if pathname=="" then
+ return "."
+ else
+ return pathname
+ end
+end
+resolvers.toppath=toppath
+prefixes.toppath=function(str)
+ return cleanpath(joinpath(toppath(),str))
+end
+prefixes.env=prefixes.environment
+prefixes.rel=prefixes.relative
+prefixes.loc=prefixes.locate
+prefixes.kpse=prefixes.locate
+prefixes.full=prefixes.locate
+prefixes.file=prefixes.filename
+prefixes.path=prefixes.pathname
+function resolvers.allprefixes(separator)
+ local all=table.sortedkeys(prefixes)
+ if separator then
+ for i=1,#all do
+ all[i]=all[i]..":"
end
- return fnd
+ end
+ return all
end
-
-function resolvers.locators.tree(specification)
- local name = specification.filename
- local realname = resolvers.resolve(name) -- no shortcut
- if realname and realname ~= '' and lfs.isdir(realname) then
- if trace_locating then
- report_trees("locator '%s' found",realname)
- end
- resolvers.appendhash('tree',name,false) -- don't cache
- elseif trace_locating then
- report_trees("locator '%s' not found",name)
+local function _resolve_(method,target)
+ local action=prefixes[method]
+ if action then
+ return action(target)
+ else
+ return method..":"..target
+ end
+end
+local resolved,abstract={},{}
+function resolvers.resetresolve(str)
+ resolved,abstract={},{}
+end
+local pattern=Cs((C(R("az")^2)*P(":")*C((1-S(" \"\';,"))^1)/_resolve_+P(1))^0)
+local function resolve(str)
+ if type(str)=="table" then
+ local t={}
+ for i=1,#str do
+ t[i]=resolve(str[i])
+ end
+ return t
+ else
+ local res=resolved[str]
+ if not res then
+ res=lpegmatch(pattern,str)
+ resolved[str]=res
+ abstract[res]=str
end
+ return res
+ end
end
-
-function resolvers.hashers.tree(specification)
- local name = specification.filename
- if trace_locating then
- report_trees("analysing '%s'",name)
+local function unresolve(str)
+ return abstract[str] or str
+end
+resolvers.resolve=resolve
+resolvers.unresolve=unresolve
+if type(os.uname)=="function" then
+ for k,v in next,os.uname() do
+ if not prefixes[k] then
+ prefixes[k]=function() return v end
end
- resolvers.methodhandler("hashers",name)
-
- resolvers.generators.file(specification)
+ end
+end
+if os.type=="unix" then
+ local pattern
+ local function makepattern(t,k,v)
+ if t then
+ rawset(t,k,v)
+ end
+ local colon=P(":")
+ for k,v in table.sortedpairs(prefixes) do
+ if p then
+ p=P(k)+p
+ else
+ p=P(k)
+ end
+ end
+ pattern=Cs((p*colon+colon/";"+P(1))^0)
+ end
+ makepattern()
+ getmetatable(prefixes).__newindex=makepattern
+ function resolvers.repath(str)
+ return lpegmatch(pattern,str)
+ end
+else
+ function resolvers.repath(str)
+ return str
+ end
end
-
-resolvers.concatinators.tree = resolvers.concatinators.file
-resolvers.generators.tree = resolvers.generators.file
-resolvers.openers.tree = resolvers.openers.file
-resolvers.loaders.tree = resolvers.loaders.file
end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['data-crl'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
+package.loaded["data-inp"] = package.loaded["data-inp"] or true
+
+-- original size: 910, stripped down to: 823
--- this one is replaced by data-sch.lua --
+if not modules then modules={} end modules ['data-inp']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local allocate=utilities.storage.allocate
+local resolvers=resolvers
+local methodhandler=resolvers.methodhandler
+local registermethod=resolvers.registermethod
+local finders=allocate { helpers={},notfound=function() end }
+local openers=allocate { helpers={},notfound=function() end }
+local loaders=allocate { helpers={},notfound=function() return false,nil,0 end }
+registermethod("finders",finders,"uri")
+registermethod("openers",openers,"uri")
+registermethod("loaders",loaders,"uri")
+resolvers.finders=finders
+resolvers.openers=openers
+resolvers.loaders=loaders
-local gsub = string.gsub
-local resolvers = resolvers
+end -- of closure
-local finders, openers, loaders = resolvers.finders, resolvers.openers, resolvers.loaders
+do -- create closure to overcome 200 locals limit
-resolvers.curl = resolvers.curl or { }
-local curl = resolvers.curl
+package.loaded["data-out"] = package.loaded["data-out"] or true
-local cached = { }
+-- original size: 530, stripped down to: 475
-local function runcurl(specification)
- local original = specification.original
- -- local scheme = specification.scheme
- local cleanname = gsub(original,"[^%a%d%.]+","-")
- local cachename = caches.setfirstwritablefile(cleanname,"curl")
- if not cached[original] then
- if not io.exists(cachename) then
- cached[original] = cachename
- local command = "curl --silent --create-dirs --output " .. cachename .. " " .. original
- os.spawn(command)
- end
- if io.exists(cachename) then
- cached[original] = cachename
- else
- cached[original] = ""
- end
- end
- return cached[original]
-end
+if not modules then modules={} end modules ['data-out']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local allocate=utilities.storage.allocate
+local resolvers=resolvers
+local registermethod=resolvers.registermethod
+local savers=allocate { helpers={} }
+resolvers.savers=savers
+registermethod("savers",savers,"uri")
--- old code: we could be cleaner using specification (see schemes)
-local function finder(specification,filetype)
- return resolvers.methodhandler("finders",runcurl(specification),filetype)
-end
+end -- of closure
-local opener = openers.file
-local loader = loaders.file
+do -- create closure to overcome 200 locals limit
-local function install(scheme)
- finders[scheme] = finder
- openers[scheme] = opener
- loaders[scheme] = loader
-end
+package.loaded["data-fil"] = package.loaded["data-fil"] or true
-resolvers.curl.install = install
+-- original size: 3801, stripped down to: 3231
-install('http')
-install('https')
-install('ftp')
+if not modules then modules={} end modules ['data-fil']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end)
+local report_files=logs.reporter("resolvers","files")
+local resolvers=resolvers
+local finders,openers,loaders,savers=resolvers.finders,resolvers.openers,resolvers.loaders,resolvers.savers
+local locators,hashers,generators,concatinators=resolvers.locators,resolvers.hashers,resolvers.generators,resolvers.concatinators
+local checkgarbage=utilities.garbagecollector and utilities.garbagecollector.check
+function locators.file(specification)
+ local name=specification.filename
+ local realname=resolvers.resolve(name)
+ if realname and realname~='' and lfs.isdir(realname) then
+ if trace_locating then
+ report_files("file locator %a found as %a",name,realname)
+ end
+ resolvers.appendhash('file',name,true)
+ elseif trace_locating then
+ report_files("file locator %a not found",name)
+ end
+end
+function hashers.file(specification)
+ local name=specification.filename
+ local content=caches.loadcontent(name,'files')
+ resolvers.registerfilehash(name,content,content==nil)
+end
+function generators.file(specification)
+ local path=specification.filename
+ local content=resolvers.scanfiles(path,false,true)
+ resolvers.registerfilehash(path,content,true)
+end
+concatinators.file=file.join
+function finders.file(specification,filetype)
+ local filename=specification.filename
+ local foundname=resolvers.findfile(filename,filetype)
+ if foundname and foundname~="" then
+ if trace_locating then
+ report_files("file finder: %a found",filename)
+ end
+ return foundname
+ else
+ if trace_locating then
+ report_files("file finder: %a not found",filename)
+ end
+ return finders.notfound()
+ end
+end
+function openers.helpers.textopener(tag,filename,f)
+ return {
+ reader=function() return f:read () end,
+ close=function() logs.show_close(filename) return f:close() end,
+ }
+end
+function openers.file(specification,filetype)
+ local filename=specification.filename
+ if filename and filename~="" then
+ local f=io.open(filename,"r")
+ if f then
+ if trace_locating then
+ report_files("file opener: %a opened",filename)
+ end
+ return openers.helpers.textopener("file",filename,f)
+ end
+ end
+ if trace_locating then
+ report_files("file opener: %a not found",filename)
+ end
+ return openers.notfound()
+end
+function loaders.file(specification,filetype)
+ local filename=specification.filename
+ if filename and filename~="" then
+ local f=io.open(filename,"rb")
+ if f then
+ logs.show_load(filename)
+ if trace_locating then
+ report_files("file loader: %a loaded",filename)
+ end
+ local s=f:read("*a")
+ if checkgarbage then
+ checkgarbage(#s)
+ end
+ f:close()
+ if s then
+ return true,s,#s
+ end
+ end
+ end
+ if trace_locating then
+ report_files("file loader: %a not found",filename)
+ end
+ return loaders.notfound()
+end
end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['data-lua'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
+package.loaded["data-con"] = package.loaded["data-con"] or true
--- some loading stuff ... we might move this one to slot 2 depending
--- on the developments (the loaders must not trigger kpse); we could
--- of course use a more extensive lib path spec
+-- original size: 4940, stripped down to: 3580
-local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
+if not modules then modules={} end modules ['data-con']={
+ version=1.100,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local format,lower,gsub=string.format,string.lower,string.gsub
+local trace_cache=false trackers.register("resolvers.cache",function(v) trace_cache=v end)
+local trace_containers=false trackers.register("resolvers.containers",function(v) trace_containers=v end)
+local trace_storage=false trackers.register("resolvers.storage",function(v) trace_storage=v end)
+containers=containers or {}
+local containers=containers
+containers.usecache=true
+local report_containers=logs.reporter("resolvers","containers")
+local allocated={}
+local mt={
+ __index=function(t,k)
+ if k=="writable" then
+ local writable=caches.getwritablepath(t.category,t.subcategory) or { "." }
+ t.writable=writable
+ return writable
+ elseif k=="readables" then
+ local readables=caches.getreadablepaths(t.category,t.subcategory) or { "." }
+ t.readables=readables
+ return readables
+ end
+ end,
+ __storage__=true
+}
+function containers.define(category,subcategory,version,enabled)
+ if category and subcategory then
+ local c=allocated[category]
+ if not c then
+ c={}
+ allocated[category]=c
+ end
+ local s=c[subcategory]
+ if not s then
+ s={
+ category=category,
+ subcategory=subcategory,
+ storage={},
+ enabled=enabled,
+ version=version or math.pi,
+ trace=false,
+ }
+ setmetatable(s,mt)
+ c[subcategory]=s
+ end
+ return s
+ end
+end
+function containers.is_usable(container,name)
+ return container.enabled and caches and caches.is_writable(container.writable,name)
+end
+function containers.is_valid(container,name)
+ if name and name~="" then
+ local storage=container.storage[name]
+ return storage and storage.cache_version==container.version
+ else
+ return false
+ end
+end
+function containers.read(container,name)
+ local storage=container.storage
+ local stored=storage[name]
+ if not stored and container.enabled and caches and containers.usecache then
+ stored=caches.loaddata(container.readables,name)
+ if stored and stored.cache_version==container.version then
+ if trace_cache or trace_containers then
+ report_containers("action %a, category %a, name %a","load",container.subcategory,name)
+ end
+ else
+ stored=nil
+ end
+ storage[name]=stored
+ elseif stored then
+ if trace_cache or trace_containers then
+ report_containers("action %a, category %a, name %a","reuse",container.subcategory,name)
+ end
+ end
+ return stored
+end
+function containers.write(container,name,data)
+ if data then
+ data.cache_version=container.version
+ if container.enabled and caches then
+ local unique,shared=data.unique,data.shared
+ data.unique,data.shared=nil,nil
+ caches.savedata(container.writable,name,data)
+ if trace_cache or trace_containers then
+ report_containers("action %a, category %a, name %a","save",container.subcategory,name)
+ end
+ data.unique,data.shared=unique,shared
+ end
+ if trace_cache or trace_containers then
+ report_containers("action %a, category %a, name %a","store",container.subcategory,name)
+ end
+ container.storage[name]=data
+ end
+ return data
+end
+function containers.content(container,name)
+ return container.storage[name]
+end
+function containers.cleanname(name)
+ return (gsub(lower(name),"[^%w%d]+","-"))
+end
-local report_libraries = logs.reporter("resolvers","libraries")
-local gsub, insert = string.gsub, table.insert
-local unpack = unpack or table.unpack
+end -- of closure
-local resolvers, package = resolvers, package
+do -- create closure to overcome 200 locals limit
-local libformats = { 'luatexlibs', 'tex', 'texmfscripts', 'othertextfiles' } -- 'luainputs'
-local clibformats = { 'lib' }
+package.loaded["data-use"] = package.loaded["data-use"] or true
-local _path_, libpaths, _cpath_, clibpaths
+-- original size: 3913, stripped down to: 2998
-function package.libpaths()
- if not _path_ or package.path ~= _path_ then
- _path_ = package.path
- libpaths = file.splitpath(_path_,";")
- end
- return libpaths
+if not modules then modules={} end modules ['data-use']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local format,lower,gsub,find=string.format,string.lower,string.gsub,string.find
+local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end)
+local report_mounts=logs.reporter("resolvers","mounts")
+local resolvers=resolvers
+resolvers.automounted=resolvers.automounted or {}
+function resolvers.automount(usecache)
+ local mountpaths=resolvers.cleanpathlist(resolvers.expansion('TEXMFMOUNT'))
+ if (not mountpaths or #mountpaths==0) and usecache then
+ mountpaths=caches.getreadablepaths("mount")
+ end
+ if mountpaths and #mountpaths>0 then
+ statistics.starttiming(resolvers.instance)
+ for k=1,#mountpaths do
+ local root=mountpaths[k]
+ local f=io.open(root.."/url.tmi")
+ if f then
+ for line in f:lines() do
+ if line then
+ if find(line,"^[%%#%-]") then
+ elseif find(line,"^zip://") then
+ if trace_locating then
+ report_mounts("mounting %a",line)
+ end
+ table.insert(resolvers.automounted,line)
+ resolvers.usezipfile(line)
+ end
+ end
+ end
+ f:close()
+ end
+ end
+ statistics.stoptiming(resolvers.instance)
+ end
+end
+statistics.register("used config file",function() return caches.configfiles() end)
+statistics.register("used cache path",function() return caches.usedpaths() end)
+function statistics.savefmtstatus(texname,formatbanner,sourcefile)
+ local enginebanner=status.list().banner
+ if formatbanner and enginebanner and sourcefile then
+ local luvname=file.replacesuffix(texname,"luv")
+ local luvdata={
+ enginebanner=enginebanner,
+ formatbanner=formatbanner,
+ sourcehash=md5.hex(io.loaddata(resolvers.findfile(sourcefile)) or "unknown"),
+ sourcefile=sourcefile,
+ }
+ io.savedata(luvname,table.serialize(luvdata,true))
+ end
end
-
-function package.clibpaths()
- if not _cpath_ or package.cpath ~= _cpath_ then
- _cpath_ = package.cpath
- clibpaths = file.splitpath(_cpath_,";")
+function statistics.checkfmtstatus(texname)
+ local enginebanner=status.list().banner
+ if enginebanner and texname then
+ local luvname=file.replacesuffix(texname,"luv")
+ if lfs.isfile(luvname) then
+ local luv=dofile(luvname)
+ if luv and luv.sourcefile then
+ local sourcehash=md5.hex(io.loaddata(resolvers.findfile(luv.sourcefile)) or "unknown")
+ local luvbanner=luv.enginebanner or "?"
+ if luvbanner~=enginebanner then
+ return format("engine mismatch (luv: %s <> bin: %s)",luvbanner,enginebanner)
+ end
+ local luvhash=luv.sourcehash or "?"
+ if luvhash~=sourcehash then
+ return format("source mismatch (luv: %s <> bin: %s)",luvhash,sourcehash)
+ end
+ else
+ return "invalid status file"
+ end
+ else
+ return "missing status file"
end
- return clibpaths
+ end
+ return true
end
-local function thepath(...)
- local t = { ... } t[#t+1] = "?.lua"
- local path = file.join(unpack(t))
- if trace_locating then
- report_libraries("! appending '%s' to 'package.path'",path)
- end
- return path
-end
-local p_libpaths, a_libpaths = { }, { }
+end -- of closure
-function package.appendtolibpath(...)
- insert(a_libpath,thepath(...))
-end
+do -- create closure to overcome 200 locals limit
-function package.prependtolibpath(...)
- insert(p_libpaths,1,thepath(...))
-end
+package.loaded["data-zip"] = package.loaded["data-zip"] or true
--- beware, we need to return a loadfile result !
+-- original size: 8489, stripped down to: 6757
-local function loaded(libpaths,name,simple)
- for i=1,#libpaths do -- package.path, might become option
- local libpath = libpaths[i]
- local resolved = gsub(libpath,"%?",simple)
- if trace_locating then -- more detail
- report_libraries("! checking for '%s' on 'package.path': '%s' => '%s'",simple,libpath,resolved)
- end
- if file.is_readable(resolved) then
- if trace_locating then
- report_libraries("! lib '%s' located via 'package.path': '%s'",name,resolved)
- end
- return loadfile(resolved)
- end
+if not modules then modules={} end modules ['data-zip']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local format,find,match=string.format,string.find,string.match
+local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end)
+local report_zip=logs.reporter("resolvers","zip")
+local resolvers=resolvers
+zip=zip or {}
+local zip=zip
+zip.archives=zip.archives or {}
+local archives=zip.archives
+zip.registeredfiles=zip.registeredfiles or {}
+local registeredfiles=zip.registeredfiles
+local limited=false
+directives.register("system.inputmode",function(v)
+ if not limited then
+ local i_limiter=io.i_limiter(v)
+ if i_limiter then
+ zip.open=i_limiter.protect(zip.open)
+ limited=true
+ end
+ end
+end)
+local function validzip(str)
+ if not find(str,"^zip://") then
+ return "zip:///"..str
+ else
+ return str
+ end
+end
+function zip.openarchive(name)
+ if not name or name=="" then
+ return nil
+ else
+ local arch=archives[name]
+ if not arch then
+ local full=resolvers.findfile(name) or ""
+ arch=(full~="" and zip.open(full)) or false
+ archives[name]=arch
end
+ return arch
+ end
end
-
-package.loaders[2] = function(name) -- was [#package.loaders+1]
- if file.suffix(name) == "" then
- name = file.addsuffix(name,"lua") -- maybe a list
- if trace_locating then -- mode detail
- report_libraries("! locating '%s' with forced suffix",name)
- end
+function zip.closearchive(name)
+ if not name or (name=="" and archives[name]) then
+ zip.close(archives[name])
+ archives[name]=nil
+ end
+end
+function resolvers.locators.zip(specification)
+ local archive=specification.filename
+ local zipfile=archive and archive~="" and zip.openarchive(archive)
+ if trace_locating then
+ if zipfile then
+ report_zip("locator: archive %a found",archive)
else
- if trace_locating then -- mode detail
- report_libraries("! locating '%s'",name)
- end
+ report_zip("locator: archive %a not found",archive)
end
- for i=1,#libformats do
- local format = libformats[i]
- local resolved = resolvers.findfile(name,format) or ""
- if trace_locating then -- mode detail
- report_libraries("! checking for '%s' using 'libformat path': '%s'",name,format)
- end
- if resolved ~= "" then
- if trace_locating then
- report_libraries("! lib '%s' located via environment: '%s'",name,resolved)
- end
- return loadfile(resolved)
- end
- end
- -- libpaths
- local libpaths, clibpaths = package.libpaths(), package.clibpaths()
- local simple = gsub(name,"%.lua$","")
- local simple = gsub(simple,"%.","/")
- local resolved = loaded(p_libpaths,name,simple) or loaded(libpaths,name,simple) or loaded(a_libpaths,name,simple)
- if resolved then
- return resolved
- end
- --
- local libname = file.addsuffix(simple,os.libsuffix)
- for i=1,#clibformats do
- -- better have a dedicated loop
- local format = clibformats[i]
- local paths = resolvers.expandedpathlistfromvariable(format)
- for p=1,#paths do
- local path = paths[p]
- local resolved = file.join(path,libname)
- if trace_locating then -- mode detail
- report_libraries("! checking for '%s' using 'clibformat path': '%s'",libname,path)
- end
- if file.is_readable(resolved) then
- if trace_locating then
- report_libraries("! lib '%s' located via 'clibformat': '%s'",libname,resolved)
- end
- return package.loadlib(resolved,name)
- end
+ end
+end
+function resolvers.hashers.zip(specification)
+ local archive=specification.filename
+ if trace_locating then
+ report_zip("loading file %a",archive)
+ end
+ resolvers.usezipfile(specification.original)
+end
+function resolvers.concatinators.zip(zipfile,path,name)
+ if not path or path=="" then
+ return format('%s?name=%s',zipfile,name)
+ else
+ return format('%s?name=%s/%s',zipfile,path,name)
+ end
+end
+function resolvers.finders.zip(specification)
+ local original=specification.original
+ local archive=specification.filename
+ if archive then
+ local query=url.query(specification.query)
+ local queryname=query.name
+ if queryname then
+ local zfile=zip.openarchive(archive)
+ if zfile then
+ if trace_locating then
+ report_zip("finder: archive %a found",archive)
+ end
+ local dfile=zfile:open(queryname)
+ if dfile then
+ dfile=zfile:close()
+ if trace_locating then
+ report_zip("finder: file %a found",queryname)
+ end
+ return specification.original
+ elseif trace_locating then
+ report_zip("finder: file %a not found",queryname)
end
+ elseif trace_locating then
+ report_zip("finder: unknown archive %a",archive)
+ end
end
- for i=1,#clibpaths do -- package.path, might become option
- local libpath = clibpaths[i]
- local resolved = gsub(libpath,"?",simple)
- if trace_locating then -- more detail
- report_libraries("! checking for '%s' on 'package.cpath': '%s'",simple,libpath)
- end
- if file.is_readable(resolved) then
- if trace_locating then
- report_libraries("! lib '%s' located via 'package.cpath': '%s'",name,resolved)
- end
- return package.loadlib(resolved,name)
+ end
+ if trace_locating then
+ report_zip("finder: %a not found",original)
+ end
+ return resolvers.finders.notfound()
+end
+function resolvers.openers.zip(specification)
+ local original=specification.original
+ local archive=specification.filename
+ if archive then
+ local query=url.query(specification.query)
+ local queryname=query.name
+ if queryname then
+ local zfile=zip.openarchive(archive)
+ if zfile then
+ if trace_locating then
+ report_zip("opener; archive %a opened",archive)
+ end
+ local dfile=zfile:open(queryname)
+ if dfile then
+ if trace_locating then
+ report_zip("opener: file %a found",queryname)
+ end
+ return resolvers.openers.helpers.textopener('zip',original,dfile)
+ elseif trace_locating then
+ report_zip("opener: file %a not found",queryname)
end
+ elseif trace_locating then
+ report_zip("opener: unknown archive %a",archive)
+ end
end
- -- just in case the distribution is messed up
- if trace_loading then -- more detail
- report_libraries("! checking for '%s' using 'luatexlibs': '%s'",name)
- end
- local resolved = resolvers.findfile(file.basename(name),'luatexlibs') or ""
- if resolved ~= "" then
+ end
+ if trace_locating then
+ report_zip("opener: %a not found",original)
+ end
+ return resolvers.openers.notfound()
+end
+function resolvers.loaders.zip(specification)
+ local original=specification.original
+ local archive=specification.filename
+ if archive then
+ local query=url.query(specification.query)
+ local queryname=query.name
+ if queryname then
+ local zfile=zip.openarchive(archive)
+ if zfile then
if trace_locating then
- report_libraries("! lib '%s' located by basename via environment: '%s'",name,resolved)
+ report_zip("loader: archive %a opened",archive)
+ end
+ local dfile=zfile:open(queryname)
+ if dfile then
+ logs.show_load(original)
+ if trace_locating then
+ report_zip("loader; file %a loaded",original)
+ end
+ local s=dfile:read("*all")
+ dfile:close()
+ return true,s,#s
+ elseif trace_locating then
+ report_zip("loader: file %a not found",queryname)
end
- return loadfile(resolved)
+ elseif trace_locating then
+ report_zip("loader; unknown archive %a",archive)
+ end
end
- if trace_locating then
- report_libraries('? unable to locate lib: %s',name)
+ end
+ if trace_locating then
+ report_zip("loader: %a not found",original)
+ end
+ return resolvers.openers.notfound()
+end
+function resolvers.usezipfile(archive)
+ local specification=resolvers.splitmethod(archive)
+ local archive=specification.filename
+ if archive and not registeredfiles[archive] then
+ local z=zip.openarchive(archive)
+ if z then
+ local instance=resolvers.instance
+ local tree=url.query(specification.query).tree or ""
+ if trace_locating then
+ report_zip("registering: archive %a",archive)
+ end
+ statistics.starttiming(instance)
+ resolvers.prependhash('zip',archive)
+ resolvers.extendtexmfvariable(archive)
+ registeredfiles[archive]=z
+ instance.files[archive]=resolvers.registerzipfile(z,tree)
+ statistics.stoptiming(instance)
+ elseif trace_locating then
+ report_zip("registering: unknown archive %a",archive)
+ end
+ elseif trace_locating then
+ report_zip("registering: archive %a not found",archive)
+ end
+end
+function resolvers.registerzipfile(z,tree)
+ local files,filter={},""
+ if tree=="" then
+ filter="^(.+)/(.-)$"
+ else
+ filter=format("^%s/(.+)/(.-)$",tree)
+ end
+ if trace_locating then
+ report_zip("registering: using filter %a",filter)
+ end
+ local register,n=resolvers.registerfile,0
+ for i in z:files() do
+ local path,name=match(i.filename,filter)
+ if path then
+ if name and name~='' then
+ register(files,name,path)
+ n=n+1
+ else
+ end
+ else
+ register(files,i.filename,'')
+ n=n+1
end
--- return "unable to locate " .. name
+ end
+ report_zip("registering: %s files registered",n)
+ return files
end
-resolvers.loadlualib = require
--- -- -- --
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
-package.obsolete = package.obsolete or { }
+package.loaded["data-tre"] = package.loaded["data-tre"] or true
-package.append_libpath = appendtolibpath -- will become obsolete
-package.prepend_libpath = prependtolibpath -- will become obsolete
+-- original size: 2508, stripped down to: 2074
-package.obsolete.append_libpath = appendtolibpath -- will become obsolete
-package.obsolete.prepend_libpath = prependtolibpath -- will become obsolete
+if not modules then modules={} end modules ['data-tre']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local find,gsub,format=string.find,string.gsub,string.format
+local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end)
+local report_trees=logs.reporter("resolvers","trees")
+local resolvers=resolvers
+local done,found,notfound={},{},resolvers.finders.notfound
+function resolvers.finders.tree(specification)
+ local spec=specification.filename
+ local fnd=found[spec]
+ if fnd==nil then
+ if spec~="" then
+ local path,name=file.dirname(spec),file.basename(spec)
+ if path=="" then path="." end
+ local hash=done[path]
+ if not hash then
+ local pattern=path.."/*"
+ hash=dir.glob(pattern)
+ done[path]=hash
+ end
+ local pattern="/"..gsub(name,"([%.%-%+])","%%%1").."$"
+ for k=1,#hash do
+ local v=hash[k]
+ if find(v,pattern) then
+ found[spec]=v
+ return v
+ end
+ end
+ end
+ fnd=notfound()
+ found[spec]=fnd
+ end
+ return fnd
+end
+function resolvers.locators.tree(specification)
+ local name=specification.filename
+ local realname=resolvers.resolve(name)
+ if realname and realname~='' and lfs.isdir(realname) then
+ if trace_locating then
+ report_trees("locator %a found",realname)
+ end
+ resolvers.appendhash('tree',name,false)
+ elseif trace_locating then
+ report_trees("locator %a not found",name)
+ end
+end
+function resolvers.hashers.tree(specification)
+ local name=specification.filename
+ if trace_locating then
+ report_trees("analysing %a",name)
+ end
+ resolvers.methodhandler("hashers",name)
+ resolvers.generators.file(specification)
+end
+resolvers.concatinators.tree=resolvers.concatinators.file
+resolvers.generators.tree=resolvers.generators.file
+resolvers.openers.tree=resolvers.openers.file
+resolvers.loaders.tree=resolvers.loaders.file
end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['data-aux'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local find = string.find
-local type, next = type, next
-
-local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
+package.loaded["data-sch"] = package.loaded["data-sch"] or true
-local resolvers = resolvers
+-- original size: 6202, stripped down to: 5149
-local report_scripts = logs.reporter("resolvers","scripts")
-
-function resolvers.updatescript(oldname,newname) -- oldname -> own.name, not per se a suffix
- local scriptpath = "scripts/context/lua"
- newname = file.addsuffix(newname,"lua")
- local oldscript = resolvers.cleanpath(oldname)
- if trace_locating then
- report_scripts("to be replaced old script %s", oldscript)
- end
- local newscripts = resolvers.findfiles(newname) or { }
- if #newscripts == 0 then
- if trace_locating then
- report_scripts("unable to locate new script")
- end
+if not modules then modules={} end modules ['data-sch']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local load=load
+local gsub,concat,format=string.gsub,table.concat,string.format
+local finders,openers,loaders=resolvers.finders,resolvers.openers,resolvers.loaders
+local trace_schemes=false trackers.register("resolvers.schemes",function(v) trace_schemes=v end)
+local report_schemes=logs.reporter("resolvers","schemes")
+local http=require("socket.http")
+local ltn12=require("ltn12")
+local resolvers=resolvers
+local schemes=resolvers.schemes or {}
+resolvers.schemes=schemes
+local cleaners={}
+schemes.cleaners=cleaners
+local threshold=24*60*60
+directives.register("schemes.threshold",function(v) threshold=tonumber(v) or threshold end)
+function cleaners.none(specification)
+ return specification.original
+end
+function cleaners.strip(specification)
+ return (gsub(specification.original,"[^%a%d%.]+","-"))
+end
+function cleaners.md5(specification)
+ return file.addsuffix(md5.hex(specification.original),file.suffix(specification.path))
+end
+local cleaner=cleaners.strip
+directives.register("schemes.cleanmethod",function(v) cleaner=cleaners[v] or cleaners.strip end)
+function resolvers.schemes.cleanname(specification)
+ local hash=cleaner(specification)
+ if trace_schemes then
+ report_schemes("hashing %a to %a",specification.original,hash)
+ end
+ return hash
+end
+local cached,loaded,reused,thresholds,handlers={},{},{},{},{}
+local function runcurl(name,cachename)
+ local command="curl --silent --create-dirs --output "..cachename.." "..name
+ os.spawn(command)
+end
+local function fetch(specification)
+ local original=specification.original
+ local scheme=specification.scheme
+ local cleanname=schemes.cleanname(specification)
+ local cachename=caches.setfirstwritablefile(cleanname,"schemes")
+ if not cached[original] then
+ statistics.starttiming(schemes)
+ if not io.exists(cachename) or (os.difftime(os.time(),lfs.attributes(cachename).modification)>(thresholds[protocol] or threshold)) then
+ cached[original]=cachename
+ local handler=handlers[scheme]
+ if handler then
+ if trace_schemes then
+ report_schemes("fetching %a, protocol %a, method %a",original,scheme,"built-in")
+ end
+ logs.flush()
+ handler(specification,cachename)
+ else
+ if trace_schemes then
+ report_schemes("fetching %a, protocol %a, method %a",original,scheme,"curl")
+ end
+ logs.flush()
+ runcurl(original,cachename)
+ end
+ end
+ if io.exists(cachename) then
+ cached[original]=cachename
+ if trace_schemes then
+ report_schemes("using cached %a, protocol %a, cachename %a",original,scheme,cachename)
+ end
else
- for i=1,#newscripts do
- local newscript = resolvers.cleanpath(newscripts[i])
- if trace_locating then
- report_scripts("checking new script %s", newscript)
- end
- if oldscript == newscript then
- if trace_locating then
- report_scripts("old and new script are the same")
- end
- elseif not find(newscript,scriptpath) then
- if trace_locating then
- report_scripts("new script should come from %s",scriptpath)
- end
- elseif not (find(oldscript,file.removesuffix(newname).."$") or find(oldscript,newname.."$")) then
- if trace_locating then
- report_scripts("invalid new script name")
- end
- else
- local newdata = io.loaddata(newscript)
- if newdata then
- if trace_locating then
- report_scripts("old script content replaced by new content")
- end
- io.savedata(oldscript,newdata)
- break
- elseif trace_locating then
- report_scripts("unable to load new script")
- end
- end
- end
+ cached[original]=""
+ if trace_schemes then
+ report_schemes("using missing %a, protocol %a",original,scheme)
+ end
+ end
+ loaded[scheme]=loaded[scheme]+1
+ statistics.stoptiming(schemes)
+ else
+ if trace_schemes then
+ report_schemes("reusing %a, protocol %a",original,scheme)
+ end
+ reused[scheme]=reused[scheme]+1
+ end
+ return cached[original]
+end
+local function finder(specification,filetype)
+ return resolvers.methodhandler("finders",fetch(specification),filetype)
+end
+local opener=openers.file
+local loader=loaders.file
+local function install(scheme,handler,newthreshold)
+ handlers [scheme]=handler
+ loaded [scheme]=0
+ reused [scheme]=0
+ finders [scheme]=finder
+ openers [scheme]=opener
+ loaders [scheme]=loader
+ thresholds[scheme]=newthreshold or threshold
+end
+schemes.install=install
+local function http_handler(specification,cachename)
+ local tempname=cachename..".tmp"
+ local f=io.open(tempname,"wb")
+ local status,message=http.request {
+ url=specification.original,
+ sink=ltn12.sink.file(f)
+ }
+ if not status then
+ os.remove(tempname)
+ else
+ os.remove(cachename)
+ os.rename(tempname,cachename)
+ end
+ return cachename
+end
+install('http',http_handler)
+install('https')
+install('ftp')
+statistics.register("scheme handling time",function()
+ local l,r,nl,nr={},{},0,0
+ for k,v in table.sortedhash(loaded) do
+ if v>0 then
+ nl=nl+1
+ l[nl]=k..":"..v
+ end
+ end
+ for k,v in table.sortedhash(reused) do
+ if v>0 then
+ nr=nr+1
+ r[nr]=k..":"..v
+ end
+ end
+ local n=nl+nr
+ if n>0 then
+ l=nl>0 and concat(l) or "none"
+ r=nr>0 and concat(r) or "none"
+ return format("%s seconds, %s processed, threshold %s seconds, loaded: %s, reused: %s",
+ statistics.elapsedtime(schemes),n,threshold,l,r)
+ else
+ return nil
+ end
+end)
+local httprequest=http.request
+local toquery=url.toquery
+local function fetchstring(url,data)
+ local q=data and toquery(data)
+ if q then
+ url=url.."?"..q
+ end
+ local reply=httprequest(url)
+ return reply
+end
+schemes.fetchstring=fetchstring
+function schemes.fetchtable(url,data)
+ local reply=fetchstring(url,data)
+ if reply then
+ local s=load("return "..reply)
+ if s then
+ return s()
end
+ end
end
@@ -15312,78 +15069,198 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['data-tmf'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local resolvers = resolvers
+package.loaded["data-lua"] = package.loaded["data-lua"] or true
-local report_tds = logs.reporter("resolvers","tds")
+-- original size: 4861, stripped down to: 3693
--- = <<
--- ? ??
--- < +=
--- > =+
+if not modules then modules={} end modules ['data-lua']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local resolvers,package=resolvers,package
+local gsub=string.gsub
+local concat=table.concat
+local addsuffix=file.addsuffix
+local P,S,Cs,lpegmatch=lpeg.P,lpeg.S,lpeg.Cs,lpeg.match
+local libsuffixes={ 'tex','lua' }
+local clibsuffixes={ 'lib' }
+local libformats={ 'TEXINPUTS','LUAINPUTS' }
+local clibformats={ 'CLUAINPUTS' }
+local helpers=package.helpers
+trackers.register("resolvers.libraries",function(v) helpers.trace=v end)
+trackers.register("resolvers.locating",function(v) helpers.trace=v end)
+helpers.report=logs.reporter("resolvers","libraries")
+local pattern=Cs(P("!")^0/""*(P("/")*P(-1)/"/"+P("/")^1/"/"+1)^0)
+local function cleanpath(path)
+ return resolvers.resolve(lpegmatch(pattern,path))
+end
+helpers.cleanpath=cleanpath
+local loadedaslib=helpers.loadedaslib
+local loadedbylua=helpers.loadedbylua
+local loadedbypath=helpers.loadedbypath
+local notloaded=helpers.notloaded
+local getlibpaths=package.libpaths
+local getclibpaths=package.clibpaths
+function helpers.libpaths(libhash)
+ local libpaths={}
+ for i=1,#libformats do
+ local paths=resolvers.expandedpathlistfromvariable(libformats[i])
+ for i=1,#paths do
+ local path=cleanpath(paths[i])
+ if not libhash[path] then
+ libpaths[#libpaths+1]=path
+ libhash[path]=true
+ end
+ end
+ end
+ return libpaths
+end
+function helpers.clibpaths(clibhash)
+ local clibpaths={}
+ for i=1,#clibformats do
+ local paths=resolvers.expandedpathlistfromvariable(clibformats[i])
+ for i=1,#paths do
+ local path=cleanpath(paths[i])
+ if not clibhash[path] then
+ clibpaths[#clibpaths+1]=path
+ clibhash[path]=true
+ end
+ end
+ end
+ return clibpaths
+end
+local function loadedbyformat(name,rawname,suffixes,islib)
+ local trace=helpers.trace
+ local report=helpers.report
+ if trace then
+ report("locating %a as %a using formats %a",rawname,name,suffixes)
+ end
+ for i=1,#suffixes do
+ local format=suffixes[i]
+ local resolved=resolvers.findfile(name,format) or ""
+ if trace then
+ report("checking %a using format %a",name,format)
+ end
+ if resolved~="" then
+ if trace then
+ report("lib %a located on %a",name,resolved)
+ end
+ if islib then
+ return true,loadedaslib(resolved,rawname)
+ else
+ return true,loadfile(resolved)
+ end
+ end
+ end
+end
+helpers.loadedbyformat=loadedbyformat
+local pattern=Cs((((1-S("\\/"))^0*(S("\\/")^1/"/"))^0*(P(".")^1/"/"+P(1))^1)*-1)
+local function lualibfile(name)
+ return lpegmatch(pattern,name) or name
+end
+helpers.lualibfile=lualibfile
+function helpers.loaded(name)
+ local thename=lualibfile(name)
+ local luaname=addsuffix(thename,"lua")
+ local libname=addsuffix(thename,os.libsuffix)
+ local libpaths=getlibpaths()
+ local clibpaths=getclibpaths()
+ local done,result=loadedbyformat(luaname,name,libsuffixes,false)
+ if done then
+ return result
+ end
+ local done,result=loadedbyformat(libname,name,clibsuffixes,true)
+ if done then
+ return result
+ end
+ local done,result=loadedbypath(luaname,name,libpaths,false,"lua")
+ if done then
+ return result
+ end
+ local done,result=loadedbypath(luaname,name,clibpaths,false,"lua")
+ if done then
+ return result
+ end
+ local done,result=loadedbypath(libname,name,clibpaths,true,"lib")
+ if done then
+ return result
+ end
+ local done,result=loadedbylua(name)
+ if done then
+ return result
+ end
+ return notloaded(name)
+end
+resolvers.loadlualib=require
-function resolvers.load_tree(tree,resolve)
- if type(tree) == "string" and tree ~= "" then
- local getenv, setenv = resolvers.getenv, resolvers.setenv
+end -- of closure
- -- later might listen to the raw osenv var as well
- local texos = "texmf-" .. os.platform
+do -- create closure to overcome 200 locals limit
- local oldroot = environment.texroot
- local newroot = file.collapsepath(tree)
+package.loaded["data-aux"] = package.loaded["data-aux"] or true
- local newtree = file.join(newroot,texos)
- local newpath = file.join(newtree,"bin")
+-- original size: 2394, stripped down to: 2005
- if not lfs.isdir(newtree) then
- report_tds("no '%s' under tree %s",texos,tree)
- os.exit()
+if not modules then modules={} end modules ['data-aux']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local find=string.find
+local type,next=type,next
+local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end)
+local resolvers=resolvers
+local report_scripts=logs.reporter("resolvers","scripts")
+function resolvers.updatescript(oldname,newname)
+ local scriptpath="scripts/context/lua"
+ newname=file.addsuffix(newname,"lua")
+ local oldscript=resolvers.cleanpath(oldname)
+ if trace_locating then
+ report_scripts("to be replaced old script %a",oldscript)
+ end
+ local newscripts=resolvers.findfiles(newname) or {}
+ if #newscripts==0 then
+ if trace_locating then
+ report_scripts("unable to locate new script")
+ end
+ else
+ for i=1,#newscripts do
+ local newscript=resolvers.cleanpath(newscripts[i])
+ if trace_locating then
+ report_scripts("checking new script %a",newscript)
+ end
+ if oldscript==newscript then
+ if trace_locating then
+ report_scripts("old and new script are the same")
end
- if not lfs.isdir(newpath) then
- report_tds("no '%s/bin' under tree %s",texos,tree)
- os.exit()
+ elseif not find(newscript,scriptpath) then
+ if trace_locating then
+ report_scripts("new script should come from %a",scriptpath)
end
-
- local texmfos = newtree
-
- environment.texroot = newroot
- environment.texos = texos
- environment.texmfos = texmfos
-
- -- Beware, we need to obey the relocatable autoparent so we
- -- set TEXMFCNF to its raw value. This is somewhat tricky when
- -- we run a mkii job from within. Therefore, in mtxrun, there
- -- is a resolve applied when we're in mkii/kpse mode or when
- -- --resolve is passed to mtxrun. Maybe we should also set the
- -- local AUTOPARENT etc. although these are alwasy set new.
-
- if resolve then
- -- resolvers.luacnfspec = resolvers.joinpath(resolvers.resolve(resolvers.expandedpathfromlist(resolvers.splitpath(resolvers.luacnfspec))))
- resolvers.luacnfspec = resolvers.resolve(resolvers.luacnfspec)
+ elseif not (find(oldscript,file.removesuffix(newname).."$") or find(oldscript,newname.."$")) then
+ if trace_locating then
+ report_scripts("invalid new script name")
+ end
+ else
+ local newdata=io.loaddata(newscript)
+ if newdata then
+ if trace_locating then
+ report_scripts("old script content replaced by new content")
+ end
+ io.savedata(oldscript,newdata)
+ break
+ elseif trace_locating then
+ report_scripts("unable to load new script")
end
-
- setenv('SELFAUTOPARENT', newroot)
- setenv('SELFAUTODIR', newtree)
- setenv('SELFAUTOLOC', newpath)
- setenv('TEXROOT', newroot)
- setenv('TEXOS', texos)
- setenv('TEXMFOS', texmfos)
- setenv('TEXMFCNF', resolvers.luacnfspec,true) -- already resolved
- setenv('PATH', newpath .. io.pathseparator .. getenv('PATH'))
-
- report_tds("changing from root '%s' to '%s'",oldroot,newroot)
- report_tds("prepending '%s' to PATH",newpath)
- report_tds("setting TEXMFCNF to '%s'",resolvers.luacnfspec)
- report_tds()
+ end
end
+ end
end
@@ -15391,81 +15268,132 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['data-lst'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
+package.loaded["data-tmf"] = package.loaded["data-tmf"] or true
+
+-- original size: 2600, stripped down to: 1627
+
+if not modules then modules={} end modules ['data-tmf']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
}
+local resolvers=resolvers
+local report_tds=logs.reporter("resolvers","tds")
+function resolvers.load_tree(tree,resolve)
+ if type(tree)=="string" and tree~="" then
+ local getenv,setenv=resolvers.getenv,resolvers.setenv
+ local texos="texmf-"..os.platform
+ local oldroot=environment.texroot
+ local newroot=file.collapsepath(tree)
+ local newtree=file.join(newroot,texos)
+ local newpath=file.join(newtree,"bin")
+ if not lfs.isdir(newtree) then
+ report_tds("no %a under tree %a",texos,tree)
+ os.exit()
+ end
+ if not lfs.isdir(newpath) then
+ report_tds("no '%s/bin' under tree %a",texos,tree)
+ os.exit()
+ end
+ local texmfos=newtree
+ environment.texroot=newroot
+ environment.texos=texos
+ environment.texmfos=texmfos
+ if resolve then
+ resolvers.luacnfspec=resolvers.resolve(resolvers.luacnfspec)
+ end
+ setenv('SELFAUTOPARENT',newroot)
+ setenv('SELFAUTODIR',newtree)
+ setenv('SELFAUTOLOC',newpath)
+ setenv('TEXROOT',newroot)
+ setenv('TEXOS',texos)
+ setenv('TEXMFOS',texmfos)
+ setenv('TEXMFCNF',resolvers.luacnfspec,true)
+ setenv('PATH',newpath..io.pathseparator..getenv('PATH'))
+ report_tds("changing from root %a to %a",oldroot,newroot)
+ report_tds("prepending %a to PATH",newpath)
+ report_tds("setting TEXMFCNF to %a",resolvers.luacnfspec)
+ report_tds()
+ end
+end
--- used in mtxrun, can be loaded later .. todo
-local find, concat, upper, format = string.find, table.concat, string.upper, string.format
-local fastcopy, sortedpairs = table.fastcopy, table.sortedpairs
+end -- of closure
-resolvers.listers = resolvers.listers or { }
+do -- create closure to overcome 200 locals limit
-local resolvers = resolvers
+package.loaded["data-lst"] = package.loaded["data-lst"] or true
-local report_lists = logs.reporter("resolvers","lists")
+-- original size: 2654, stripped down to: 2301
+if not modules then modules={} end modules ['data-lst']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local find,concat,upper,format=string.find,table.concat,string.upper,string.format
+local fastcopy,sortedpairs=table.fastcopy,table.sortedpairs
+resolvers.listers=resolvers.listers or {}
+local resolvers=resolvers
+local report_lists=logs.reporter("resolvers","lists")
local function tabstr(str)
- if type(str) == 'table' then
- return concat(str," | ")
- else
- return str
- end
+ if type(str)=='table' then
+ return concat(str," | ")
+ else
+ return str
+ end
end
-
function resolvers.listers.variables(pattern)
- local instance = resolvers.instance
- local environment = instance.environment
- local variables = instance.variables
- local expansions = instance.expansions
- local pattern = upper(pattern or "")
- local configured = { }
- local order = instance.order
- for i=1,#order do
- for k, v in next, order[i] do
- if v ~= nil and configured[k] == nil then
- configured[k] = v
- end
- end
- end
- local env = fastcopy(environment)
- local var = fastcopy(variables)
- local exp = fastcopy(expansions)
- for key, value in sortedpairs(configured) do
- if key ~= "" and (pattern == "" or find(upper(key),pattern)) then
- report_lists(key)
- report_lists(" env: %s",tabstr(rawget(environment,key)) or "unset")
- report_lists(" var: %s",tabstr(configured[key]) or "unset")
- report_lists(" exp: %s",tabstr(expansions[key]) or "unset")
- report_lists(" res: %s",tabstr(resolvers.resolve(expansions[key])) or "unset")
- end
- end
- instance.environment = fastcopy(env)
- instance.variables = fastcopy(var)
- instance.expansions = fastcopy(exp)
-end
-
-function resolvers.listers.configurations(report)
- local configurations = resolvers.instance.specification
- local report = report or texio.write_nl
- for i=1,#configurations do
- report(format("file : %s",resolvers.resolve(configurations[i])))
- end
- report("")
- local list = resolvers.expandedpathfromlist(resolvers.splitpath(resolvers.luacnfspec))
- for i=1,#list do
- local li = resolvers.resolve(list[i])
- if lfs.isdir(li) then
- report(format("path - %s",li))
- else
- report(format("path + %s",li))
- end
+ local instance=resolvers.instance
+ local environment=instance.environment
+ local variables=instance.variables
+ local expansions=instance.expansions
+ local pattern=upper(pattern or "")
+ local configured={}
+ local order=instance.order
+ for i=1,#order do
+ for k,v in next,order[i] do
+ if v~=nil and configured[k]==nil then
+ configured[k]=v
+ end
+ end
+ end
+ local env=fastcopy(environment)
+ local var=fastcopy(variables)
+ local exp=fastcopy(expansions)
+ for key,value in sortedpairs(configured) do
+ if key~="" and (pattern=="" or find(upper(key),pattern)) then
+ report_lists(key)
+ report_lists(" env: %s",tabstr(rawget(environment,key)) or "unset")
+ report_lists(" var: %s",tabstr(configured[key]) or "unset")
+ report_lists(" exp: %s",tabstr(expansions[key]) or "unset")
+ report_lists(" res: %s",tabstr(resolvers.resolve(expansions[key])) or "unset")
+ end
+ end
+ instance.environment=fastcopy(env)
+ instance.variables=fastcopy(var)
+ instance.expansions=fastcopy(exp)
+end
+local report_resolved=logs.reporter("system","resolved")
+function resolvers.listers.configurations()
+ local configurations=resolvers.instance.specification
+ for i=1,#configurations do
+ report_resolved("file : %s",resolvers.resolve(configurations[i]))
+ end
+ report_resolved("")
+ local list=resolvers.expandedpathfromlist(resolvers.splitpath(resolvers.luacnfspec))
+ for i=1,#list do
+ local li=resolvers.resolve(list[i])
+ if lfs.isdir(li) then
+ report_resolved("path - %s",li)
+ else
+ report_resolved("path + %s",li)
end
+ end
end
@@ -15473,279 +15401,407 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['luat-sta'] = {
- version = 1.001,
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
+package.loaded["util-lib"] = package.loaded["util-lib"] or true
--- this code is used in the updater
+-- original size: 8911, stripped down to: 4216
-local gmatch, match = string.gmatch, string.match
-local type = type
+if not modules then modules={} end modules ['util-lib']={
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files",
+}
+local gsub,find=string.gsub,string.find
+local pathpart,nameonly,joinfile=file.pathpart,file.nameonly,file.join
+local findfile,findfiles=resolvers and resolvers.findfile,resolvers and resolvers.findfiles
+local loaded=package.loaded
+local report_swiglib=logs.reporter("swiglib")
+local trace_swiglib=false trackers.register("resolvers.swiglib",function(v) trace_swiglib=v end)
+local function requireswiglib(required,version)
+ local library=loaded[required]
+ if library==nil then
+ local required_full=gsub(required,"%.","/")
+ local required_path=pathpart(required_full)
+ local required_base=nameonly(required_full)
+ local required_name=required_base.."."..os.libsuffix
+ local version=type(version)=="string" and version~="" and version or false
+ local function check(locate,...)
+ local found_library=nil
+ if version then
+ local asked_library=joinfile(required_path,version,required_name)
+ if trace_swiglib then
+ report_swiglib("checking %s: %a","with version",asked_library)
+ end
+ found_library=locate(asked_library,...)
+ if not found_library or found_library==""then
+ asked_library=joinfile(required_path,required_name)
+ if trace_swiglib then
+ report_swiglib("checking %s: %a","without version",asked_library)
+ end
+ found_library=locate(asked_library,...)
+ end
+ else
+ local asked_library=joinfile(required_path,required_name)
+ if trace_swiglib then
+ report_swiglib("checking %s: %a","without version",asked_library)
+ end
+ found_library=locate(asked_library,...)
+ end
+ return found_library and found_library~="" and found_library or false
+ end
+ local found_library=findfile and check(findfile,"lib")
+ if findfiles and not found_library then
+ local asked_library=joinfile(required_path,".*",required_name)
+ if trace_swiglib then
+ report_swiglib("checking %s: %a","latest version",asked_library)
+ end
+ local list=findfiles(asked_library,"lib",true)
+ if list and #list>0 then
+ table.sort(list)
+ found_library=list[#list]
+ end
+ end
+ if not found_library then
+ package.extraclibpath(environment.ownpath)
+ local paths=package.clibpaths()
+ for i=1,#paths do
+ local found_library=check(lfs.isfile)
+ if found_library then
+ break
+ end
+ end
+ end
+ if not found_library then
+ if trace_swiglib then
+ report_swiglib("not found: %a",asked_library)
+ end
+ library=false
+ else
+ local path=pathpart(found_library)
+ local base=nameonly(found_library)
+ dir.push(path)
+ if trace_swiglib then
+ report_swiglib("found: %a",found_library)
+ end
+ library=package.loadlib(found_library,"luaopen_"..required_base)
+ if type(library)=="function" then
+ library=library()
+ else
+ library=false
+ end
+ dir.pop()
+ end
+ if not library then
+ report_swiglib("unknown: %a",required)
+ elseif trace_swiglib then
+ report_swiglib("stored: %a",required)
+ end
+ loaded[required]=library
+ else
+ report_swiglib("reused: %a",required)
+ end
+ return library
+end
+local savedrequire=require
+function require(name,version)
+ if find(name,"^swiglib%.") then
+ return requireswiglib(name,version)
+ else
+ return savedrequire(name)
+ end
+end
+local swiglibs={}
+function swiglib(name,version)
+ local library=swiglibs[name]
+ if not library then
+ statistics.starttiming(swiglibs)
+ report_swiglib("loading %a",name)
+ library=requireswiglib("swiglib."..name,version)
+ swiglibs[name]=library
+ statistics.stoptiming(swiglibs)
+ end
+ return library
+end
+statistics.register("used swiglibs",function()
+ if next(swiglibs) then
+ return string.format("%s, initial load time %s seconds",table.concat(table.sortedkeys(swiglibs)," "),statistics.elapsedtime(swiglibs))
+ end
+end)
-states = states or { }
-local states = states
-states.data = states.data or { }
-local data = states.data
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
-states.hash = states.hash or { }
-local hash = states.hash
+package.loaded["luat-sta"] = package.loaded["luat-sta"] or true
-states.tag = states.tag or ""
-states.filename = states.filename or ""
+-- original size: 5703, stripped down to: 2507
+if not modules then modules={} end modules ['luat-sta']={
+ version=1.001,
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local gmatch,match=string.gmatch,string.match
+local type=type
+states=states or {}
+local states=states
+states.data=states.data or {}
+local data=states.data
+states.hash=states.hash or {}
+local hash=states.hash
+states.tag=states.tag or ""
+states.filename=states.filename or ""
function states.save(filename,tag)
- tag = tag or states.tag
- filename = file.addsuffix(filename or states.filename,'lus')
- io.savedata(filename,
- "-- generator : luat-sta.lua\n" ..
- "-- state tag : " .. tag .. "\n\n" ..
- table.serialize(data[tag or states.tag] or {},true)
- )
+ tag=tag or states.tag
+ filename=file.addsuffix(filename or states.filename,'lus')
+ io.savedata(filename,
+ "-- generator : luat-sta.lua\n".."-- state tag : "..tag.."\n\n"..table.serialize(data[tag or states.tag] or {},true)
+ )
end
-
function states.load(filename,tag)
- states.filename = filename
- states.tag = tag or "whatever"
- states.filename = file.addsuffix(states.filename,'lus')
- data[states.tag], hash[states.tag] = (io.exists(filename) and dofile(filename)) or { }, { }
+ states.filename=filename
+ states.tag=tag or "whatever"
+ states.filename=file.addsuffix(states.filename,'lus')
+ data[states.tag],hash[states.tag]=(io.exists(filename) and dofile(filename)) or {},{}
end
-
local function set_by_tag(tag,key,value,default,persistent)
- local d, h = data[tag], hash[tag]
- if d then
- if type(d) == "table" then
- local dkey, hkey = key, key
- local pre, post = match(key,"(.+)%.([^%.]+)$")
- if pre and post then
- for k in gmatch(pre,"[^%.]+") do
- local dk = d[k]
- if not dk then
- dk = { }
- d[k] = dk
- elseif type(dk) == "string" then
- -- invalid table, unable to upgrade structure
- -- hope for the best or delete the state file
- break
- end
- d = dk
- end
- dkey, hkey = post, key
- end
- if value == nil then
- value = default
- elseif value == false then
- -- special case
- elseif persistent then
- value = value or d[dkey] or default
- else
- value = value or default
- end
- d[dkey], h[hkey] = value, value
- elseif type(d) == "string" then
- -- weird
- data[tag], hash[tag] = value, value
- end
- end
+ local d,h=data[tag],hash[tag]
+ if d then
+ if type(d)=="table" then
+ local dkey,hkey=key,key
+ local pre,post=match(key,"(.+)%.([^%.]+)$")
+ if pre and post then
+ for k in gmatch(pre,"[^%.]+") do
+ local dk=d[k]
+ if not dk then
+ dk={}
+ d[k]=dk
+ elseif type(dk)=="string" then
+ break
+ end
+ d=dk
+ end
+ dkey,hkey=post,key
+ end
+ if value==nil then
+ value=default
+ elseif value==false then
+ elseif persistent then
+ value=value or d[dkey] or default
+ else
+ value=value or default
+ end
+ d[dkey],h[hkey]=value,value
+ elseif type(d)=="string" then
+ data[tag],hash[tag]=value,value
+ end
+ end
end
-
local function get_by_tag(tag,key,default)
- local h = hash[tag]
- if h and h[key] then
- return h[key]
- else
- local d = data[tag]
- if d then
- for k in gmatch(key,"[^%.]+") do
- local dk = d[k]
- if dk ~= nil then
- d = dk
- else
- return default
- end
- end
- if d == false then
- return false
- else
- return d or default
- end
+ local h=hash[tag]
+ if h and h[key] then
+ return h[key]
+ else
+ local d=data[tag]
+ if d then
+ for k in gmatch(key,"[^%.]+") do
+ local dk=d[k]
+ if dk~=nil then
+ d=dk
+ else
+ return default
end
+ end
+ if d==false then
+ return false
+ else
+ return d or default
+ end
end
+ end
end
-
-states.set_by_tag = set_by_tag
-states.get_by_tag = get_by_tag
-
+states.set_by_tag=set_by_tag
+states.get_by_tag=get_by_tag
function states.set(key,value,default,persistent)
- set_by_tag(states.tag,key,value,default,persistent)
+ set_by_tag(states.tag,key,value,default,persistent)
end
-
function states.get(key,default)
- return get_by_tag(states.tag,key,default)
+ return get_by_tag(states.tag,key,default)
end
-
-
-
end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['luat-fmt'] = {
- version = 1.001,
- comment = "companion to mtxrun",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-
-local format = string.format
-
-local report_format = logs.reporter("resolvers","formats")
-
--- helper for mtxrun
+package.loaded["luat-fmt"] = package.loaded["luat-fmt"] or true
-local quoted = string.quoted
+-- original size: 5951, stripped down to: 4922
-local function primaryflags() -- not yet ok
- local trackers = environment.argument("trackers")
- local directives = environment.argument("directives")
- local flags = ""
- if trackers and trackers ~= "" then
- flags = flags .. "--trackers=" .. quoted(trackers)
- end
- if directives and directives ~= "" then
- flags = flags .. "--directives=" .. quoted(directives)
- end
- return flags
+if not modules then modules={} end modules ['luat-fmt']={
+ version=1.001,
+ comment="companion to mtxrun",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local format=string.format
+local concat=table.concat
+local quoted=string.quoted
+local luasuffixes=utilities.lua.suffixes
+local report_format=logs.reporter("resolvers","formats")
+local function primaryflags()
+ local trackers=environment.argument("trackers")
+ local directives=environment.argument("directives")
+ local flags={}
+ if trackers and trackers~="" then
+ flags={ "--trackers="..quoted(trackers) }
+ end
+ if directives and directives~="" then
+ flags={ "--directives="..quoted(directives) }
+ end
+ if environment.argument("jit") then
+ flags={ "--jiton" }
+ end
+ return concat(flags," ")
end
-
function environment.make_format(name)
- -- change to format path (early as we need expanded paths)
- local olddir = lfs.currentdir()
- local path = caches.getwritablepath("formats") or "" -- maybe platform
- if path ~= "" then
- lfs.chdir(path)
- end
- report_format("format path: %s",lfs.currentdir())
- -- check source file
- local texsourcename = file.addsuffix(name,"mkiv")
- local fulltexsourcename = resolvers.findfile(texsourcename,"tex") or ""
- if fulltexsourcename == "" then
- texsourcename = file.addsuffix(name,"tex")
- fulltexsourcename = resolvers.findfile(texsourcename,"tex") or ""
- end
- if fulltexsourcename == "" then
- report_format("no tex source file with name: %s (mkiv or tex)",name)
- lfs.chdir(olddir)
- return
- else
- report_format("using tex source file: %s",fulltexsourcename)
- end
- local texsourcepath = dir.expandname(file.dirname(fulltexsourcename)) -- really needed
- -- check specification
- local specificationname = file.replacesuffix(fulltexsourcename,"lus")
- local fullspecificationname = resolvers.findfile(specificationname,"tex") or ""
- if fullspecificationname == "" then
- specificationname = file.join(texsourcepath,"context.lus")
- fullspecificationname = resolvers.findfile(specificationname,"tex") or ""
- end
- if fullspecificationname == "" then
- report_format("unknown stub specification: %s",specificationname)
- lfs.chdir(olddir)
- return
- end
- local specificationpath = file.dirname(fullspecificationname)
- -- load specification
- local usedluastub = nil
- local usedlualibs = dofile(fullspecificationname)
- if type(usedlualibs) == "string" then
- usedluastub = file.join(file.dirname(fullspecificationname),usedlualibs)
- elseif type(usedlualibs) == "table" then
- report_format("using stub specification: %s",fullspecificationname)
- local texbasename = file.basename(name)
- local luastubname = file.addsuffix(texbasename,"lua")
- local lucstubname = file.addsuffix(texbasename,"luc")
- -- pack libraries in stub
- report_format("creating initialization file: %s",luastubname)
- utilities.merger.selfcreate(usedlualibs,specificationpath,luastubname)
- -- compile stub file (does not save that much as we don't use this stub at startup any more)
- local strip = resolvers.booleanvariable("LUACSTRIP", true)
- if utilities.lua.compile(luastubname,lucstubname) and lfs.isfile(lucstubname) then
- report_format("using compiled initialization file: %s",lucstubname)
- usedluastub = lucstubname
- else
- report_format("using uncompiled initialization file: %s",luastubname)
- usedluastub = luastubname
- end
+ local engine=environment.ownmain or "luatex"
+ local olddir=dir.current()
+ local path=caches.getwritablepath("formats",engine) or ""
+ if path~="" then
+ lfs.chdir(path)
+ end
+ report_format("using format path %a",dir.current())
+ local texsourcename=file.addsuffix(name,"mkiv")
+ local fulltexsourcename=resolvers.findfile(texsourcename,"tex") or ""
+ if fulltexsourcename=="" then
+ texsourcename=file.addsuffix(name,"tex")
+ fulltexsourcename=resolvers.findfile(texsourcename,"tex") or ""
+ end
+ if fulltexsourcename=="" then
+ report_format("no tex source file with name %a (mkiv or tex)",name)
+ lfs.chdir(olddir)
+ return
+ else
+ report_format("using tex source file %a",fulltexsourcename)
+ end
+ local texsourcepath=dir.expandname(file.dirname(fulltexsourcename))
+ local specificationname=file.replacesuffix(fulltexsourcename,"lus")
+ local fullspecificationname=resolvers.findfile(specificationname,"tex") or ""
+ if fullspecificationname=="" then
+ specificationname=file.join(texsourcepath,"context.lus")
+ fullspecificationname=resolvers.findfile(specificationname,"tex") or ""
+ end
+ if fullspecificationname=="" then
+ report_format("unknown stub specification %a",specificationname)
+ lfs.chdir(olddir)
+ return
+ end
+ local specificationpath=file.dirname(fullspecificationname)
+ local usedluastub=nil
+ local usedlualibs=dofile(fullspecificationname)
+ if type(usedlualibs)=="string" then
+ usedluastub=file.join(file.dirname(fullspecificationname),usedlualibs)
+ elseif type(usedlualibs)=="table" then
+ report_format("using stub specification %a",fullspecificationname)
+ local texbasename=file.basename(name)
+ local luastubname=file.addsuffix(texbasename,luasuffixes.lua)
+ local lucstubname=file.addsuffix(texbasename,luasuffixes.luc)
+ report_format("creating initialization file %a",luastubname)
+ utilities.merger.selfcreate(usedlualibs,specificationpath,luastubname)
+ if utilities.lua.compile(luastubname,lucstubname) and lfs.isfile(lucstubname) then
+ report_format("using compiled initialization file %a",lucstubname)
+ usedluastub=lucstubname
else
- report_format("invalid stub specification: %s",fullspecificationname)
- lfs.chdir(olddir)
- return
- end
- -- generate format
- local command = format("luatex --ini %s --lua=%s %s %sdump",primaryflags(),quoted(usedluastub),quoted(fulltexsourcename),os.platform == "unix" and "\\\\" or "\\")
- report_format("running command: %s\n",command)
- os.spawn(command)
- -- remove related mem files
- local pattern = file.removesuffix(file.basename(usedluastub)).."-*.mem"
- -- report_format("removing related mplib format with pattern '%s'", pattern)
- local mp = dir.glob(pattern)
- if mp then
- for i=1,#mp do
- local name = mp[i]
- report_format("removing related mplib format %s", file.basename(name))
- os.remove(name)
- end
+ report_format("using uncompiled initialization file %a",luastubname)
+ usedluastub=luastubname
end
+ else
+ report_format("invalid stub specification %a",fullspecificationname)
lfs.chdir(olddir)
+ return
+ end
+ local command=format("%s --ini %s --lua=%s %s %sdump",engine,primaryflags(),quoted(usedluastub),quoted(fulltexsourcename),os.platform=="unix" and "\\\\" or "\\")
+ report_format("running command: %s\n",command)
+ os.spawn(command)
+ local pattern=file.removesuffix(file.basename(usedluastub)).."-*.mem"
+ local mp=dir.glob(pattern)
+ if mp then
+ for i=1,#mp do
+ local name=mp[i]
+ report_format("removing related mplib format %a",file.basename(name))
+ os.remove(name)
+ end
+ end
+ lfs.chdir(olddir)
end
-
function environment.run_format(name,data,more)
- -- hm, rather old code here; we can now use the file.whatever functions
- if name and name ~= "" then
- local barename = file.removesuffix(name)
- local fmtname = caches.getfirstreadablefile(file.addsuffix(barename,"fmt"),"formats")
- if fmtname == "" then
- fmtname = resolvers.findfile(file.addsuffix(barename,"fmt")) or ""
- end
- fmtname = resolvers.cleanpath(fmtname)
- if fmtname == "" then
- report_format("no format with name: %s",name)
- else
- local barename = file.removesuffix(name) -- expanded name
- local luaname = file.addsuffix(barename,"luc")
- if not lfs.isfile(luaname) then
- luaname = file.addsuffix(barename,"lua")
- end
- if not lfs.isfile(luaname) then
- report_format("using format name: %s",fmtname)
- report_format("no luc/lua with name: %s",barename)
- else
- local command = format("luatex %s --fmt=%s --lua=%s %s %s",primaryflags(),quoted(barename),quoted(luaname),quoted(data),more ~= "" and quoted(more) or "")
- report_format("running command: %s",command)
- os.spawn(command)
- end
- end
+ if name and name~="" then
+ local engine=environment.ownmain or "luatex"
+ local barename=file.removesuffix(name)
+ local fmtname=caches.getfirstreadablefile(file.addsuffix(barename,"fmt"),"formats",engine)
+ if fmtname=="" then
+ fmtname=resolvers.findfile(file.addsuffix(barename,"fmt")) or ""
+ end
+ fmtname=resolvers.cleanpath(fmtname)
+ if fmtname=="" then
+ report_format("no format with name %a",name)
+ else
+ local barename=file.removesuffix(name)
+ local luaname=file.addsuffix(barename,"luc")
+ if not lfs.isfile(luaname) then
+ luaname=file.addsuffix(barename,"lua")
+ end
+ if not lfs.isfile(luaname) then
+ report_format("using format name %a",fmtname)
+ report_format("no luc/lua file with name %a",barename)
+ else
+ local command=format("%s %s --fmt=%s --lua=%s %s %s",engine,primaryflags(),quoted(barename),quoted(luaname),quoted(data),more~="" and quoted(more) or "")
+ report_format("running command: %s",command)
+ os.spawn(command)
+ end
end
+ end
end
end -- of closure
+
+-- used libraries : l-lua.lua l-lpeg.lua l-function.lua l-string.lua l-table.lua l-io.lua l-number.lua l-set.lua l-os.lua l-file.lua l-md5.lua l-url.lua l-dir.lua l-boolean.lua l-unicode.lua l-math.lua util-str.lua util-tab.lua util-sto.lua util-prs.lua util-fmt.lua trac-set.lua trac-log.lua trac-inf.lua trac-pro.lua util-lua.lua util-deb.lua util-mrg.lua util-tpl.lua util-env.lua luat-env.lua lxml-tab.lua lxml-lpt.lua lxml-mis.lua lxml-aux.lua lxml-xml.lua trac-xml.lua data-ini.lua data-exp.lua data-env.lua data-tmp.lua data-met.lua data-res.lua data-pre.lua data-inp.lua data-out.lua data-fil.lua data-con.lua data-use.lua data-zip.lua data-tre.lua data-sch.lua data-lua.lua data-aux.lua data-tmf.lua data-lst.lua util-lib.lua luat-sta.lua luat-fmt.lua
+-- skipped libraries : -
+-- original bytes : 658276
+-- stripped bytes : 241564
+
-- end library merge
-own = { } -- not local, might change
+-- We need this hack till luatex is fixed.
+--
+-- for k,v in pairs(arg) do print(k,v) end
+
+if arg and (arg[0] == 'luatex' or arg[0] == 'luatex.exe') and arg[1] == "--luaonly" then
+ arg[-1]=arg[0] arg[0]=arg[2] for k=3,#arg do arg[k-2]=arg[k] end arg[#arg]=nil arg[#arg]=nil
+end
+
+-- End of hack.
+
+local format, gsub, gmatch, match, find = string.format, string.gsub, string.gmatch, string.match, string.find
+local concat = table.concat
+
+local ownname = environment and environment.ownname or arg[0] or 'mtxrun.lua'
+local ownpath = gsub(match(ownname,"^(.+)[\\/].-$") or ".","\\","/")
+local owntree = environment and environment.ownpath or ownpath
-own.libs = { -- order can be made better
+local ownlibs = { -- order can be made better
+ 'l-lua.lua',
+ 'l-lpeg.lua',
+ 'l-function.lua',
'l-string.lua',
'l-table.lua',
- 'l-lpeg.lua',
'l-io.lua',
'l-number.lua',
'l-set.lua',
@@ -15758,19 +15814,23 @@ own.libs = { -- order can be made better
'l-unicode.lua',
'l-math.lua',
+ 'util-str.lua', -- code might move to l-string
'util-tab.lua',
'util-sto.lua',
- 'util-mrg.lua',
- 'util-lua.lua',
'util-prs.lua',
'util-fmt.lua',
- 'util-deb.lua',
- 'trac-inf.lua',
'trac-set.lua',
'trac-log.lua',
- 'trac-pro.lua',
+ 'trac-inf.lua', -- was before trac-set
+ 'trac-pro.lua', -- not really needed
+ 'util-lua.lua', -- indeed here?
+ 'util-deb.lua',
+
+ 'util-mrg.lua',
+ 'util-tpl.lua',
+ 'util-env.lua',
'luat-env.lua', -- can come before inf (as in mkiv)
'lxml-tab.lua',
@@ -15780,6 +15840,8 @@ own.libs = { -- order can be made better
'lxml-aux.lua',
'lxml-xml.lua',
+ 'trac-xml.lua',
+
'data-ini.lua',
'data-exp.lua',
'data-env.lua',
@@ -15796,35 +15858,20 @@ own.libs = { -- order can be made better
-- 'data-bin.lua',
'data-zip.lua',
'data-tre.lua',
- 'data-crl.lua',
+ 'data-sch.lua',
'data-lua.lua',
'data-aux.lua', -- updater
'data-tmf.lua',
'data-lst.lua',
+ 'util-lib.lua', -- swiglib
+
'luat-sta.lua',
'luat-fmt.lua',
-}
-
--- We need this hack till luatex is fixed.
---
--- for k,v in pairs(arg) do print(k,v) end
-
-if arg and (arg[0] == 'luatex' or arg[0] == 'luatex.exe') and arg[1] == "--luaonly" then
- arg[-1]=arg[0] arg[0]=arg[2] for k=3,#arg do arg[k-2]=arg[k] end arg[#arg]=nil arg[#arg]=nil
-end
--- End of hack.
-
-local format, gsub, gmatch, match, find = string.format, string.gsub, string.gmatch, string.match, string.find
-local concat = table.concat
-
-own.name = (environment and environment.ownname) or arg[0] or 'mtxrun.lua'
-own.path = gsub(match(own.name,"^(.+)[\\/].-$") or ".","\\","/")
-
-local ownpath, owntree = own.path, environment and environment.ownpath or own.path
+}
-own.list = {
+local ownlist = {
'.',
ownpath ,
ownpath .. "/../sources", -- HH's development path
@@ -15838,13 +15885,21 @@ own.list = {
owntree .. "/../../../texmf/tex/context/base",
}
-if own.path == "." then table.remove(own.list,1) end
+if ownpath == "." then table.remove(ownlist,1) end
+
+own = {
+ name = ownname,
+ path = ownpath,
+ tree = owntree,
+ list = ownlist,
+ libs = ownlibs,
+}
local function locate_libs()
- for l=1,#own.libs do
- local lib = own.libs[l]
- for p =1,#own.list do
- local pth = own.list[p]
+ for l=1,#ownlibs do
+ local lib = ownlibs[l]
+ for p =1,#ownlist do
+ local pth = ownlist[p]
local filename = pth .. "/" .. lib
local found = lfs.isfile(filename)
if found then
@@ -15858,8 +15913,8 @@ end
local function load_libs()
local found = locate_libs()
if found then
- for l=1,#own.libs do
- local filename = found .. "/" .. own.libs[l]
+ for l=1,#ownlibs do
+ local filename = found .. "/" .. ownlibs[l]
local codeblob = loadfile(filename)
if codeblob then
codeblob()
@@ -15933,55 +15988,85 @@ if not environment.experiments then environment.experiments = e_experiments end
local instance = resolvers.reset()
local helpinfo = [[
---script run an mtx script (lua prefered method) (--noquotes), no script gives list
---execute run a script or program (texmfstart method) (--noquotes)
---resolve resolve prefixed arguments
---ctxlua run internally (using preloaded libs)
---internal run script using built in libraries (same as --ctxlua)
---locate locate given filename in database (default) or system (--first --all --detail)
-
---autotree use texmf tree cf. env 'texmfstart_tree' or 'texmfstarttree'
---tree=pathtotree use given texmf tree (default file: 'setuptex.tmf')
---environment=name use given (tmf) environment file
---path=runpath go to given path before execution
---ifchanged=filename only execute when given file has changed (md checksum)
---iftouched=old,new only execute when given file has changed (time stamp)
-
---makestubs create stubs for (context related) scripts
---removestubs remove stubs (context related) scripts
---stubpath=binpath paths where stubs wil be written
---windows create windows (mswin) stubs
---unix create unix (linux) stubs
-
---verbose give a bit more info
---trackers=list enable given trackers
---progname=str format or backend
-
---edit launch editor with found file
---launch (--all) launch files like manuals, assumes os support
-
---timedrun run a script an time its run
---autogenerate regenerate databases if needed (handy when used to run context in an editor)
-
---usekpse use kpse as fallback (when no mkiv and cache installed, often slower)
---forcekpse force using kpse (handy when no mkiv and cache installed but less functionality)
-
---prefixes show supported prefixes
-
---generate generate file database
-
---variables show configuration variables
---configurations show configuration order
-
---expand-braces expand complex variable
---expand-path expand variable (resolve paths)
---expand-var expand variable (resolve references)
---show-path show path expansion of ...
---var-value report value of variable
---find-file report file location
---find-path report path of file
-
---pattern=str filter variables
+
+
+
+ mtxrun
+ ConTeXt TDS Runner Tool
+ 1.31
+
+
+
+
+ run an mtx script (lua prefered method) (), no script gives list
+ run a script or program (texmfstart method) ()
+ resolve prefixed arguments
+ run internally (using preloaded libs)
+ run script using built in libraries (same as )
+ locate given filename in database (default) or system ( )
+
+
+ use texmf tree cf. env texmfstart_tree or texmfstarttree
+ use given texmf tree (default file: setuptex.tmf)
+ use given (tmf) environment file
+ go to given path before execution
+ only execute when given file has changed (md checksum)
+ only execute when given file has changed (time stamp)
+
+
+ create stubs for (context related) scripts
+ remove stubs (context related) scripts
+ paths where stubs wil be written
+ create windows (mswin) stubs
+ create unix (linux) stubs
+
+
+ give a bit more info
+ enable given trackers
+ format or backend
+
+
+ launch editor with found file
+ launch files like manuals, assumes os support ()
+
+
+ run a script and time its run
+ regenerate databases if needed (handy when used to run context in an editor)
+
+
+ use kpse as fallback (when no mkiv and cache installed, often slower)
+ force using kpse (handy when no mkiv and cache installed but less functionality)
+
+
+ show supported prefixes
+
+
+ generate file database
+
+
+ show configuration variables
+ show configuration order
+
+
+ show (known) directives
+ show (known) trackers
+ show (known) experiments
+
+
+ expand complex variable
+ expand variable (resolve paths)
+ expand variable (resolve references)
+ show path expansion of ...
+ report value of variable
+ report file location
+ report path of file
+
+
+ filter variables
+
+
+
+
]]
local application = logs.application {
@@ -16093,7 +16178,8 @@ function runners.execute_script(fullname,internal,nosplit)
elseif state == 'skip' then
return true
elseif state == "run" then
- local path, name, suffix, result = file.dirname(fullname), file.basename(fullname), file.extname(fullname), ""
+ local path, name, suffix = file.splitname(fullname)
+ local result = ""
if path ~= "" then
result = fullname
elseif name then
@@ -16104,7 +16190,7 @@ function runners.execute_script(fullname,internal,nosplit)
name = gsub(name,"^script:","")
if suffix == "" and runners.registered[name] and runners.registered[name][1] then
name = runners.registered[name][1]
- suffix = file.extname(name)
+ suffix = file.suffix(name)
end
if suffix == "" then
-- loop over known suffixes
@@ -16131,7 +16217,7 @@ function runners.execute_script(fullname,internal,nosplit)
environment.ownscript = result
dofile(result)
else
- local binary = runners.applications[file.extname(result)]
+ local binary = runners.applications[file.suffix(result)]
result = string.quoted(string.unquoted(result))
-- if string.match(result,' ') and not string.match(result,"^\".*\"$") then
-- result = '"' .. result .. '"'
@@ -16324,7 +16410,7 @@ function resolvers.launch(str)
-- maybe we also need to test on mtxrun.launcher.suffix environment
-- variable or on windows consult the assoc and ftype vars and such
local launchers = runners.launchers[os.platform] if launchers then
- local suffix = file.extname(str) if suffix then
+ local suffix = file.suffix(str) if suffix then
local runner = launchers[suffix] if runner then
str = runner .. " " .. str
end
@@ -16383,7 +16469,7 @@ function runners.find_mtx_script(filename)
end
filename = file.addsuffix(filename,"lua")
local basename = file.removesuffix(file.basename(filename))
- local suffix = file.extname(filename)
+ local suffix = file.suffix(filename)
-- qualified path, raw name
local fullname = file.is_qualified_path(filename) and io.exists(filename) and filename
if fullname and fullname ~= "" then
@@ -16438,7 +16524,7 @@ function runners.execute_ctx_script(filename,...)
runners.register_arguments(...)
local arguments = environment.arguments_after
local fullname = runners.find_mtx_script(filename) or ""
- if file.extname(fullname) == "cld" then
+ if file.suffix(fullname) == "cld" then
-- handy in editors where we force --autopdf
report("running cld script: %s",filename)
table.insert(arguments,1,fullname)
@@ -16546,6 +16632,21 @@ function runners.timed(action)
statistics.timed(action)
end
+function runners.associate(filename)
+ os.launch(filename)
+end
+
+function runners.gethelp(filename)
+ local url = environment.argument("url")
+ if url and url ~= "" then
+ local command = string.gsub(environment.argument("command") or "unknown","^%s*\\*(.-)%s*$","%1")
+ url = utilities.templates.replace(url,{ command = command })
+ os.launch(url)
+ else
+ report("no --url given")
+ end
+end
+
-- this is a bit dirty ... first we store the first filename and next we
-- split the arguments so that we only see the ones meant for this script
-- ... later we will use the second half
@@ -16647,8 +16748,18 @@ else
end
+if e_argument("script") or e_argument("scripts") then
+
+ -- run a script by loading it (using libs), pass args
+
+ runners.loadbase()
+ if is_mkii_stub then
+ ok = runners.execute_script(filename,false,true)
+ else
+ ok = runners.execute_ctx_script(filename)
+ end
-if e_argument("selfmerge") then
+elseif e_argument("selfmerge") then
-- embed used libraries
@@ -16678,17 +16789,6 @@ elseif e_argument("ctxlua") or e_argument("internal") then
runners.loadbase()
ok = runners.execute_script(filename,true)
-elseif e_argument("script") or e_argument("scripts") then
-
- -- run a script by loading it (using libs), pass args
-
- runners.loadbase()
- if is_mkii_stub then
- ok = runners.execute_script(filename,false,true)
- else
- ok = runners.execute_ctx_script(filename)
- end
-
elseif e_argument("execute") then
-- execute script
@@ -16715,6 +16815,14 @@ elseif e_argument("launch") then
runners.loadbase()
runners.launch_file(filename)
+elseif e_argument("associate") then
+
+ runners.associate(filename)
+
+elseif e_argument("gethelp") then
+
+ runners.gethelp()
+
elseif e_argument("makestubs") then
-- make stubs (depricated)
@@ -16806,7 +16914,7 @@ elseif e_argument("find-path") then
elseif e_argument("expand-braces") then
- -- luatools: runners.execute_ctx_script("mtx-base","--expand-braces",filename
+ -- luatools: runners.execute_ctx_script("mtx-base","--expand-braces",filename)
resolvers.load("nofiles")
runners.register_arguments(filename)
@@ -16908,6 +17016,23 @@ elseif e_argument("version") then
application.version()
+elseif e_argument("directives") then
+
+ directives.show()
+
+elseif e_argument("trackers") then
+
+ trackers.show()
+
+elseif e_argument("experiments") then
+
+ experiments.show()
+
+elseif e_argument("exporthelp") then
+
+ runners.loadbase()
+ application.export(e_argument("exporthelp"),filename)
+
elseif e_argument("help") or filename=='help' or filename == "" then
application.help()
@@ -16938,7 +17063,6 @@ elseif environment.files[1] == 'texmfcnf.lua' then -- so that we don't need to l
resolvers.listers.configurations()
else
-
runners.loadbase()
runners.execute_ctx_script("mtx-base",filename)
@@ -16955,4 +17079,4 @@ end
if ok == false then ok = 1 elseif ok == true then ok = 0 end
-os.exit(ok)
+os.exit(ok,true) -- true forces a cleanup in 5.2+
diff --git a/Master/texmf-dist/scripts/context/stubs/unix/pstopdf b/Master/texmf-dist/scripts/context/stubs/unix/pstopdf
new file mode 100644
index 00000000000..116f5f4a32e
--- /dev/null
+++ b/Master/texmf-dist/scripts/context/stubs/unix/pstopdf
@@ -0,0 +1,2 @@
+#!/bin/sh
+mtxrun --script pstopdf "$@"
diff --git a/Master/texmf-dist/tex/context/base/anch-bar.mkiv b/Master/texmf-dist/tex/context/base/anch-bar.mkiv
index 9f9770fb6a3..c7c6190bef9 100644
--- a/Master/texmf-dist/tex/context/base/anch-bar.mkiv
+++ b/Master/texmf-dist/tex/context/base/anch-bar.mkiv
@@ -58,7 +58,9 @@
\installcommandhandler \??sidebar {sidebar} \??sidebar
\newcount\c_anch_sidebars_n
-\newdimen\c_anch_sidebars_distance
+\newcount\c_anch_sidebars_current % local
+\newdimen\d_anch_sidebars_distance
+\newcount\c_anch_sidebars_level
% \setupMPvariables
% [mpos:sidebar]
@@ -67,24 +69,60 @@
% distance=5pt]
\setupsidebar
- [\c!rulethickness=2pt,
+ [\c!rulethickness=\dimexpr\bodyfontsize/6\relax, % 2pt default
\c!rulecolor=\s!black,
\c!alternative=0,
- \c!topoffset=0pt,
- \c!bottomoffset=0pt,
- \c!distance=.5\bodyfontsize]
+ \c!topoffset=\zeropoint,
+ \c!bottomoffset=\zeropoint,
+ \c!distance=.5\bodyfontsize,
+ \c!level=,
+ \c!leftmargindistance=\zeropoint]
\let\setupsidebars\setupsidebar
\unexpanded\def\startsidebar
{\dosingleempty\anch_sidebars_start}
-\def\anch_sidebars_start[#1]%
+\unexpanded\def\startsidebar
+ {\dodoubleempty\anch_sidebars_start}
+
+\def\anch_sidebars_start[#1][#2]%
{\bgroup
- \def\currentsidebar{#1}%
\dontleavehmode
+ \advance\c_anch_sidebars_level\plusone
\global\advance\c_anch_sidebars_n\plusone
- \advance\c_anch_sidebars_distance\sidebarparameter\c!distance
+ \c_anch_sidebars_current\c_anch_sidebars_n\relax % relax needed
+ \doifassignmentelse{#1}
+ {\edef\currentsidebar{\the\c_anch_sidebars_level}%
+ \checksidebarparent
+ \setupcurrentsidebar[#1]}
+ {\def\currentsidebar{#1}%
+ \setupcurrentsidebar[#2]}%
+ \scratchdistance\sidebarparameter\c!distance\relax
+ \edef\m_level{\sidebarparameter\c!level}%
+ \ifx\m_level\empty
+ \ifnum\c_anch_sidebars_level=\plusone
+ \scratchdimen\sidebarparameter\c!leftmargindistance\relax
+ \ifdim\scratchdimen=\zeropoint
+ \advance\d_anch_sidebars_distance\scratchdistance\relax
+ \else
+ \d_anch_sidebars_distance\scratchdimen
+ \fi
+ \else
+ \advance\d_anch_sidebars_distance\scratchdistance\relax
+ \fi
+ \else
+ \ifnum\m_level=\plusone
+ \scratchdimen\sidebarparameter\c!leftmargindistance\relax
+ \ifdim\scratchdimen=\zeropoint
+ \advance\d_anch_sidebars_distance\scratchdistance\relax
+ \else
+ \d_anch_sidebars_distance\scratchdimen
+ \fi
+ \else
+ \d_anch_sidebars_distance\dimexpr\scratchdimen+\numexpr\m_level-\plusone\relax\dimexpr\scratchdistance\relax\relax
+ \fi
+ \fi
\startpositionoverlay{text-1}%
\normalexpanded{\setMPpositiongraphicrange % maybe expand in definition
{b:sidebar:\the\c_anch_sidebars_n}%
@@ -94,15 +132,17 @@
linewidth=\sidebarparameter\c!rulethickness,
linecolor=\sidebarparameter\c!rulecolor,
alternative=\sidebarparameter\c!alternative,
- topoffset=\sidebarparameter\c!topoffset,
- bottomoffset=\sidebarparameter\c!bottomoffset,
- distance=\the\c_anch_sidebars_distance}}%
+ topoffset=\the\dimexpr\sidebarparameter\c!topoffset,
+ bottomoffset=\the\dimexpr\sidebarparameter\c!bottomoffset,
+ distance=\the\d_anch_sidebars_distance}%
+ }%
\stoppositionoverlay
- \bpos{sidebar:\the\c_anch_sidebars_n}}
+ \bpos{sidebar:\the\c_anch_sidebars_current}%
+ \ignorespaces}
\unexpanded\def\stopsidebar
{\removelastspace
- \epos{sidebar:\the\c_anch_sidebars_n}
+ \epos{sidebar:\the\c_anch_sidebars_current}
\carryoverpar\egroup}
%D Let's keep this nice and simple (okay, we could pass the 6 variables in
@@ -121,49 +161,73 @@
\MPpositiongraphic{mpos:sidebar}{}%
\stopMPpositionmethod
-%D We now reimplement the margin rules handler defined in
-%D \type {core-rul}:
+%D We now reimplement the \MKII\ margin rules handler in a more
+%D modern way.
%D
-%D \setupmarginrules[level=5]
+%D \setupmarginrules
+%D [rulecolor=darkred,
+%D rulethickness=2pt]
%D
-%D \startmarginrule[1]
-%D First we set the level at~5. Next we typeset this first
-%D paragraph as a level~1 one. As expected no rule show up.
-%D \stopmarginrule
+%D \setupmarginrules % sidebar
+%D [2]
+%D [rulecolor=darkblue]
%D
-%D \startmarginrule[5]
-%D The second paragraph is a level~5 one. As we can see here,
-%D the marginal rule gets a width according to its level.
+%D \startmarginrule[1]
+%D \input ward
+%D \startmarginrule[2]
+%D \input ward
+%D \startmarginrule[3]
+%D \input ward
+%D \startmarginrule[level=6,rulecolor=darkgreen]
+%D \input ward
+%D \stopmarginrule
+%D \input ward
+%D \stopmarginrule
+%D \input ward
+%D \stopmarginrule
+%D \input ward
%D \stopmarginrule
%D
-%D \startmarginrule[8]
-%D It will of course be no surprise that this third paragraph
-%D has a even thicker margin rule. This behavior can be
-%D overruled by specifying the width explictly.
-%D \stopmarginrule
+%D Compared to the old mechanism we now can pass settings too.
\definesidebar
[\v!margin]
- [\c!rulethickness=\@@karulethickness,
- \c!distance=\dimexpr\leftmargindistance-\@@karulethickness/2\relax]
+ [\c!leftmargindistance=\dimexpr\leftmargindistance+\sidebarparameter\c!rulethickness/2\relax]
-\definecomplexorsimple\startmarginrule
+\dorecurse{5}{\definesidebar[\v!margin:#1][\v!margin]} % let's be nice and predefine 5 levels
-\def\simplestartmarginrule
- {\complexstartmarginrule[1]}
+\unexpanded\def\setupmarginrule
+ {\dodoubleargument\anch_marginrules_setup}
-\def\complexstartmarginrule[#1]%
- {\bgroup
- \ifnum#1<\@@kalevel\relax
- \let\stopmarginrule\egroup
+\def\anch_marginrules_setup[#1][#2]%
+ {\ifsecondargument
+ \setupsidebar[\v!margin:#1][#2]%
\else
- \def\@@kadefaultwidth{#1}%
- \let\stopmarginrule\dostopmarginrule
- \normalexpanded{\startsidebar[\v!margin]}% why expanded
+ \setupsidebar[\v!margin][#1]%
\fi}
-\def\dostopmarginrule
- {\stopsidebar
- \egroup}
+\let\setupmarginrules\setupmarginrule
+
+\unexpanded\def\startmarginrule
+ {\dosingleempty\anch_marginrules_start}
+
+\unexpanded\def\startmarginrule
+ {\dosingleempty\anch_marginrules_start}
+
+\def\anch_marginrules_start[#1]% pretty inefficient checking
+ {\edef\m_anch_marginrules_kind{#1}%
+ \ifx\m_anch_marginrules_kind\empty
+ \anch_sidebars_start[\v!margin][]%
+ \else
+ \doifassignmentelse\m_anch_marginrules_kind
+ {\anch_sidebars_start[\v!margin][#1]}%
+ {\anch_marginrules_check{#1}%
+ \anch_sidebars_start[\v!margin:#1][\c!level=#1]}%
+ \fi}
+
+\def\anch_marginrules_check#1%
+ {\doifnotcommandhandler\??sidebar{\v!margin:#1}{\definesidebar[\v!margin:#1][\v!margin]}}
+
+\let\stopmarginrule\stopsidebar
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/anch-bck.mkvi b/Master/texmf-dist/tex/context/base/anch-bck.mkvi
index 8ec056468dd..79e42dc0acc 100644
--- a/Master/texmf-dist/tex/context/base/anch-bck.mkvi
+++ b/Master/texmf-dist/tex/context/base/anch-bck.mkvi
@@ -276,7 +276,7 @@
\kern\textbackgroundskip\nobreak
\fi \fi
\nobreak
- \vskip-\dimexpr\lineheight+\parskip\relax
+ \vskip-\dimexpr\lineheight+\parskip\relax % problem: we loose the hangindent
\nobreak
\endgroup
\begingroup
@@ -298,7 +298,7 @@
\endgraf % new
\textbackgroundparameter\c!after}
-\unexpanded\def\checkpositionoverlays
+\unexpanded\def\checkpositionoverlays % overloads \relax in anch-pgr
{\ifproductionrun
\enabletextarearegistration
\enablehiddenbackground
@@ -307,7 +307,7 @@
\setuptextbackground
[\c!mp=mpos:region:draw,
- \c!method=mpos:region,
+ \c!method=mpos:region, % mpos:regionshape
\c!state=\v!start,
\c!location=\v!text,
\c!leftoffset=\!!zeropoint, % 1em,
@@ -397,6 +397,14 @@
\includeMPgraphic{mpos:region:anchor} ;
\stopMPpositiongraphic
+\startMPpositiongraphic{mpos:regionshape}{fillcolor,filloffset,linecolor,gridcolor,linewidth,gridwidth,gridshift,lineradius,lineoffset}
+ \includeMPgraphic{mpos:region:setup} ;
+ \includeMPgraphic{mpos:region:extra} ;
+ \MPgetmultishapes{\MPvar{self}}{\MPanchorid} ;
+ \includeMPgraphic{\MPvar{mp}} ;
+ \includeMPgraphic{mpos:region:anchor} ;
+\stopMPpositiongraphic
+
\startMPpositionmethod{mpos:region}
\MPpositiongraphic{mpos:region}{}%
\stopMPpositionmethod
diff --git a/Master/texmf-dist/tex/context/base/anch-pgr.lua b/Master/texmf-dist/tex/context/base/anch-pgr.lua
index bf4dcbe0287..278448e3aa7 100644
--- a/Master/texmf-dist/tex/context/base/anch-pgr.lua
+++ b/Master/texmf-dist/tex/context/base/anch-pgr.lua
@@ -8,6 +8,8 @@ if not modules then modules = { } end modules ['anch-pgr'] = {
-- todo: we need to clean up lists (of previous pages)
+local commands, context = commands, context
+
local format = string.format
local abs = math.abs
local concat, sort = table.concat, table.sort
@@ -15,20 +17,19 @@ local splitter = lpeg.splitat(":")
local lpegmatch = lpeg.match
local jobpositions = job.positions
+local formatters = string.formatters
local report_graphics = logs.reporter("graphics")
-local function point(n)
- return format("%.5fpt",n/65536)
-end
+local f_b_tag = formatters["b:%s"]
+local f_e_tag = formatters["e:%s"]
+local f_p_tag = formatters["p:%s"]
-local function pair(x,y)
- return format("(%.5fpt,%.5fpt)",x/65536,y/65536)
-end
+local f_tag_two = formatters["%s:%s"]
-local function path(t)
- return concat(t,"--") .. "--cycle"
-end
+local f_point = formatters["%p"]
+local f_pair = formatters["(%p,%p)"]
+local f_path = formatters["%--t--cycle"]
local function regionarea(r)
local rx, ry = r.x, r.y
@@ -36,10 +37,10 @@ local function regionarea(r)
local rh = ry + r.h
local rd = ry - r.d
return {
- pair(rx, rh - ry),
- pair(rw, rh - ry),
- pair(rw, rd - ry),
- pair(rx, rd - ry),
+ f_pair(rx, rh - ry),
+ f_pair(rw, rh - ry),
+ f_pair(rw, rd - ry),
+ f_pair(rx, rd - ry),
}
end
@@ -47,34 +48,48 @@ end
local eps = 2
-local function add(t,x,y,last)
+local function add(t,x,y,last,direction)
local n = #t
if n == 0 then
t[n+1] = { x, y }
- elseif n == 1 then
- local tn = t[1]
- if abs(tn[1]-x) <= eps or abs(tn[2]-y) <= eps then
- t[n+1] = { x, y }
- end
else
- local tm = t[n-1]
local tn = t[n]
local lx = tn[1]
local ly = tn[2]
- if abs(lx-tm[1]) <= eps and abs(lx-x) <= eps then
- if abs(ly-y) > eps then
- tn[2] = y
+ if x == lx and y == ly then
+ -- quick skip
+ elseif n == 1 then
+-- if abs(lx-x) <= eps or abs(ly-y) <= eps then
+ if abs(lx-x) > eps or abs(ly-y) > eps then
+ t[n+1] = { x, y }
end
- elseif abs(ly-tm[2]) <= eps and abs(ly-y) <= eps then
- if abs(lx-x) > eps then
- tn[1] = x
+ else
+ local tm = t[n-1]
+ local px = tm[1]
+ local py = tm[2]
+if (direction == "down" and y > ly) or (direction == "up" and y < ly) then
+ -- move back from too much hang
+else
+ if abs(lx-px) <= eps and abs(lx-x) <= eps then
+ if abs(ly-y) > eps then
+ tn[2] = y
+ end
+ elseif abs(ly-py) <= eps and abs(ly-y) <= eps then
+ if abs(lx-x) > eps then
+ tn[1] = x
+ end
+ elseif not last then
+ t[n+1] = { x, y }
end
- elseif not last then
- t[n+1] = { x, y }
+end
end
end
end
+-- local function add(t,x,y,last)
+-- t[#t+1] = { x, y }
+-- end
+
local function finish(t)
local n = #t
if n > 1 then
@@ -109,105 +124,103 @@ end
-- todo: mark regions and free paragraphs in collected
-local function shapes(r,rx,ry,rw,rh,rd,lytop,lybot,rytop,rybot)
+local function shapes(r,rx,ry,rw,rh,rd,lytop,lybot,rytop,rybot,obeyhang)
-- we assume that we only hang per page and not cross pages
-- which makes sense as hanging is only uses in special cases
--
-- we can remove data as soon as a page is done so we could
-- remember per page and discard areas after each shipout
local leftshape, rightshape
--- leftshape = r.leftshape
--- rightshape = r.rightshape
--- if not leftshape then
- leftshape = { { rx, rh } }
- rightshape = { { rw, rh } }
- local paragraphs = r.paragraphs
- local extending = false
- if paragraphs then
- for i=1,#paragraphs do
- local p = paragraphs[i]
- local ha = p.ha
- if ha and ha ~= 0 then
+ leftshape = { { rx, rh } } -- spikes get removed so we can start at the edge
+ rightshape = { { rw, rh } } -- even if we hang next
+ local paragraphs = r.paragraphs
+ local extending = false
+ if paragraphs then
+ for i=1,#paragraphs do
+ local p = paragraphs[i]
+ local ha = p.ha
+ if obeyhang and ha and ha ~= 0 then
+ local py = p.y
+ local ph = p.h
+ local pd = p.d
+ local hi = p.hi
+ local hang = ha * (ph + pd)
+ local py_ph = py + ph
+ -- ha < 0 hi < 0 : right top
+ -- ha < 0 hi > 0 : left top
+ if ha < 0 then
+ if hi < 0 then -- right
+ add(rightshape,rw, py_ph,"up")
+ add(rightshape,rw + hi,py_ph,"up")
+ add(rightshape,rw + hi,py_ph + hang,"up")
+ add(rightshape,rw, py_ph + hang,"up")
+ else
+ -- left
+ add(leftshape,rx,py_ph,"down")
+ add(leftshape,rx + hi,py_ph,"down")
+ add(leftshape,rx + hi,py_ph + hang,"down")
+ add(leftshape,rx,py_ph + hang,"down")
+ end
+ else
+ -- maybe some day
+ end
+ extending = true -- false
+ else -- we need to clip to the next par
+ local ps = p.ps
+ if ps then
local py = p.y
local ph = p.h
local pd = p.d
- local hi = p.hi
- local hang = ha * (ph + pd)
+ local step = ph + pd
+ local size = #ps * step
local py_ph = py + ph
- -- ha < 0 hi < 0 : right top
- -- ha < 0 hi > 0 : left top
- if ha < 0 then
- if hi < 0 then -- right
- add(rightshape,rw , py_ph)
- add(rightshape,rw + hi, py_ph)
- add(rightshape,rw + hi, py_ph + hang)
- add(rightshape,rw , py_ph + hang)
- else
- -- left
- add(leftshape,rx, py_ph)
- add(leftshape,rx + hi, py_ph)
- add(leftshape,rx + hi, py_ph + hang)
- add(leftshape,rx, py_ph + hang)
- end
- end
-extending = false
- else -- we need to clip to the next par
- local ps = p.ps
- if ps then
- local py = p.y
- local ph = p.h
- local pd = p.d
- local step = ph + pd
- local size = #ps * step
- local py_ph = py + ph
- add(leftshape,rx,py_ph)
- add(rightshape,rw,py_ph)
- for i=1,#ps do
- local p = ps[i]
- local l = p[1]
- local w = p[2]
- add(leftshape,rx + l, py_ph)
- add(rightshape,rx + l + w, py_ph)
- py_ph = py_ph - step
- add(leftshape,rx + l, py_ph)
- add(rightshape,rx + l + w, py_ph)
- end
- extending = true
--- add(left,rx,py_ph)
--- add(right,rw,py_ph)
- else
- if extending then
- local py = p.y
- local ph = p.h
- local pd = p.d
- local py_ph = py + ph
- local py_pd = py - pd
- add(leftshape,leftshape[#leftshape][1],py_ph)
- add(rightshape,rightshape[#rightshape][1],py_ph)
- add(leftshape,rx,py_ph)
- add(rightshape,rw,py_ph)
-extending = false
- end
+ add(leftshape,rx,py_ph,"up")
+ add(rightshape,rw,py_ph,"down")
+ for i=1,#ps do
+ local p = ps[i]
+ local l = p[1]
+ local w = p[2]
+ add(leftshape,rx + l, py_ph,"up")
+ add(rightshape,rx + l + w, py_ph,"down")
+ py_ph = py_ph - step
+ add(leftshape,rx + l, py_ph,"up")
+ add(rightshape,rx + l + w, py_ph,"down")
end
+ extending = true
+ elseif extending then
+ local py = p.y
+ local ph = p.h
+ local pd = p.d
+ local py_ph = py + ph
+ local py_pd = py - pd
+ add(leftshape,leftshape[#leftshape][1],py_ph,"up")
+ add(rightshape,rightshape[#rightshape][1],py_ph,"down")
+ add(leftshape,rx,py_ph,"up") -- shouldn't this be py_pd
+ add(rightshape,rw,py_ph,"down") -- shouldn't this be py_pd
+ extending = false
end
end
end
- -- we can have a simple variant when no paragraphs
- if extending then
- -- not ok
- leftshape[#leftshape][2] = rd
- rightshape[#rightshape][2] = rw
- else
- add(leftshape,rx,rd)
- add(rightshape,rw,rd)
- end
--- r.leftshape = leftshape
--- r.rightshape = rightshape
--- end
+ end
+ -- we can have a simple variant when no paragraphs
+ if extending then
+ -- not ok
+ leftshape[#leftshape][2] = rd
+ rightshape[#rightshape][2] = rw
+ else
+ add(leftshape,rx,rd,"up")
+ add(rightshape,rw,rd,"down")
+ end
return clip(leftshape,lytop,lybot), clip(rightshape,rytop,rybot)
end
-local function singlepart(b,e,r,left,right)
+-- local function shapes(r,rx,ry,rw,rh,rd,lytop,lybot,rytop,rybot,obeyhang)
+-- local leftshape = { { rx, rh }, { rx, rd } }
+-- local rightshape = { { rw, rh }, { rw, rd } }
+-- return clip(leftshape,lytop,lybot), clip(rightshape,rytop,rybot)
+-- end
+
+local function singlepart(b,e,r,left,right,obeyhang)
local bx, by = b.x, b.y
local ex, ey = e.x, e.y
local rx, ry = r.x, r.y
@@ -231,14 +244,14 @@ local function singlepart(b,e,r,left,right)
local area
if by == ey then
area = {
- pair(bx,bh-ry),
- pair(ex,eh-ry),
- pair(ex,ed-ry),
- pair(bx,bd-ry),
+ f_pair(bx,bh-ry),
+ f_pair(ex,eh-ry),
+ f_pair(ex,ed-ry),
+ f_pair(bx,bd-ry),
}
else
area = { }
- local leftshapes, rightshapes = shapes(r,rx,ry,rw,rh,rd,bd,ed,bh,eh)
+ local leftshapes, rightshapes = shapes(r,rx,ry,rw,rh,rd,bd,ed,bh,eh,obeyhang)
add(area,bx,bh-ry)
for i=1,#rightshapes do
local ri = rightshapes[i]
@@ -255,7 +268,7 @@ local function singlepart(b,e,r,left,right)
finish(area)
for i=1,#area do
local a = area[i]
- area[i] = pair(a[1],a[2])
+ area[i] = f_pair(a[1],a[2])
end
end
return {
@@ -265,7 +278,7 @@ local function singlepart(b,e,r,left,right)
}
end
-local function firstpart(b,r,left,right)
+local function firstpart(b,r,left,right,obeyhang)
local bx, by = b.x, b.y
local rx, ry = r.x, r.y
local rw = rx + r.w
@@ -278,7 +291,7 @@ local function firstpart(b,r,left,right)
local bh = by + b.h
local bd = by - b.d
local area = { }
- local leftshapes, rightshapes = shapes(r,rx,ry,rw,rh,rd,bd,rd,bh,rd)
+ local leftshapes, rightshapes = shapes(r,rx,ry,rw,rh,rd,bd,rd,bh,rd,obeyhang)
add(area,bx,bh-ry)
for i=1,#rightshapes do
local ri = rightshapes[i]
@@ -293,7 +306,7 @@ local function firstpart(b,r,left,right)
finish(area)
for i=1,#area do
local a = area[i]
- area[i] = pair(a[1],a[2])
+ area[i] = f_pair(a[1],a[2])
end
return {
location = "first",
@@ -302,7 +315,7 @@ local function firstpart(b,r,left,right)
}
end
-local function middlepart(r,left,right)
+local function middlepart(r,left,right,obeyhang)
local rx, ry = r.x, r.y
local rw = rx + r.w
local rh = ry + r.h
@@ -312,7 +325,7 @@ local function middlepart(r,left,right)
rw = rw - right
end
local area = { }
- local leftshapes, rightshapes = shapes(r,rx,ry,rw,rh,rd,rh,rd,rh,rd)
+ local leftshapes, rightshapes = shapes(r,rx,ry,rw,rh,rd,rh,rd,rh,rd,obeyhang)
for i=#leftshapes,1,-1 do
local li = leftshapes[i]
add(area,li[1],li[2]-ry)
@@ -324,7 +337,7 @@ local function middlepart(r,left,right)
finish(area)
for i=1,#area do
local a = area[i]
- area[i] = pair(a[1],a[2])
+ area[i] = f_pair(a[1],a[2])
end
return {
location = "middle",
@@ -333,7 +346,7 @@ local function middlepart(r,left,right)
}
end
-local function lastpart(e,r,left,right)
+local function lastpart(e,r,left,right,obeyhang)
local ex, ey = e.x, e.y
local rx, ry = r.x, r.y
local rw = rx + r.w
@@ -347,7 +360,7 @@ local function lastpart(e,r,left,right)
local ed = ey - e.d
local area = { }
-- two cases: till end and halfway e line
- local leftshapes, rightshapes = shapes(r,rx,ry,rw,rh,rd,rh,ed,rh,eh)
+ local leftshapes, rightshapes = shapes(r,rx,ry,rw,rh,rd,rh,ed,rh,eh,obeyhang)
for i=1,#rightshapes do
local ri = rightshapes[i]
add(area,ri[1],ri[2]-ry)
@@ -361,7 +374,7 @@ local function lastpart(e,r,left,right)
finish(area)
for i=1,#area do
local a = area[i]
- area[i] = pair(a[1],a[2])
+ area[i] = f_pair(a[1],a[2])
end
return {
location = "last",
@@ -375,24 +388,24 @@ local backgrounds = { }
graphics.backgrounds = backgrounds
-local function calculatemultipar(tag)
+local function calculatemultipar(tag,obeyhang)
local collected = jobpositions.collected
- local b = collected[format("b:%s",tag)]
- local e = collected[format("e:%s",tag)]
+ local b = collected[f_b_tag(tag)]
+ local e = collected[f_e_tag(tag)]
if not b or not e then
- report_graphics("invalid tag '%s'",tag)
+ report_graphics("invalid tag %a",tag)
return { }
end
local br = b.r
local er = e.r
if not br or not er then
- report_graphics("invalid region for '%s'",tag)
+ report_graphics("invalid region for %a",tag)
return { }
end
local btag, bindex = lpegmatch(splitter,br)
local etag, eindex = lpegmatch(splitter,er)
if not bindex or not eindex or btag ~= etag then
- report_graphics("invalid indices for '%s'",tag)
+ report_graphics("invalid indices for %a",tag)
return { }
end
local bindex = tonumber(bindex)
@@ -420,7 +433,7 @@ local function calculatemultipar(tag)
--
local bn = b.n
if bn then
- local bp = collected[format("p:%s",bn)]
+ local bp = collected[f_p_tag(bn)]
if bp then
left = left + bp.ls
right = right + bp.rs
@@ -429,35 +442,35 @@ local function calculatemultipar(tag)
--
if bindex == eindex then
return {
- list = { [b.p] = { singlepart(b,e,collected[br],left,right) } },
+ list = { [b.p] = { singlepart(b,e,collected[br],left,right,obeyhang) } },
bpos = b,
epos = e,
}
else
local list = {
- [b.p] = { firstpart(b,collected[br],left,right) },
+ [b.p] = { firstpart(b,collected[br],left,right,obeyhang) },
}
for i=bindex+1,eindex-1 do
- br = format("%s:%s",btag,i)
+ br = f_tag_two(btag,i)
local r = collected[br]
if not r then
- report_graphics("invalid middle for '%s'",br)
+ report_graphics("invalid middle for %a",br)
else
local p = r.p
local pp = list[p]
if pp then
- pp[#pp+1] = middlepart(r,left,right)
+ pp[#pp+1] = middlepart(r,left,right,obeyhang)
else
- list[p] = { middlepart(r,left,right) }
+ list[p] = { middlepart(r,left,right,obeyhang) }
end
end
end
local p = e.p
local pp = list[p]
if pp then
- pp[#pp+1] = lastpart(e,collected[er],left,right)
+ pp[#pp+1] = lastpart(e,collected[er],left,right,obeyhang)
else
- list[p] = { lastpart(e,collected[er],left,right) }
+ list[p] = { lastpart(e,collected[er],left,right,obeyhang) }
end
return {
list = list,
@@ -511,36 +524,41 @@ local multilocs = {
-- if unknown context_abck : input mp-abck.mpiv ; fi ;
-local template_a = [[
+local f_template_a = [[
path multiregs[], multipars[], multibox ;
string multikind[] ;
numeric multilocs[], nofmultipars ;
nofmultipars := %s ;
-multibox := unitsquare xyscaled %s ;
+multibox := unitsquare xyscaled (%p,%p) ;
numeric par_strut_height, par_strut_depth, par_line_height ;
-par_strut_height := %s ;
-par_strut_depth := %s ;
-par_line_height := %s ;
+par_strut_height := %p ;
+par_strut_depth := %p ;
+par_line_height := %p ;
]]
-local template_b = [[
+local f_template_b = [[
multilocs[%s] := %s ;
multikind[%s] := "%s" ;
-multipars[%s] := (%s) shifted - %s ;
+multipars[%s] := (%--t--cycle) shifted - (%p,%p) ;
]]
-local template_c = [[
-multiregs[%s] := (%s) shifted - %s ;
+local f_template_c = [[
+multiregs[%s] := (%--t--cycle) shifted - %s ;
]]
-local template_d = [[
+local f_template_d = [[
setbounds currentpicture to multibox ;
]]
-function backgrounds.fetchmultipar(n,anchor,page)
+f_template_a = formatters[f_template_a]
+f_template_b = formatters[f_template_b]
+f_template_c = formatters[f_template_c]
+f_template_d = formatters[f_template_d]
+
+function backgrounds.fetchmultipar(n,anchor,page,obeyhang)
local data = pbg[n]
if not data then
- data = calculatemultipar(n)
+ data = calculatemultipar(n,obeyhang)
pbg[n] = data -- can be replaced by register
-- register(data.list,n,anchor)
end
@@ -550,60 +568,66 @@ function backgrounds.fetchmultipar(n,anchor,page)
local pagedata = list[page]
if pagedata then
local nofmultipars = #pagedata
- -- report_graphics("fetching '%s' at page %s using anchor '%s' containing %s multipars",n,page,anchor,nofmultipars)
+ -- report_graphics("fetching %a at page %s using anchor %a containing %s multipars",n,page,anchor,nofmultipars)
local a = jobpositions.collected[anchor]
if not a then
- report_graphics("missing anchor '%s'",anchor)
+ report_graphics("missing anchor %a",anchor)
else
local trace = false
local x, y, w, h, d = a.x, a.y, a.w, a.h, a.d
local bpos = data.bpos
local bh, bd = bpos.h, bpos.d
- local result = { format(template_a,nofmultipars,pair(w,h+d),point(bh),point(bd),point(bh+bd)) }
+ local result = { f_template_a(nofmultipars,w,h+d,bh,bd,bh+bd) }
for i=1,nofmultipars do
local region = pagedata[i]
- result[#result+1] = format(template_b,
+ result[#result+1] = f_template_b(
i, multilocs[region.location],
i, region.location,
- i, path(region.area), pair(x,y-region.region.y))
+ i, region.area, x, y-region.region.y)
if trace then
- result[#result+1] = format(template_c,
- i, path(regionarea(region.region)), offset)
+ result[#result+1] = f_template_c(i, regionarea(region.region), offset)
end
end
data[page] = nil
- result[#result+1] = template_d
+ result[#result+1] = f_template_d()
result = concat(result,"\n")
return result
end
end
end
end
- return format(template_a,0,"origin",0,0,0)
+ return f_template_a(0,"origin",0,0,0)
end
-backgrounds.point = point
-backgrounds.pair = pair
-backgrounds.path = path
+backgrounds.point = f_point
+backgrounds.pair = f_pair
+backgrounds.path = f_path
function commands.fetchmultipar(n,anchor,page)
context(backgrounds.fetchmultipar(n,anchor,page))
end
-local template_a = [[
+function commands.fetchmultishape(n,anchor,page)
+ context(backgrounds.fetchmultipar(n,anchor,page,true))
+end
+
+local f_template_a = [[
path posboxes[], posregions[] ;
numeric pospages[] ;
numeric nofposboxes ;
nofposboxes := %s ;
-%s ;
+%t ;
]]
-local template_b = [[
+local f_template_b = [[
pospages[%s] := %s ;
-posboxes[%s] := %s--%s--%s--%s--cycle ;
-posregions[%s] := %s--%s--%s--%s--cycle ;
+posboxes[%s] := (%p,%p)--(%p,%p)--(%p,%p)--(%p,%p)--cycle ;
+posregions[%s] := (%p,%p)--(%p,%p)--(%p,%p)--(%p,%p)--cycle ;
]]
+f_template_a = formatters[f_template_a]
+f_template_b = formatters[f_template_b]
+
function commands.fetchposboxes(tags,anchor,page) -- no caching (yet) / todo: anchor, page
local collected = jobpositions.collected
if type(tags) == "string" then
@@ -625,10 +649,10 @@ function commands.fetchposboxes(tags,anchor,page) -- no caching (yet) / todo: an
local ch = cy + c.h
local cd = cy - c.d
nofboxes = nofboxes + 1
- list[nofboxes] = format(template_b,
+ list[nofboxes] = f_template_b(
nofboxes,c.p,
- nofboxes,pair(cx,ch),pair(cw,ch),pair(cw,cd),pair(cx,cd),
- nofboxes,pair(0,rh),pair(rw,rh),pair(rw,rd),pair(0,rd)
+ nofboxes,cx,ch,cw,ch,cw,cd,cx,cd,
+ nofboxes,0,rh,rw,rh,rw,rd,0,rd
)
end
end
@@ -636,16 +660,15 @@ function commands.fetchposboxes(tags,anchor,page) -- no caching (yet) / todo: an
print("\n missing",tag)
end
end
- -- print(format(template_a,nofboxes,concat(list)))
- context(template_a,nofboxes,concat(list))
+ context(f_template_a(nofboxes,list))
end
local doifelse = commands.doifelse
-function commands.doifelsemultipar(n,page)
+function commands.doifelsemultipar(n,page,obeyhang)
local data = pbg[n]
if not data then
- data = calculatemultipar(n)
+ data = calculatemultipar(n,obeyhang)
pbg[n] = data
end
if page then
diff --git a/Master/texmf-dist/tex/context/base/anch-pgr.mkiv b/Master/texmf-dist/tex/context/base/anch-pgr.mkiv
index a417d26e3eb..01ef25dc4fc 100644
--- a/Master/texmf-dist/tex/context/base/anch-pgr.mkiv
+++ b/Master/texmf-dist/tex/context/base/anch-pgr.mkiv
@@ -33,7 +33,7 @@
\installcorenamespace{positionaction}
\installcorenamespace{positioncleanup}
-\unexpanded\def\dosetpositionaction#1%
+\unexpanded\def\anch_positions_set_action#1%
{\expandafter\gdef\csname\??positionaction#1\endcsname} % nicely gobbles spaces
\unexpanded\def\doifpositionaction#1%
@@ -111,7 +111,7 @@
{\begingroup
\edef\currentpositionanchor
{\ifx\currentpositionoverlay\empty#3\else\currentpositionoverlay::\MPanchoridentifier\fi}%
- \normalexpanded{\dosetpositionaction{\currentpositionanchor}{\noexpand\getvalue{\??positioncleanup\currentpositionanchor}}}%
+ \normalexpanded{\anch_positions_set_action{\currentpositionanchor}{\noexpand\getvalue{\??positioncleanup\currentpositionanchor}}}%
\let#1\relax
\ifcsname\??positioncleanup\currentpositionanchor\endcsname
\setxvalue{\??positioncleanup\currentpositionanchor}%
@@ -140,9 +140,6 @@
\fi
\fi\fi}
-% \def\anch_positions_register_page_indeed#1%
-% {\setbox#1\hbox{\hpos\pageanchor{\box#1}}}
-
\def\anch_positions_register_page_indeed#1% maybe like text
{\ifvbox#1\setbox#1\hbox{\box#1}\fi
\anch_make_page_box{#1}}
@@ -218,7 +215,6 @@
%D \typebuffer[graphic]
\def\MPanchoridentifier{mpa} % {mp-anchor}
-%def\MPoverlayposprefix{MO::} % not used
%D The rest of the definitions concerning such overlays may
%D look complicated,
@@ -237,8 +233,8 @@
\def\textbackgroundoverlay#1{\v!text#1}
\def\MPanchornumber {\the\realpageno}
-\def\positionoverlay % the test prevents too many redundant positions
- {\ifpositioning % in (not used) text* position layers
+\unexpanded\def\positionoverlay % the test prevents too many redundant positions
+ {\ifpositioning % in (not used) text* position layers
\expandafter\anch_positions_overlay_indeed
\else % also \iftrialtypesetting test here?
\expandafter\gobbleoneargument
@@ -269,7 +265,7 @@
\box\scratchbox
\vfill}}
-\def\positionregionoverlay % shares regions
+\unexpanded\def\positionregionoverlay % shares regions
{\ifpositioning
\expandafter\anch_positions_region_overlay_indeed
\else % also \iftrialtypesetting test here?
@@ -308,9 +304,15 @@
\expandafter\anch_positions_overlay_start_yes
\fi}
+\let\stoppositionoverlay\relax
+
\def\anch_positions_overlay_start_nop#1\stoppositionoverlay
{}
+\ifdefined\checkpositionoverlays \else \let\checkpositionoverlays\relax \fi
+
+\let\currentpositionoverlay\empty
+
\def\anch_positions_overlay_start_yes#1%
{\checkpositionoverlays
\edef\currentpositionoverlay{#1}}
@@ -318,9 +320,11 @@
\unexpanded\def\stoppositionoverlay
{\let\currentpositionoverlay\empty}
+% needs checking if still needed
+%
% \def\resetpositionoverlay#1%
-% {\dosetpositionaction{#1::\MPanchoridentifier::}{}}
-
+% {\anch_positions_set_action{#1::\MPanchoridentifier::}{}}
+%
% \def\handlepositionboxes#1#2#3%
% {\handlepositionaction\dohandlepositionboxes\with{#1}{#2}{#3}\on{#2}}
%
@@ -332,15 +336,15 @@
% \appendtoks
% \let\dohandlepositionboxes\doinsertpositionboxes % was handle ?
% \to \everyinsertpositionaction
-
-\def\docleanpositionboxes#1#2#3% pos tag setups
- {\ifnum\MPp{#1}<\realpageno \else
- \noexpand \dohandlepositionboxes{#1}{#2}{#3}% reinsert
- \fi}
-
-\appendtoks
- \let\dohandlepositionboxes\docleanpositionboxes
-\to \everycleanpositionaction
+%
+% \def\docleanpositionboxes#1#2#3% pos tag setups
+% {\ifnum\MPp{#1}<\realpageno \else
+% \noexpand \dohandlepositionboxes{#1}{#2}{#3}% reinsert
+% \fi}
+%
+% \appendtoks
+% \let\dohandlepositionboxes\docleanpositionboxes
+% \to \everycleanpositionaction
%D A position graphic is a normal (non||reused) \METAPOST\
%D graphic, used immediately, with zero dimensions, so that a
@@ -350,7 +354,7 @@
\installcorenamespace{positionmethod}
%installcorenamespace{graphicvariable}
-\newbox\positiongraphicbox
+\newbox\b_anch_positions_graphic
\def\startMPpositiongraphic % id setups
{\dodoublegroupempty\anch_positions_meta_graphic_start}
@@ -361,11 +365,11 @@
\let\stopMPpositiongraphic\relax
\def\anch_positions_meta_graphic_prepare
- {\ifcsname\??gv\currentmpvariableclass:self\endcsname \else
- \letvalue{\??gv\currentmpvariableclass:self}\currentposition
+ {\ifcsname\??graphicvariable\currentmpvariableclass:self\endcsname \else
+ \letvalue{\??graphicvariable\currentmpvariableclass:self}\currentposition
\fi
- \ifcsname\??gv\currentmpvariableclass:from\endcsname \else
- \letvalue{\??gv\currentmpvariableclass:from}\currentposition
+ \ifcsname\??graphicvariable\currentmpvariableclass:from\endcsname \else
+ \letvalue{\??graphicvariable\currentmpvariableclass:from}\currentposition
\fi}
\def\anch_positions_meta_graphic_use#1#2#3%
@@ -375,7 +379,7 @@
\startMPcode#3\stopMPcode
\endgroup}
-\def\MPpositiongraphic
+\unexpanded\def\MPpositiongraphic
{\dodoublegroupempty\anch_positions_meta_graphic_direct}
\def\anch_positions_meta_graphic_direct#1% tag setups
@@ -402,9 +406,9 @@
\anch_positions_meta_graphic_prepare
\obeyMPboxorigin % do we also set the size ? when needed this must be done in mp ... might change
\def\anch_positions_meta_graphic_direct{\anch_positions_meta_graphic_nested{#3}}% takes two extra arguments
- \setbox\positiongraphicbox\hbox{\ignorespaces\csname#1#2\endcsname\removelastspace}%
- \smashbox\positiongraphicbox
- \box\positiongraphicbox
+ \setbox\b_anch_positions_graphic\hbox{\ignorespaces\csname#1#2\endcsname\removelastspace}%
+ \smashbox\b_anch_positions_graphic
+ \box\b_anch_positions_graphic
\endgroup}
\def\anch_positions_meta_graphic_nested#1#2#3% nesting used in prikkels / pascal (might go away)
@@ -422,77 +426,77 @@
%D Simple one position graphics.
-\def\setMPpositiongraphic
- {\dotriplegroupempty\dosetMPpositiongraphic}
+\unexpanded\def\setMPpositiongraphic
+ {\dotriplegroupempty\anch_positions_meta_graphic_set}
-\def\dosetMPpositiongraphic#1#2#3% pos tag vars
+\def\anch_positions_meta_graphic_set#1#2#3% pos tag vars
{\ifx\currentpositionoverlay\empty
- \dosetpositionaction{#1}{\MPpositiongraphic{#2}{#3}}%
+ \anch_positions_set_action{#1}{\MPpositiongraphic{#2}{#3}}%
\else % silly can be one
- \handlepositiongraphics{#1}{#2}{#3}%
+ \anch_positions_meta_graphic_handle{#1}{#2}{#3}%
\fi}
-\def\handlepositiongraphics#1#2#3% combine with boxes
- {\handlepositionaction\dohandleMPpositiongraphic\with{#1}{#2}{#3}\on{#2}}
+\def\anch_positions_meta_graphic_handle#1#2#3% combine with boxes
+ {\handlepositionaction\anch_positions_meta_graphic_handle_indeed\with{#1}{#2}{#3}\on{#2}}
-\def\doinsertMPpositiongraphic#1#2#3% pos tag setups
+\def\anch_positions_meta_graphic_insert#1#2#3% pos tag setups
{\ifnum\MPp{#1}=\realpageno\relax % extra saveguard
\def\currentposition{#1}\MPpositiongraphic{#2}{#3}%
\fi}
\appendtoks
- \let\dohandleMPpositiongraphic\doinsertMPpositiongraphic
+ \let\anch_positions_meta_graphic_handle_indeed\anch_positions_meta_graphic_insert
\to \everyinsertpositionaction
-\def\docleanMPpositiongraphic#1#2#3% pos tag setups
+\def\anch_positions_meta_graphic_cleanup#1#2#3% pos tag setups
{\ifnum\MPp{#1}<\realpageno \else
- \noexpand\dohandleMPpositiongraphic{#1}{#2}{#3}%
+ \noexpand\anch_positions_meta_graphic_handle_indeed{#1}{#2}{#3}%
\fi}
\appendtoks
- \let\dohandleMPpositiongraphic\docleanMPpositiongraphic
+ \let\anch_positions_meta_graphic_handle_indeed\anch_positions_meta_graphic_cleanup
\to \everycleanpositionaction
%D Graphics that span two positions (beware, does not cross pages).
\unexpanded\def\setMPpositiongraphicrange
- {\doquadruplegroupempty\dosetMPpositiongraphicrange}
+ {\doquadruplegroupempty\anch_positions_meta_graphic_set_range}
-\def\dosetMPpositiongraphicrange#1#2#3#4% bpos epos tag vars
+\def\anch_positions_meta_graphic_set_range#1#2#3#4% bpos epos tag vars
{\ifx\currentpositionoverlay\empty
- \dosetpositionaction{#1}{\MPpositiongraphic{#3}{#4}}%
+ \anch_positions_set_action{#1}{\MPpositiongraphic{#3}{#4}}%
\else
- \handlepositiongraphicsrange{#1}{#2}{#3}{#4}%
+ \anch_positions_meta_graphic_handle_range{#1}{#2}{#3}{#4}%
\fi}
-\def\handlepositiongraphicsrange#1#2#3#4%
- {\handlepositionaction\dohandleMPpositiongraphicrange\with{#1}{#2}{#3}{#4}\on{#2}}
+\def\anch_positions_meta_graphic_handle_range#1#2#3#4%
+ {\handlepositionaction\anch_positions_meta_graphic_handle_range_indeed\with{#1}{#2}{#3}{#4}\on{#2}}
-\def\doinsertMPpositiongraphicrange#1#2#3#4% pos pos tag setups
+\def\anch_positions_meta_graphic_insert_range#1#2#3#4% pos pos tag setups
{\ctxcommand{doifelserangeonpage("#1","#2",\number\realpageno)}%
- {%\writestatus{YES}{#1/#2 => #3}%
- \def\currentposition{#1}%
+ {\def\currentposition{#1}%
\MPpositiongraphic{#3}{#4}}%
- {}}%\writestatus{NOP}{#1/#2 = #3}}}
+ {}}
\appendtoks
- \let\dohandleMPpositiongraphicrange\doinsertMPpositiongraphicrange
+ \let\anch_positions_meta_graphic_handle_range_indeed\anch_positions_meta_graphic_insert_range
\to \everyinsertpositionaction
-\def\docleanMPpositiongraphicrange#1#2#3#4% pos tag setups
+\def\anch_positions_meta_graphic_cleanup_range#1#2#3#4% pos tag setups
{\ifnum\MPp{#2}<\realpageno \else
- \noexpand \dohandleMPpositiongraphicrange{#1}{#2}{#3}{#4}%
+ \noexpand \anch_positions_meta_graphic_handle_range_indeed{#1}{#2}{#3}{#4}%
\fi}
\appendtoks
- \let\dohandleMPpositiongraphicrange\docleanMPpositiongraphicrange
+ \let\anch_positions_meta_graphic_handle_range_indeed\anch_positions_meta_graphic_cleanup_range
\to \everycleanpositionaction
-\let\dohandleMPpositiongraphicrange\gobblefourarguments
+\let\anch_positions_meta_graphic_handle_range_indeed\gobblefourarguments
% Helpers:
-\def\MPgetposboxes #1#2{\ctxcommand{fetchposboxes("#1","#2",\the\realpageno)}}
-\def\MPgetmultipars#1#2{\ctxcommand{fetchmultipar("#1","#2",\the\realpageno)}}
+\def\MPgetposboxes #1#2{\ctxcommand{fetchposboxes("#1","#2",\the\realpageno)}}
+\def\MPgetmultipars #1#2{\ctxcommand{fetchmultipar("#1","#2",\the\realpageno)}}
+\def\MPgetmultishapes#1#2{\ctxcommand{fetchmultishape("#1","#2",\the\realpageno)}}
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/anch-pos.lua b/Master/texmf-dist/tex/context/base/anch-pos.lua
index 5d01a6e466d..2697cecf4e8 100644
--- a/Master/texmf-dist/tex/context/base/anch-pos.lua
+++ b/Master/texmf-dist/tex/context/base/anch-pos.lua
@@ -17,8 +17,10 @@ more efficient.
-- maybe replace texsp by our own converter (stay at the lua end)
-- eventually mp will have large numbers so we can use sp there too
+local commands, context = commands, context
+
local tostring, next, rawget, setmetatable = tostring, next, rawget, setmetatable
-local concat, sort = table.concat, table.sort
+local sort = table.sort
local format, gmatch, match = string.format, string.gmatch, string.match
local rawget = rawget
local lpegmatch = lpeg.match
@@ -39,6 +41,7 @@ local v_column = variables.column
local pt = number.dimenfactors.pt
local pts = number.pts
+local formatters = string.formatters
local collected = allocate()
local tobesaved = allocate()
@@ -71,6 +74,23 @@ local default = { -- not r and paragraphs etc
}
}
+local f_b_tag = formatters["b:%s"]
+local f_e_tag = formatters["e:%s"]
+local f_p_tag = formatters["p:%s"]
+local f_w_tag = formatters["w:%s"]
+
+local f_b_column = formatters["_plib_.b_col(%q)"]
+local f_e_column = formatters["_plib_.e_col()"]
+
+local f_enhance = formatters["_plib_.enhance(%q)"]
+local f_region = formatters["region:%s"]
+
+local f_b_region = formatters["_plib_.b_region(%q)"]
+local f_e_region = formatters["_plib_.e_region(%s)"]
+
+local f_tag_three = formatters["%s:%s:%s"]
+local f_tag_two = formatters["%s:%s"]
+
local function sorter(a,b)
return a.y > b.y
end
@@ -275,13 +295,13 @@ function commands.bcolumn(tag,register)
insert(columns,tag)
column = tag
if register then
- context(new_latelua(format("_plib_.b_col(%q)",tag)))
+ context(new_latelua(f_b_column(tag)))
end
end
function commands.ecolumn(register)
if register then
- context(new_latelua("_plib_.e_col()"))
+ context(new_latelua(f_e_column()))
end
remove(columns)
column = columns[#columns]
@@ -311,7 +331,7 @@ end
function jobpositions.markregionbox(n,tag,correct)
if not tag or tag == "" then
nofregions = nofregions + 1
- tag = format("region:%s",nofregions)
+ tag = f_region(nofregions)
end
local box = texbox[n]
local w = box.width
@@ -325,8 +345,8 @@ function jobpositions.markregionbox(n,tag,correct)
h = h ~= 0 and h or nil,
d = d ~= 0 and d or nil,
}
- local push = new_latelua(format("_plib_.b_region(%q)",tag))
- local pop = new_latelua(format("_plib_.e_region(%s)",tostring(correct)))
+ local push = new_latelua(f_b_region(tag))
+ local pop = new_latelua(f_e_region(tostring(correct))) -- todo: check if tostring is needed with formatter
-- maybe we should construct a hbox first (needs experimenting) so that we can avoid some at the tex end
local head = box.list
if head then
@@ -348,7 +368,7 @@ end
function commands.pos(name,t)
tobesaved[name] = t
- context(new_latelua(format("_plib_.enhance(%q)",name)))
+ context(new_latelua(f_enhance(name)))
end
local nofparagraphs = 0
@@ -391,9 +411,9 @@ function commands.parpos() -- todo: relate to localpar (so this is an intermedia
if parshape and #parshape > 0 then
t.ps = parshape
end
- local tag = format("p:%s",nofparagraphs)
+ local tag = f_p_tag(nofparagraphs)
tobesaved[tag] = t
- context(new_latelua(format("_plib_.enhance(%q)",tag)))
+ context(new_latelua(f_enhance(tag)))
end
function commands.posxy(name) -- can node.write be used here?
@@ -405,7 +425,7 @@ function commands.posxy(name) -- can node.write be used here?
y = true,
n = nofparagraphs > 0 and nofparagraphs or nil,
}
- context(new_latelua(format("_plib_.enhance(%q)",name)))
+ context(new_latelua(f_enhance(name)))
end
function commands.poswhd(name,w,h,d)
@@ -420,7 +440,7 @@ function commands.poswhd(name,w,h,d)
d = d,
n = nofparagraphs > 0 and nofparagraphs or nil,
}
- context(new_latelua(format("_plib_.enhance(%q)",name)))
+ context(new_latelua(f_enhance(name)))
end
function commands.posplus(name,w,h,d,extra)
@@ -436,7 +456,7 @@ function commands.posplus(name,w,h,d,extra)
n = nofparagraphs > 0 and nofparagraphs or nil,
e = extra,
}
- context(new_latelua(format("_plib_.enhance(%q)",name)))
+ context(new_latelua(f_enhance(name)))
end
function commands.posstrut(name,w,h,d)
@@ -451,12 +471,12 @@ function commands.posstrut(name,w,h,d)
d = strutbox.depth,
n = nofparagraphs > 0 and nofparagraphs or nil,
}
- context(new_latelua(format("_plib_.enhance(%q)",name)))
+ context(new_latelua(f_enhance(name)))
end
function jobpositions.getreserved(tag,n)
if tag == v_column then
- local fulltag = format("%s:%s:%s",tag,texcount.realpageno,n or 1)
+ local fulltag = f_tag_three(tag,texcount.realpageno,n or 1)
local data = collected[fulltag]
if data then
return data, fulltag
@@ -464,7 +484,7 @@ function jobpositions.getreserved(tag,n)
tag = v_text
end
if tag == v_text then
- local fulltag = format("%s:%s",tag,texcount.realpageno)
+ local fulltag = f_tag_two(tag,texcount.realpageno)
return collected[fulltag] or false, fulltag
end
return collected[tag] or false, tag
@@ -885,7 +905,7 @@ end
local function MPpardata(n)
local t = collected[n]
if not t then
- local tag = format("p:%s",n)
+ local tag = f_p_tag(n)
t = collected[tag]
end
if t then
@@ -905,10 +925,10 @@ end
commands.MPpardata = MPpardata
function commands.MPposset(id) -- special helper, used in backgrounds
- local b = format("b:%s",id)
- local e = format("e:%s",id)
- local w = format("w:%s",id)
- local p = format("p:%s",jobpositions.n(b))
+ local b = f_b_tag(id)
+ local e = f_e_tag(id)
+ local w = f_w_tag(id)
+ local p = f_p_tag(jobpositions.n(b))
MPpos(b) context(",") MPpos(e) context(",") MPpos(w) context(",") MPpos(p) context(",") MPpardata(p)
end
@@ -969,35 +989,35 @@ function commands.MPxywhd(id)
end
end
--- is testcase already defined? if so, then local
+local doif, doifelse = commands.doif, commands.doifelse
function commands.doifpositionelse(name)
- commands.doifelse(collected[name])
+ doifelse(collected[name])
end
function commands.doifposition(name)
- commands.doif(collected[name])
+ doif(collected[name])
end
function commands.doifpositiononpage(name,page) -- probably always realpageno
local c = collected[name]
- commands.testcase(c and c.p == page)
+ doifelse(c and c.p == page)
end
function commands.doifoverlappingelse(one,two,overlappingmargin)
- commands.testcase(overlapping(one,two,overlappingmargin))
+ doifelse(overlapping(one,two,overlappingmargin))
end
function commands.doifpositionsonsamepageelse(list,page)
- commands.testcase(onsamepage(list))
+ doifelse(onsamepage(list))
end
function commands.doifpositionsonthispageelse(list)
- commands.testcase(onsamepage(list,tostring(tex.count.realpageno)))
+ doifelse(onsamepage(list,tostring(tex.count.realpageno)))
end
function commands.doifelsepositionsused()
- commands.testcase(next(collected))
+ doifelse(next(collected))
end
commands.markcolumnbox = jobpositions.markcolumnbox
diff --git a/Master/texmf-dist/tex/context/base/anch-pos.mkiv b/Master/texmf-dist/tex/context/base/anch-pos.mkiv
index 2e13eeba2cc..7ecaa296ed8 100644
--- a/Master/texmf-dist/tex/context/base/anch-pos.mkiv
+++ b/Master/texmf-dist/tex/context/base/anch-pos.mkiv
@@ -361,9 +361,9 @@
\startcolor[blue]%
\llap{\infofont\number\c_anch_positions_paragraph}%
\vrule
- \!!width 4\onepoint
- \!!height2\onepoint
- \!!depth 2\onepoint
+ \s!width 4\onepoint
+ \s!height2\onepoint
+ \s!depth 2\onepoint
\stopcolor
\hss}}
@@ -377,7 +377,7 @@
{\smashedhbox
{#1{\infofont#2#3}%
\kern-\onepoint
- \vrule\!!width2\onepoint\!!height\halfapoint\!!depth\halfapoint}}
+ \vrule\s!width2\onepoint\s!height\halfapoint\s!depth\halfapoint}}
\unexpanded\def\anch_positions_trace_left_indeed
{\anch_positions_trace\llap\darkmagenta{\currentposition>}}
diff --git a/Master/texmf-dist/tex/context/base/anch-tab.mkiv b/Master/texmf-dist/tex/context/base/anch-tab.mkiv
index 4bdaa2ef984..a70f63e24bf 100644
--- a/Master/texmf-dist/tex/context/base/anch-tab.mkiv
+++ b/Master/texmf-dist/tex/context/base/anch-tab.mkiv
@@ -13,6 +13,9 @@
\writestatus{loading}{ConTeXt Anchoring Macros / Table Extensions}
+%D This is just a playground and functionality might change or even
+%D dissappear in favour of better solutions.
+
\unprotect
\newcount\c_anch_tabs
@@ -57,23 +60,22 @@
\global\advance\c_anch_tabs\plusone
\to \everytabulate
-%D Beware, the following code is somewhat weird and experimental
-%D and might be dropped or become a loadable module.
+%D Beware, the following code is somewhat weird and experimental and might be
+%D dropped or become a loadable module.
%D \macros
%D {GFC, GTC, GSC}
%D
-%D The next macros extend tables and tabulation with
-%D backgrounds and position related features. Areas are
-%D specified with symbolic names, and symbolic references to
-%D the graphics involved. Each table has its own namespace.
+%D The next macros extend tables and tabulation with backgrounds and position
+%D related features. Areas are specified with symbolic names, and symbolic
+%D references to the graphics involved. Each table has its own namespace.
\newconditional\tablehaspositions
-\newcount\noftabpositions
-\newtoks \posXCtoks
+\newcount \noftabpositions
+\newtoks \posXCtoks
-\def\dotablebpos{\bpos}
-\def\dotableepos{\epos}
+\def\anch_tabulate_bpos{\bpos}
+\def\anch_tabulate_epos{\epos}
\installcorenamespace{positiontables}
@@ -85,74 +87,80 @@
\let\tabulatepos\tablepos
-\def\dodododoGSC[#1:#2]%
- {\remappositionframed{#2}{\tbPOSprefix#1}%
- \dotablebpos{\tbPOSprefix#1}%
- \doglobal\appendtoks\@EA\dotableepos\@EA{\tbPOSprefix#1}\to\posXCtoks}
+\unexpanded\def\tbXC {\dosingleempty\anch_tables_XC }
+\unexpanded\def\tbGSC{\dosingleempty\anch_tables_GSC}
+\unexpanded\def\tbGFC{\dosingleempty\anch_tables_GFC}
+\unexpanded\def\tbGTC{\dosingleempty\anch_tables_GTC}
-\def\dododoGSC[#1:#2:#3]%
- {\doglobal\appendtoks\dodododoGSC[#1:#2]\to\posXCtoks\NC}
+\def\anch_table_check_state
+ {\iftrialtypesetting
+ \global\settrue\tablehaspositions
+ \firstargumentfalse
+ \fi}
-\def\dodoGSC[#1]%
- {\def\docommand##1{\dododoGSC[##1:##1]}%
- \processcommalist[#1]\docommand}
+\def\anch_tables_XC [#1]{\anch_table_check_state\iffirstargument\anch_tables_indeed_XC [#1]\else\expandafter\fi\NC}
+\def\anch_tables_GSC[#1]{\anch_table_check_state\iffirstargument\anch_tables_indeed_GSC[#1]\else\expandafter\NC\fi}
+\def\anch_tables_GFC[#1]{\anch_table_check_state\iffirstargument\anch_tables_indeed_GFC[#1]\else\expandafter\NC\fi}
+\def\anch_tables_GTC[#1]{\anch_table_check_state\iffirstargument\anch_tables_indeed_GTC[#1]\else\expandafter\NC\fi}
-\def\dodododoGFC[#1:#2:#3]%
- {\remappositionframed{#2}{\tbPOSprefix#1}%
- \dotablebpos{\tbPOSprefix#1}}
+\def\anch_tables_indeed_XC[#1]%
+ {{\let\NC\relax\processcommalist[#1]\anch_tables_step_XC}}
-\def\dododoGFC[#1]%
- {\def\docommand##1{\dodododoGFC[##1:##1]}%
- \processcommalist[#1]\docommand}
+\def\anch_tables_step_XC#1%
+ {\anch_tables_step_indeed_XC[#1]}
-\def\dodoGFC[#1]%
- {\doglobal\appendtoks\dododoGFC[#1]\to\posXCtoks\NC}
+\def\anch_tables_step_indeed_XC[#1#2]%
+ {\if#1>\anch_tables_indeed_GFC [#2:#2]\else
+ \if#1+\anch_tables_indeed_GFC [#2:#2]\else
+ \if#1<\anch_tables_indeed_GTC [#2:#2]\else
+ \if#1-\anch_tables_indeed_GTC [#2:#2]\else
+ \if#1=\anch_tables_indeed_GSC [#2:#2]\else
+ \anch_tables_indeed_GSC[#1#2:#1#2]\fi\fi\fi\fi\fi}
-\def\dododododoGTC[#1:#2]%
- {\dotableepos{\tbPOSprefix#1}}
+\def\anch_tables_indeed_GSC[#1]%
+ {\processcommalist[#1]\anch_tables_step_GSC}
-\def\dodododoGTC[#1]%
- {\def\docommand##1{\dododododoGTC[##1:##1]}%
- \processcommalist[#1]\docommand}
+\def\anch_tables_step_GSC#1%
+ {\anch_tables_append_GSC[#1:#1]}
-\def\dododoGTC[#1]%
- {\doglobal\appendtoks\dodododoGTC[#1]\to\posXCtoks}
+\def\anch_tables_append_GSC[#1:#2:#3]%
+ {\doglobal\appendtoks\anch_tables_process_GSC[#1:#2]\to\posXCtoks\NC}
-\def\dodoGTC[#1]%
- {\doglobal\appendtoks\dododoGTC[#1]\to\posXCtoks\NC}
+\def\anch_tables_process_GSC[#1:#2]%
+ {\remappositionframed{#2}{\tbPOSprefix#1}%
+ \anch_tabulate_bpos{\tbPOSprefix#1}%
+ \doglobal\appendtoks\@EA\anch_tabulate_epos\@EA{\tbPOSprefix#1}\to\posXCtoks}
-\def\dodododoXC[#1#2]%
- {\if#1>\dodoGFC [#2:#2]\else
- \if#1+\dodoGFC [#2:#2]\else
- \if#1<\dodoGTC [#2:#2]\else
- \if#1-\dodoGTC [#2:#2]\else
- \if#1=\dodoGSC [#2:#2]\else
- \dodoGSC[#1#2:#1#2]\fi\fi\fi\fi\fi}
+\def\anch_tables_indeed_GFC[#1]%
+ {\doglobal\appendtoks\anch_tables_delayed_GFC[#1]\to\posXCtoks\NC}
-\def\dododoXC#1%
- {\dodododoXC[#1]}
+\def\anch_tables_delayed_GFC[#1]%
+ {\processcommalist[#1]\anch_tables_step_GFC}
-\def\dodoXC[#1]%
- {{\let\NC\relax\processcommalist[#1]\dododoXC}}
+\def\anch_tables_step_GFC#1%
+ {\anch_tables_process_GFC[#1:#1]}
-\def\@@checktablepositionstate
- {\iftrialtypesetting
- \global\settrue\tablehaspositions
- \firstargumentfalse
- \fi}
+\def\anch_tables_process_GFC[#1:#2:#3]%
+ {\remappositionframed{#2}{\tbPOSprefix#1}%
+ \anch_tabulate_bpos{\tbPOSprefix#1}}
+
+\def\anch_tables_indeed_GTC[#1]%
+ {\doglobal\appendtoks\anch_tables_delayed_GTC[#1]\to\posXCtoks\NC}
-\def\doGSC[#1]{\@@checktablepositionstate\iffirstargument\dodoGSC[#1]\else\expandafter\NC\fi}
-\def\doGFC[#1]{\@@checktablepositionstate\iffirstargument\dodoGFC[#1]\else\expandafter\NC\fi}
-\def\doGTC[#1]{\@@checktablepositionstate\iffirstargument\dodoGTC[#1]\else\expandafter\NC\fi}
-\def\doXC [#1]{\@@checktablepositionstate\iffirstargument\dodoXC [#1]\else\expandafter\fi\NC}
+\def\anch_tables_delayed_GTC[#1]%
+ {\doglobal\appendtoks\anch_tables_process_GTC[#1]\to\posXCtoks}
-\def\tbGSC{\dosingleempty\doGSC}
-\def\tbGFC{\dosingleempty\doGFC}
-\def\tbGTC{\dosingleempty\doGTC}
-\def\tbXC {\dosingleempty\doXC }
+\def\anch_tables_process_GTC[#1]%
+ {\processcommalist[#1]\anch_tables_step_GTC}
-%D The amount of code to support tables and tabulation is
-%D rather minimalistic.
+\def\anch_tables_step_GTC#1%
+ {\anch_tables_step_indeed_GTC[#1:#1]}
+
+\def\anch_tables_step_indeed_GTC[#1:#2]%
+ {\anch_tabulate_epos{\tbPOSprefix#1}}
+
+%D The amount of code to support tables and tabulation is rather
+%D minimalistic.
\let\tabulatepos\tablepos
@@ -177,7 +185,7 @@
\def\tabulateEQpos
{\setbox\scratchbox\hbox{\tabulateEQ}%
\hbox to \wd\scratchbox{\hss\kern\zeropoint\tabulatepos\hss}%
- \hskip-\wd\scratchbox
+ \kern-\wd\scratchbox
\box\scratchbox}
\appendtoks
@@ -187,31 +195,30 @@
% We need to handle paragraphs as well.
-\let\doflushtabulateepos\relax
+\let\anch_tabulate_flush_epos\relax
-\def\dotabulatebpos
+\def\anch_tabulate_bpos_indeed
{\bpos}
-\def\dotabulateepos#1%
+\def\anch_tabulate_epos_indeed#1%
{\ifvoid\b_tabl_tabulate_current\c_tabl_tabulate_column
\epos{#1}%
- \glet\doflushtabulateepos\relax
+ \glet\anch_tabulate_flush_epos\relax
\else
- \gdef\doflushtabulateepos{\epos{#1}}%
+ \gdef\anch_tabulate_flush_epos{\epos{#1}}%
\fi}
\def\flushtabulatesplitbox
{\box\b_tabl_tabulate
- \iftrialtypesetting\else\ifconditional\tablehaspositions\doflushtabulateepos\fi\fi}
+ \iftrialtypesetting\else\ifconditional\tablehaspositions\anch_tabulate_flush_epos\fi\fi}
\appendtoks
- \let\dotablebpos\dotabulatebpos % ?
- \let\dotableepos\dotabulateepos % ?
- \glet\doflushtabulateepos\relax
+ \let\anch_tabulate_bpos\anch_tabulate_bpos_indeed % ?
+ \let\anch_tabulate_epos\anch_tabulate_epos_indeed % ?
+ \glet\anch_tabulate_flush_epos\relax
\to \everytabulate
-%D In order to prevent potential clashes with abbreviations,
-%D postpone the mapping.
+%D In order to prevent potential clashes with abbreviations, postpone the mapping.
\appendtoks
\let\GSC\tbGSC
@@ -223,8 +230,8 @@
%D \macros
%D {definepositionframed}
%D
-%D The next example show how to provide backgrounds to table
-%D cells. First we define some framed backgrounds.
+%D The next example show how to provide backgrounds to table cells. First we define
+%D some framed backgrounds.
%D
%D \startbuffer
%D \definepositionframed[x][background=color,backgroundcolor=red]
@@ -244,8 +251,7 @@
%D \stoptabulate
%D \stopbuffer
%D
-%D The table itself defines three areas (a, b and~c) using
-%D these frames.
+%D The table itself defines three areas (a, b and~c) using these frames.
%D
%D \typebuffer
%D % \getbuffer
@@ -270,9 +276,8 @@
\let\XC \tbXC
\to \everytable
-%D In the previous example, we could have provided an overlay to
-%D the framed definition. A more direct approach is demonstrated
-%D below:
+%D In the previous example, we could have provided an overlay to the framed definition.
+%D A more direct approach is demonstrated below:
%D
%D \startbuffer
%D \def\cw#1{\color[white]{#1}}
@@ -291,8 +296,7 @@
%D
%D \typebuffer \getbuffer
%D
-%D The definition of the table looks about the same as the
-%D previous one:
+%D The definition of the table looks about the same as the previous one:
%D
%D \startbuffer
%D \starttable[|c|c|c|]
@@ -347,22 +351,26 @@
% \definepositionframed[y][background=color,fillcolor=green]
% \definepositionframed[z][background=color,fillcolor=blue]
-\def\remappositionframed#1#2% from to
+\unexpanded\def\remappositionframed#1#2% from to
{\copyposition{b:#1}{b:#2}%
\copyposition{e:#1}{e:#2}%
- \dosetpositionaction{b:#2}{\dopositionaction{b:#1}}}
+ \anch_positions_set_action{b:#2}{\dopositionaction{b:#1}}}
\unexpanded\def\definepositionframed
- {\dodoubleargument\dodefinepositionframed}
+ {\dodoubleargument\anch_framed_define}
-\def\dodefinepositionframed[#1][#2]%
- {\dosetpositionaction{b:#1}{\dopositionframed[#1][#2]}}
+\def\anch_framed_define[#1][#2]%
+ {\anch_positions_set_action{b:#1}{\anch_framed_handle[#1][#2]}}
+
+\unexpanded\def\anch_framed_handle
+ {\bgroup
+ \anch_framed_indeed}
\unexpanded\def\positionframed
{\bgroup
- \dodoubleempty\dopositionframed}
+ \dodoubleempty\anch_framed_indeed}
-\def\dopositionframed[#1][#2]%
+\def\anch_framed_indeed[#1][#2]%
{\setbox\scratchbox\hbox
{\scratchwidth \dimexpr\MPx{e:#1}-\MPx{b:#1}\relax
\scratchdepth \dimexpr\MPy{b:#1}-\MPy{e:#1}+\MPd{e:#1}\relax
diff --git a/Master/texmf-dist/tex/context/base/attr-col.lua b/Master/texmf-dist/tex/context/base/attr-col.lua
index c592d1dc1cb..7c6b7909ba2 100644
--- a/Master/texmf-dist/tex/context/base/attr-col.lua
+++ b/Master/texmf-dist/tex/context/base/attr-col.lua
@@ -15,8 +15,11 @@ if not modules then modules = { } end modules ['attr-col'] = {
local type = type
local format = string.format
local concat = table.concat
+local min, max, floor = math.min, math.max, math.floor
-local attributes, nodes = attributes, nodes
+local attributes, nodes, utilities, logs, backends, storage = attributes, nodes, utilities, logs, backends, storage
+local commands, context, interfaces = commands, context, interfaces
+local tex = tex
local allocate = utilities.storage.allocate
local setmetatableindex = table.setmetatableindex
@@ -31,11 +34,14 @@ local report_transparencies = logs.reporter("transparencies","support")
-- nb: attributes: color etc is much slower than normal (marks + literals) but ...
-- nb. too many "0 g"s
-local states = attributes.states
-local tasks = nodes.tasks
-local nodeinjections = backends.nodeinjections
-local registrations = backends.registrations
-local unsetvalue = attributes.unsetvalue
+local states = attributes.states
+local tasks = nodes.tasks
+local nodeinjections = backends.nodeinjections
+local registrations = backends.registrations
+local unsetvalue = attributes.unsetvalue
+
+local registerstorage = storage.register
+local formatters = string.formatters
-- We can distinguish between rules and glyphs but it's not worth the trouble. A
-- first implementation did that and while it saves a bit for glyphs and rules, it
@@ -63,7 +69,7 @@ local unsetvalue = attributes.unsetvalue
-- colors.strings[color] = "return colors." .. colorspace .. "(" .. concat({...},",") .. ")"
-- end
--
--- storage.register("attributes/colors/data", colors.strings, "attributes.colors.data") -- evaluated
+-- registerstorage("attributes/colors/data", colors.strings, "attributes.colors.data") -- evaluated
--
-- We assume that only processcolors are defined in the format.
@@ -83,15 +89,23 @@ colors.default = 1
colors.main = nil
colors.triggering = true
colors.supported = true
+colors.model = "all"
+
+local data = colors.data
+local values = colors.values
+local registered = colors.registered
-storage.register("attributes/colors/values", colors.values, "attributes.colors.values")
-storage.register("attributes/colors/registered", colors.registered, "attributes.colors.registered")
+local numbers = attributes.numbers
+local list = attributes.list
-local templates = {
- rgb = "r:%s:%s:%s",
- cmyk = "c:%s:%s:%s:%s",
- gray = "s:%s",
- spot = "p:%s:%s:%s:%s"
+registerstorage("attributes/colors/values", values, "attributes.colors.values")
+registerstorage("attributes/colors/registered", registered, "attributes.colors.registered")
+
+local f_colors = {
+ rgb = formatters["r:%s:%s:%s"],
+ cmyk = formatters["c:%s:%s:%s:%s"],
+ gray = formatters["s:%s"],
+ spot = formatters["p:%s:%s:%s:%s"],
}
local models = {
@@ -104,17 +118,6 @@ local models = {
cmyk = 4,
}
-colors.model = "all"
-
-local data = colors.data
-local values = colors.values
-local registered = colors.registered
-
-local numbers = attributes.numbers
-local list = attributes.list
-
-local min, max, floor = math.min, math.max, math.floor
-
local function rgbtocmyk(r,g,b) -- we could reduce
return 1-r, 1-g, 1-b, 0
end
@@ -125,9 +128,9 @@ end
local function rgbtogray(r,g,b)
if colors.weightgray then
- return .30*r+.59*g+.11*b
+ return .30*r + .59*g + .11*b
else
- return r/3+g/3+b/3
+ return r/3 + g/3 + b/3
end
end
@@ -135,6 +138,17 @@ local function cmyktogray(c,m,y,k)
return rgbtogray(cmyktorgb(c,m,y,k))
end
+-- not critical so not needed:
+--
+-- local function cmyktogray(c,m,y,k)
+-- local r, g, b = 1.0 - min(1.0,c+k), 1.0 - min(1.0,m+k), 1.0 - min(1.0,y+k)
+-- if colors.weightgray then
+-- return .30*r + .59*g + .11*b
+-- else
+-- return r/3 + g/3 + b/3
+-- end
+-- end
+
-- http://en.wikipedia.org/wiki/HSI_color_space
-- http://nl.wikipedia.org/wiki/HSV_(kleurruimte)
@@ -271,7 +285,7 @@ local function reviver(data,n)
if not v then
local gray = graycolor(0)
d = { gray, gray, gray, gray }
- report_attributes("unable to revive color %s",n or "?")
+ report_attributes("unable to revive color %a",n)
else
local model = colors.forcedmodel(v[1])
if model == 2 then
@@ -309,7 +323,7 @@ function colors.setmodel(name,weightgray)
end
function colors.register(name, colorspace, ...) -- passing 9 vars is faster (but not called that often)
- local stamp = format(templates[colorspace],...)
+ local stamp = f_colors[colorspace](...)
local color = registered[stamp]
if not color then
color = #values + 1
@@ -363,15 +377,15 @@ transparencies.triggering = true
transparencies.attribute = a_transparency
transparencies.supported = true
-storage.register("attributes/transparencies/registered", transparencies.registered, "attributes.transparencies.registered")
-storage.register("attributes/transparencies/values", transparencies.values, "attributes.transparencies.values")
+local registered = transparencies.registered -- we could use a 2 dimensional table instead
+local data = transparencies.data
+local values = transparencies.values
+local f_transparency = formatters["%s:%s"]
-local registered = transparencies.registered -- we could use a 2 dimensional table instead
-local data = transparencies.data
-local values = transparencies.values
-local template = "%s:%s"
+registerstorage("attributes/transparencies/registered", registered, "attributes.transparencies.registered")
+registerstorage("attributes/transparencies/values", values, "attributes.transparencies.values")
-local function inject_transparency (...)
+local function inject_transparency(...)
inject_transparency = nodeinjections.transparency
return inject_transparency(...)
end
@@ -386,7 +400,7 @@ function transparencies.register(name,a,t,force) -- name is irrelevant here (can
-- but then we'd end up with transparencies resources even if we
-- would not use transparencies (but define them only). This is
-- somewhat messy.
- local stamp = format(template,a,t)
+ local stamp = f_transparency(a,t)
local n = registered[stamp]
if not n then
n = #values + 1
diff --git a/Master/texmf-dist/tex/context/base/attr-eff.lua b/Master/texmf-dist/tex/context/base/attr-eff.lua
index 023d1c51b53..4dce5419abc 100644
--- a/Master/texmf-dist/tex/context/base/attr-eff.lua
+++ b/Master/texmf-dist/tex/context/base/attr-eff.lua
@@ -6,9 +6,9 @@ if not modules then modules = { } end modules ['attr-eff'] = {
license = "see context related readme files"
}
-local format = string.format
-
-local attributes, nodes = attributes, nodes
+local commands, interfaces = commands, interfaces
+local attributes, nodes, backends, utilities = attributes, nodes, backends, utilities
+local tex = tex
local states = attributes.states
local tasks = nodes.tasks
@@ -16,6 +16,10 @@ local nodeinjections = backends.nodeinjections
local settexattribute = tex.setattribute
local allocate = utilities.storage.allocate
local setmetatableindex = table.setmetatableindex
+local formatters = string.formatters
+
+local variables = interfaces.variables
+local v_normal = variables.normal
attributes.effects = attributes.effects or { }
local effects = attributes.effects
@@ -27,14 +31,14 @@ effects.values = effects.values or { }
effects.registered = effects.registered or { }
effects.attribute = a_effect
-storage.register("attributes/effects/registered", effects.registered, "attributes.effects.registered")
-storage.register("attributes/effects/values", effects.values, "attributes.effects.values")
+local data = effects.data
+local registered = effects.registered
+local values = effects.values
-local template = "%s:%s:%s"
+local f_stamp = formatters["%s:%s:%s"]
-local data = effects.data
-local registered = effects.registered
-local values = effects.values
+storage.register("attributes/effects/registered", registered, "attributes.effects.registered")
+storage.register("attributes/effects/values", values, "attributes.effects.values")
-- valid effects: normal inner outer both hidden (stretch,rulethickness,effect)
@@ -66,12 +70,22 @@ effects.handler = nodes.installattributehandler {
processor = states.process,
}
-local function register(effect,stretch,rulethickness)
- local stamp = format(template,effect,stretch,rulethickness)
+local function register(specification)
+ local alternative, stretch, rulethickness
+ if specification then
+ alternative = specification.alternative or v_normal
+ stretch = specification.stretch or 0
+ rulethickness = specification.rulethickness or 0
+ else
+ alternative = v_normal
+ stretch = 0
+ rulethickness = 0
+ end
+ local stamp = f_stamp(alternative,stretch,rulethickness)
local n = registered[stamp]
if not n then
n = #values + 1
- values[n] = { effect, stretch, rulethickness }
+ values[n] = { alternative, stretch, rulethickness }
registered[stamp] = n
end
return n
@@ -88,10 +102,10 @@ effects.enable = enable
local enabled = false
-function commands.triggereffect(effect,stretch,rulethickness)
+function commands.triggereffect(specification)
if not enabled then
enable()
enabled = true
end
- settexattribute(a_effect,register(effect,stretch,rulethickness))
+ settexattribute(a_effect,register(specification))
end
diff --git a/Master/texmf-dist/tex/context/base/attr-eff.mkiv b/Master/texmf-dist/tex/context/base/attr-eff.mkiv
index c5c94537c14..43f575a7a69 100644
--- a/Master/texmf-dist/tex/context/base/attr-eff.mkiv
+++ b/Master/texmf-dist/tex/context/base/attr-eff.mkiv
@@ -17,38 +17,39 @@
\unprotect
-\gdef\dotriggereffect#1#2#3%
- {\ctxcommand{triggereffect('#1',#2,\number\dimexpr#3\relax)}}
+\installcorenamespace{effect}
-\unexpanded\def\setupeffect
- {\dodoubleargument\dosetupeffect}
+\installcommandhandler \??effect {effect} \??effect
-\def\dosetupeffect[#1][#2]%
- {\getparameters[\??et#1][#2]}
+\setupeffect
+ [\c!method=\v!none,
+ \c!stretch=\zerocount,
+ \c!rulethickness=\zeropoint,
+ \c!alternative=\v!normal]
-\unexpanded\def\defineeffect
- {\dodoubleargument\dodefineeffect}
-
-\def\dodefineeffect[#1][#2]%
- {\getparameters[\??et#1][\c!method=\v!none,\c!stretch=0,\c!rulethickness=\zeropoint,\c!alternative=\v!normal,#2]%
- \doif{\getvalue{\??et#1\c!method}}\v!command
- {\setugvalue{\e!start#1}{\starteffect[#1]}%
- \setugvalue{\e!stop #1}{\stopeffect}}}
-
-% yes or no grouped
+\appendtoks
+ \edef\p_method{\effectparameter\c!method}%
+ \ifx\p_method\v!method
+ \setuxvalue{\e!start\currenteffect}{\starteffect[#1]}%
+ \setuxvalue{\e!stop \currenteffect}{\stopeffect}%
+ \fi
+\to \everydefineeffect
\unexpanded\def\starteffect[#1]%
- {\dotriggereffect
- {\csname\??et#1\c!alternative \endcsname}%
- {\csname\??et#1\c!stretch \endcsname}%
- {\csname\??et#1\c!rulethickness\endcsname}}
+ {\ctxcommand{triggereffect{
+ alternative = "\namedeffectparameter{#1}\c!alternative",
+ stretch = \number\namedeffectparameter{#1}\c!stretch,
+ rulethickness = \number\dimexpr\namedeffectparameter{#1}\c!rulethickness\relax
+ }}}
\unexpanded\def\stopeffect % can be special
- {\dotriggereffect\v!normal0\zeropoint}
+ {\ctxcommand{triggereffect()}} % v!normal 0 0
\unexpanded\def\effect[#1]%
{\groupedcommand{\starteffect[#1]}{\stopeffect}}
+% yes or no grouped
+
\defineeffect [\v!inner] [\c!alternative=\v!inner,\c!rulethickness=.25pt]
\defineeffect [\v!outer] [\c!alternative=\v!outer,\c!rulethickness=.25pt]
\defineeffect [\v!both] [\c!alternative=\v!both, \c!rulethickness=.25pt]
diff --git a/Master/texmf-dist/tex/context/base/attr-ini.lua b/Master/texmf-dist/tex/context/base/attr-ini.lua
index f3714fcb4d9..206a86d79b5 100644
--- a/Master/texmf-dist/tex/context/base/attr-ini.lua
+++ b/Master/texmf-dist/tex/context/base/attr-ini.lua
@@ -6,6 +6,8 @@ if not modules then modules = { } end modules ['attr-ini'] = {
license = "see context related readme files"
}
+local commands, context, nodes, storage = commands, context, nodes, storage
+
local next, type = next, type
--[[ldx--
@@ -13,11 +15,10 @@ local next, type = next, type
symbolic names later on.
--ldx]]--
-attributes = attributes or { }
-
-local attributes, nodes = attributes, nodes
+attributes = attributes or { }
+local attributes = attributes
--- todo: local and then gobals ... first loaded anyway
+local sharedstorage = storage.shared
attributes.names = attributes.names or { }
attributes.numbers = attributes.numbers or { }
@@ -26,15 +27,14 @@ attributes.states = attributes.states or { }
attributes.handlers = attributes.handlers or { }
attributes.unsetvalue = -0x7FFFFFFF
-local names, numbers, list = attributes.names, attributes.numbers, attributes.list
+local names = attributes.names
+local numbers = attributes.numbers
+local list = attributes.list
storage.register("attributes/names", names, "attributes.names")
storage.register("attributes/numbers", numbers, "attributes.numbers")
storage.register("attributes/list", list, "attributes.list")
-names [0] = "fontdynamic"
-numbers["fontdynamic"] = 0
-
function attributes.define(name,number) -- at the tex end
if not numbers[name] then
numbers[name] = number
@@ -43,13 +43,19 @@ function attributes.define(name,number) -- at the tex end
end
end
+--[[ldx--
+We reserve this one as we really want it to be always set (faster).
+--ldx]]--
+
+names[0], numbers["fontdynamic"] = "fontdynamic", 0
+
--[[ldx--
We can use the attributes in the range 127-255 (outside user space). These
are only used when no attribute is set at the \TEX\ end which normally
happens in .
--ldx]]--
-storage.shared.attributes_last_private = storage.shared.attributes_last_private or 127
+sharedstorage.attributes_last_private = sharedstorage.attributes_last_private or 127
-- to be considered (so that we can use an array access):
--
@@ -57,10 +63,10 @@ storage.shared.attributes_last_private = storage.shared.attributes_last_private
--
-- setmetatable(private, {
-- __index = function(t,name)
--- local number = storage.shared.attributes_last_private or 127
+-- local number = sharedstorage.attributes_last_private
-- if number < 1023 then -- tex.count.minallocatedattribute - 1
-- number = number + 1
--- storage.shared.attributes_last_private = number
+-- sharedstorage.attributes_last_private = number
-- end
-- numbers[name], names[number], list[number] = number, name, { }
-- private[name] = number
@@ -74,12 +80,12 @@ storage.shared.attributes_last_private = storage.shared.attributes_last_private
function attributes.private(name) -- at the lua end (hidden from user)
local number = numbers[name]
if not number then
- local last = storage.shared.attributes_last_private or 127
+ local last = sharedstorage.attributes_last_private
if last < 1023 then -- tex.count.minallocatedattribute - 1
last = last + 1
- storage.shared.attributes_last_private = last
+ sharedstorage.attributes_last_private = last
else
- report_attribute("no more room for private attributes") -- fatal
+ report_attribute("no more room for private attributes")
os.exit()
end
number = last
@@ -88,7 +94,7 @@ function attributes.private(name) -- at the lua end (hidden from user)
return number
end
--- new (actually a tracer)
+-- tracers
local report_attribute = logs.reporter("attributes")
@@ -99,7 +105,7 @@ local function showlist(what,list)
while a do
local number, value = a.number, a.value
i = i + 1
- report_attribute("%s %2i: attribute %3i, value %4i, name %s",tostring(what),i,number,value,names[number] or '?')
+ report_attribute("%S %2i: attribute %3i, value %4i, name %a",what,i,number,value,names[number])
a = a.next
end
end
diff --git a/Master/texmf-dist/tex/context/base/attr-ini.mkiv b/Master/texmf-dist/tex/context/base/attr-ini.mkiv
index a1550b4be98..ac210c98e5a 100644
--- a/Master/texmf-dist/tex/context/base/attr-ini.mkiv
+++ b/Master/texmf-dist/tex/context/base/attr-ini.mkiv
@@ -14,8 +14,8 @@
\writestatus{loading}{ConTeXt Attribute Macros / Initialization}
%D Although it's still somewhat experimental, here we introduce code
-%D related to attributes. Housekeeping will move completely to Lua
-%D and \newattribute will go away.
+%D related to attributes. Housekeeping will move completely to \LUA\
+%D and \type {\newattribute} will go away.
\unprotect
@@ -27,14 +27,16 @@
\unexpanded\def\pushattribute#1%
{\global\advance\csname\??attributestack\string#1\endcsname\plusone
- \global\expandafter\mathchardef\csname\??attributestack\string#1:\number\csname\??attributestack\string#1\endcsname\endcsname\attribute#1}
+ \expandafter\xdef\csname\??attributestack\string#1:\number\csname\??attributestack\string#1\endcsname\endcsname{\number\attribute#1}}
\unexpanded\def\popattribute#1%
- {\attribute#1\csname\??attributestack\string#1:\number\csname\??attributestack\string#1\endcsname\endcsname
+ {\attribute#1\csname\??attributestack\string#1:\number\csname\??attributestack\string#1\endcsname\endcsname\relax
\global\advance\csname\??attributestack\string#1\endcsname\minusone}
\unexpanded\def\installattributestack#1%
- {\expandafter\newcount\csname\??attributestack\string#1\endcsname}
+ {\ifcsname\??attributestack\string#1\endcsname \else
+ \expandafter\newcount\csname\??attributestack\string#1\endcsname
+ \fi}
\newtoks \attributesresetlist
@@ -83,12 +85,13 @@
%D For the moment we put this here (later it will move to where it's used):
\definesystemattribute [state]
+\definesystemattribute [color] [public]
+\definesystemattribute [colormodel] [public,global]
\definesystemattribute [skip]
\definesystemattribute [penalty]
-\definesystemattribute [colormodel] [public,global]
-\definesystemattribute [color] [public]
\definesystemattribute [transparency] [public]
\definesystemattribute [background] [public]
+\definesystemattribute [alignbackground] [public]
\definesystemattribute [colorintent] [public]
\definesystemattribute [negative] [public]
\definesystemattribute [effect] [public]
diff --git a/Master/texmf-dist/tex/context/base/attr-lay.lua b/Master/texmf-dist/tex/context/base/attr-lay.lua
index bcdc541f7b6..4bcc70b0ca1 100644
--- a/Master/texmf-dist/tex/context/base/attr-lay.lua
+++ b/Master/texmf-dist/tex/context/base/attr-lay.lua
@@ -10,12 +10,18 @@ if not modules then modules = { } end modules ['attr-lay'] = {
-- but when we need it stacked layers might show up too; the next function based
-- approach can be replaced by static (metatable driven) resolvers
+-- maybe use backends.registrations here too
+
local type = type
-local format = string.format
local insert, remove = table.insert, table.remove
+local attributes, nodes, utilities, logs, backends = attributes, nodes, utilities, logs, backends
+local commands, context, interfaces = commands, context, interfaces
+local tex = tex
+
local allocate = utilities.storage.allocate
local setmetatableindex = table.setmetatableindex
+local formatters = string.formatters
local report_viewerlayers = logs.reporter("viewerlayers")
@@ -26,8 +32,6 @@ local report_viewerlayers = logs.reporter("viewerlayers")
-- nb. too many "0 g"s
-- nb: more local tables
-local attributes, nodes = attributes, nodes
-
attributes.viewerlayers = attributes.viewerlayers or { }
local viewerlayers = attributes.viewerlayers
@@ -57,22 +61,42 @@ local texgetattribute = tex.getattribute
local texsettokenlist = tex.settoks
local unsetvalue = attributes.unsetvalue
-storage.register("attributes/viewerlayers/registered", viewerlayers.registered, "attributes.viewerlayers.registered")
-storage.register("attributes/viewerlayers/values", viewerlayers.values, "attributes.viewerlayers.values")
-storage.register("attributes/viewerlayers/scopes", viewerlayers.scopes, "attributes.viewerlayers.scopes")
+local nodepool = nodes.pool
+
+local data = viewerlayers.data
+local values = viewerlayers.values
+local listwise = viewerlayers.listwise
+local registered = viewerlayers.registered
+local scopes = viewerlayers.scopes
+
+local f_stamp = formatters["%s"]
-local data = viewerlayers.data
-local values = viewerlayers.values
-local listwise = viewerlayers.listwise
-local registered = viewerlayers.registered
-local scopes = viewerlayers.scopes
-local template = "%s"
+storage.register("attributes/viewerlayers/registered", registered, "attributes.viewerlayers.registered")
+storage.register("attributes/viewerlayers/values", values, "attributes.viewerlayers.values")
+storage.register("attributes/viewerlayers/scopes", scopes, "attributes.viewerlayers.scopes")
+
+local layerstacker = utilities.stacker.new("layers") -- experiment
+
+layerstacker.mode = "stack"
+layerstacker.unset = attributes.unsetvalue
+
+viewerlayers.resolve_begin = layerstacker.resolve_begin
+viewerlayers.resolve_step = layerstacker.resolve_step
+viewerlayers.resolve_end = layerstacker.resolve_end
+
+function commands.cleanuplayers()
+ layerstacker.clean()
+ -- todo
+end
-- stacked
+local function startlayer(...) startlayer = nodeinjections.startlayer return startlayer(...) end
+local function stoplayer (...) stoplayer = nodeinjections.stoplayer return stoplayer (...) end
+
local function extender(viewerlayers,key)
if viewerlayers.supported and key == "none" then
- local d = nodeinjections.stoplayer()
+ local d = stoplayer()
viewerlayers.none = d
return d
end
@@ -82,17 +106,23 @@ local function reviver(data,n)
if viewerlayers.supported then
local v = values[n]
if v then
- local d = nodeinjections.startlayer(v)
+ local d = startlayer(v)
data[n] = d
return d
else
- report_viewerlayers("error, unknown reference '%s'",tostring(n))
+ report_viewerlayers("error: unknown reference %a",tostring(n))
end
end
end
-setmetatableindex(viewerlayers, extender)
-setmetatableindex(viewerlayers.data, reviver)
+setmetatableindex(viewerlayers,extender)
+setmetatableindex(viewerlayers.data,reviver)
+
+-- !!!! TEST CODE !!!!
+
+layerstacker.start = function(...) local f = nodeinjections.startstackedlayer layerstacker.start = f return f(...) end
+layerstacker.stop = function(...) local f = nodeinjections.stopstackedlayer layerstacker.stop = f return f(...) end
+layerstacker.change = function(...) local f = nodeinjections.changestackedlayer layerstacker.change = f return f(...) end
local function initializer(...)
return states.initialize(...)
@@ -103,7 +133,8 @@ attributes.viewerlayers.handler = nodes.installattributehandler {
namespace = viewerlayers,
initializer = initializer,
finalizer = states.finalize,
- processor = states.stacked,
+ -- processor = states.stacked,
+ processor = states.stacker,
}
local stack, enabled, global = { }, false, false
@@ -132,7 +163,7 @@ local function register(name,lw) -- if not inimode redefine data[n] in first cal
if not enabled then
viewerlayers.enable(true)
end
- local stamp = format(template,name)
+ local stamp = f_stamp(name)
local n = registered[stamp]
if not n then
n = #values + 1
@@ -149,12 +180,16 @@ function viewerlayers.setfeatures(hasorder)
viewerlayers.hasorder = hasorder
end
+local usestacker = true -- new, experimental
+
function viewerlayers.start(name)
--- if not enabled then
--- viewerlayers.enable(true)
--- end
- insert(stack,texgetattribute(a_viewerlayer))
- local a = register(name) or unsetvalue
+ local a
+ if usestacker then
+ a = layerstacker.push(register(name) or unsetvalue)
+ else
+ insert(stack,texgetattribute(a_viewerlayer))
+ a = register(name) or unsetvalue
+ end
if global or scopes[name] == v_global then
scopes[a] = v_global -- messy but we don't know the attributes yet
texsetattribute("global",a_viewerlayer,a)
@@ -165,14 +200,21 @@ function viewerlayers.start(name)
end
function viewerlayers.stop()
- local a = remove(stack)
- if a >= 0 then
+ local a
+ if usestacker then
+ a = layerstacker.pop()
+ else
+ a = remove(stack)
+ end
+ if not a then
+ -- error
+ elseif a >= 0 then
if global or scopes[a] == v_global then
texsetattribute("global",a_viewerlayer,a)
else
texsetattribute(a_viewerlayer,a)
end
- texsettokenlist("currentviewerlayertoks",values[a])
+ texsettokenlist("currentviewerlayertoks",values[a] or "")
else
if global or scopes[a] == v_global then
texsetattribute("global",a_viewerlayer,unsetvalue)
@@ -197,9 +239,9 @@ function viewerlayers.define(settings)
end
end
-commands.defineviewerlayer = viewerlayers.define
-commands.startviewerlayer = viewerlayers.start
-commands.stopviewerlayer = viewerlayers.stop
+commands.defineviewerlayer = viewerlayers.define
+commands.startviewerlayer = viewerlayers.start
+commands.stopviewerlayer = viewerlayers.stop
function commands.definedviewerlayer(settings)
viewerlayers.define(settings)
diff --git a/Master/texmf-dist/tex/context/base/attr-lay.mkiv b/Master/texmf-dist/tex/context/base/attr-lay.mkiv
index 67cd204e2f6..9c9c3318ef1 100644
--- a/Master/texmf-dist/tex/context/base/attr-lay.mkiv
+++ b/Master/texmf-dist/tex/context/base/attr-lay.mkiv
@@ -13,51 +13,51 @@
\writestatus{loading}{ConTeXt Attribute Macros / Viewerlayers}
+%D Currently there is a limitation in mixed inline usage. This has to do with the fact
+%D that we have a stacked model but cannot determine where to revert to (as we can
+%D have AABBCCAA ranges). Maybe I'll solve that one day. It only affects nested inline
+%D layers and these make not much sense anyway. We'd have to store the complete nesting
+%D stack in the attribute in order to be able to cross pages and that demands a new
+%D mechanism.
+
\unprotect
\registerctxluafile{attr-lay}{1.001}
% needs to work over stopitemize grouping etc
-% \def\registerviewerlayer#1#2% global !
-% {\setxvalue{\??ql:#1}{\global\attribute\viewerlayerattribute\ctxlua{tex.write(attributes.viewerlayers.register('#2'))} }}
-%
-% \setevalue{\??ql:}{\global\attribute\viewerlayerattribute\attributeunsetvalue}
+\installcorenamespace{viewerlayer}
+
+\installcommandhandler \??viewerlayer {viewerlayer} \??viewerlayer
-\getparameters
- [\??lr]
+\setupviewerlayer
[\c!state=\v!start,
\c!title=,
\c!printable=\v!yes,
\c!scope=\v!local, % maybe global but needs checking with layout
\c!method=\v!none]
-\def\defineviewerlayer
- {\dodoubleargument\dodefineviewerlayer}
-
-\def\dodefineviewerlayer[#1][#2]% document wide properties
- {\begingroup
- \getparameters[\??lr][#2]%
- \ctxcommand{defineviewerlayer{
- tag = "#1",
- title = "\@@lrtitle",
- visible = "\@@lrstate",
- editable = "\v!yes",
- printable = "\@@lrprintable",
- scope = "\@@lrscope"
- }}%
- \doif\@@lrmethod\v!command
- {\setugvalue{\e!start#1}{\startviewerlayer[#1]}%
- \setugvalue{\e!stop #1}{\stopviewerlayer }}%
- \endgroup}
-
-\unexpanded\def\startviewerlayer[#1]{\ctxcommand{startviewerlayer("#1")}} % not grouped
-\unexpanded\def\stopviewerlayer {\ctxcommand{stopviewerlayer()}} % not grouped
+\appendtoks
+ \ctxcommand{defineviewerlayer{
+ tag = "\currentviewerlayer",
+ title = "\viewerlayerparameter\c!title",
+ visible = "\viewerlayerparameter\c!state",
+ editable = "\v!yes",
+ printable = "\viewerlayerparameter\c!printable",
+ scope = "\viewerlayerparameter\c!scope"
+ }}%
+ \doif{\viewerlayerparameter\c!method}\v!command
+ {\setuxvalue{\e!start#1}{\startviewerlayer[\currentviewerlayer]}%
+ \setuxvalue{\e!stop #1}{\stopviewerlayer}}%
+\to \everydefineviewerlayer
+
+\unexpanded\def\startviewerlayer[#1]{\ctxcommand{startviewerlayer("#1")}} % not grouped
+\unexpanded\def\stopviewerlayer {\ctxcommand{stopviewerlayer()}} % not grouped
\unexpanded\def\viewerlayer [#1]{\groupedcommand{\startviewerlayer[#1]}{\stopviewerlayer}} % grouped
% some day we will keep this at the lua end as the info is only needed there
-\let\currentviewerlayer\empty \newtoks\currentviewerlayertoks % soon we can set macros at the lua end
+\newtoks\currentviewerlayertoks % soon we can set macros at the lua end
\def\currentviewerlayer{\the\currentviewerlayertoks}
@@ -67,7 +67,9 @@
% layout components are implemented rather directly (speed)
-\def\doinitializelayoutcomponent#1%
+\installcorenamespace{layoutcomponentattribute}
+
+\def\attr_layoutcomponent_initialize#1%
{\edef\layoutcomponentboxattribute{\ctxcommand{definedviewerlayer{%
tag = "#1",
title = utilities.strings.nice("#1"), % only here as in steps we have step:
@@ -76,24 +78,28 @@
printable = "\v!yes"
}}}%
\edef\layoutcomponentboxattribute{attr \viewerlayerattribute \layoutcomponentboxattribute\relax}%
- \expandafter\glet\csname\??lr:a:#1\endcsname\layoutcomponentboxattribute}
+ \expandafter\glet\csname\??layoutcomponentattribute#1\endcsname\layoutcomponentboxattribute}
-\def\dosetlayoutcomponentattribute#1% make this faster
- {\expandafter\let\expandafter\layoutcomponentboxattribute\csname\??lr:a:#1\endcsname
+\def\attr_layoutcomponent_set#1% make this faster
+ {\expandafter\let\expandafter\layoutcomponentboxattribute\csname\??layoutcomponentattribute#1\endcsname
\ifx\layoutcomponentboxattribute\relax
- \doinitializelayoutcomponent{#1}% get rid of { }
+ \attr_layoutcomponent_initialize{#1}% get rid of { }
\fi}
-\def\doresetlayoutcomponentattribute
+\def\attr_layoutcomponent_reset
{\let\layoutcomponentboxattribute\empty}
\let\setlayoutcomponentattribute \gobbleoneargument
\let\resetlayoutcomponentattribute\relax
\let\layoutcomponentboxattribute \empty
-\def\showlayoutcomponents
- {\ctxlua{attributes.viewerlayers.enable()}% will go
- \let\setlayoutcomponentattribute \dosetlayoutcomponentattribute
- \let\resetlayoutcomponentattribute\doresetlayoutcomponentattribute}
+\unexpanded\def\showlayoutcomponents
+ {%\ctxlua{attributes.viewerlayers.enable()}% automatic
+ \let\setlayoutcomponentattribute \attr_layoutcomponent_set
+ \let\resetlayoutcomponentattribute\attr_layoutcomponent_reset}
+
+\appendtoks
+ \ctxcommand{cleanuplayers()}%
+\to \everyshipout
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/attr-mkr.lua b/Master/texmf-dist/tex/context/base/attr-mkr.lua
new file mode 100644
index 00000000000..976598fa013
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/attr-mkr.lua
@@ -0,0 +1,26 @@
+if not modules then modules = { } end modules ['attr-mkr'] = {
+ version = 1.001,
+ comment = "companion to attr-mkr.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local markers = nodes.markers or { }
+nodes.markers = markers
+
+local cache = { }
+local numbers = attributes.numbers
+local a_unknown = attributes.private("marker:unknown")
+
+table.setmetatableindex(cache,function(t,k)
+ local k = "marker:" .. k
+ local v = numbers[k] or a_unknown
+ t[k] = v
+ return v
+end)
+
+function markers.get(n,name)
+ local a = cache[name]
+ return a and n[a] or nil
+end
diff --git a/Master/texmf-dist/tex/context/base/attr-mkr.mkiv b/Master/texmf-dist/tex/context/base/attr-mkr.mkiv
new file mode 100644
index 00000000000..c8818ebae7e
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/attr-mkr.mkiv
@@ -0,0 +1,25 @@
+%D \module
+%D [ file=attr-mkr,
+%D version=2013.01.09,
+%D title=\CONTEXT\ Attribute Macros,
+%D subtitle=Markers,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Attribute Macros / Markers}
+
+\unprotect
+
+\registerctxluafile{attr-mkr}{1.001}
+
+\unexpanded\def\definemarker [#1]{\defineattribute[\s!marker:#1]}
+\unexpanded\def\setmarker [#1]#2[#3]{\dosetattribute{\s!marker:#1}{#3}}
+\unexpanded\def\resetmarker [#1]{\dogetattribute{\s!marker:#1}}
+ \def\boxmarker #1#2{attr \numexpr\dogetattributeid{\s!marker:#1}\numexpr \numexpr#2\relax}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/attr-neg.lua b/Master/texmf-dist/tex/context/base/attr-neg.lua
index 4d89cb49b64..c32cec956b2 100644
--- a/Master/texmf-dist/tex/context/base/attr-neg.lua
+++ b/Master/texmf-dist/tex/context/base/attr-neg.lua
@@ -11,8 +11,9 @@ if not modules then modules = { } end modules ['attr-neg'] = {
local format = string.format
-
-local attributes, nodes = attributes, nodes
+local attributes, nodes, utilities, logs, backends = attributes, nodes, utilities, logs, backends
+local commands, context, interfaces = commands, context, interfaces
+local tex = tex
local states = attributes.states
local tasks = nodes.tasks
diff --git a/Master/texmf-dist/tex/context/base/attr-neg.mkiv b/Master/texmf-dist/tex/context/base/attr-neg.mkiv
index 0fc5070f1bd..102b220baca 100644
--- a/Master/texmf-dist/tex/context/base/attr-neg.mkiv
+++ b/Master/texmf-dist/tex/context/base/attr-neg.mkiv
@@ -19,12 +19,12 @@
% positive and negative are preregistered
-\def\dotriggernegative#1{\ctxcommand{triggernegative('#1')}}
+\unexpanded\def\startnegative{\attr_trigger_negative\v!negative}
+\unexpanded\def\stopnegative {\attr_trigger_negative\v!positive}
-\unexpanded\def\startnegative{\dotriggernegative\v!negative}
-\unexpanded\def\stopnegative {\dotriggernegative\v!positive}
+\unexpanded\def\startpositive{\attr_trigger_negative\v!positive}
+\unexpanded\def\stoppositive {\attr_trigger_negative\v!negative}
-\unexpanded\def\startpositive{\dotriggernegative\v!positive}
-\unexpanded\def\stoppositive {\dotriggernegative\v!negative}
+\def\attr_trigger_negative#1{\ctxcommand{triggernegative('#1')}}
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/back-exp.lua b/Master/texmf-dist/tex/context/base/back-exp.lua
index 3ce40a6c58b..4d219a18b80 100644
--- a/Master/texmf-dist/tex/context/base/back-exp.lua
+++ b/Master/texmf-dist/tex/context/base/back-exp.lua
@@ -18,15 +18,18 @@ if not modules then modules = { } end modules ['back-exp'] = {
-- We can optimize the code ... currently the overhead is some 10% for xml + html so
-- there is no hurry.
+-- todo: move critital formatters out of functions
+-- todo: delay loading (apart from basic tag stuff)
+
local next, type = next, type
local format, match, concat, rep, sub, gsub, gmatch, find = string.format, string.match, table.concat, string.rep, string.sub, string.gsub, string.gmatch, string.find
+local validstring = string.valid
local lpegmatch = lpeg.match
-local utfchar, utfbyte, utfsub, utfgsub = utf.char, utf.byte, utf.sub, utf.gsub
+local utfchar, utfbyte, utfvalues = utf.char, utf.byte, utf.values
local insert, remove = table.insert, table.remove
-local topoints = number.topoints
-local utfvalues = string.utfvalues
local fromunicode16 = fonts.mappings.fromunicode16
local sortedhash = table.sortedhash
+local formatters = string.formatters
local trace_export = false trackers.register ("export.trace", function(v) trace_export = v end)
local trace_spacing = false trackers.register ("export.trace.spacing", function(v) trace_spacing = v end)
@@ -88,15 +91,12 @@ local a_reference = attributes.private('reference')
local a_textblock = attributes.private("textblock")
-local has_attribute = node.has_attribute
-local set_attribute = node.set_attribute
local traverse_id = node.traverse_id
local traverse_nodes = node.traverse
local slide_nodelist = node.slide
local texattribute = tex.attribute
local texdimen = tex.dimen
local texcount = tex.count
-local unsetvalue = attributes.unsetvalue
local locate_node = nodes.locate
local references = structures.references
@@ -154,6 +154,8 @@ local somespace = { [0x20] = true, [" "] = true } -- for testing
local entities = { ["&"] = "&", [">"] = ">", ["<"] = "<" }
local attribentities = { ["&"] = "&", [">"] = ">", ["<"] = "<", ['"'] = "quot;" }
+local entityremapper = utf.remapper(entities)
+
local alignmapping = {
flushright = "right",
middle = "center",
@@ -180,7 +182,7 @@ end)
setmetatableindex(specialspaces, function(t,k)
local v = utfchar(k)
t[k] = v
- entities[v] = format("%X;",k)
+ entities[v] = formatters["%X;"](k)
somespace[k] = true
somespace[v] = true
return v
@@ -229,7 +231,7 @@ end)
local function attribute(key,value)
if value and value ~= "" then
- return format(' %s="%s"',key,gsub(value,".",attribentities))
+ return formatters[' %s="%s"'](key,gsub(value,".",attribentities))
else
return ""
end
@@ -258,17 +260,6 @@ local function hashlistdata()
end
end
---~ local spaces = { } -- watch how we also moved the -1 in depth-1 to the creator
-
---~ setmetatableindex(spaces, function(t,k)
---~ if not k then
---~ return ""
---~ end
---~ local s = rep(" ",k-1)
---~ t[k] = s
---~ return s
---~ end)
-
local spaces = utilities.strings.newrepeater(" ",-1)
function structurestags.setattributehash(fulltag,key,value) -- public hash
@@ -300,7 +291,7 @@ local usedstyles = { }
local documenttemplate = [[
document {
- font-size : %s !important ;
+ font-size : %s !important ;
max-width : %s !important ;
text-align : %s !important ;
hyphens : %s !important ;
@@ -354,7 +345,7 @@ local function allusedstyles(xmlfile)
for detail, data in sortedhash(details) do
local s = fontspecification(data.style)
local c = colorspecification(data.color)
- result[#result+1] = format(styletemplate,element,detail,
+ result[#result+1] = formatters[styletemplate](element,detail,
s.style or "inherit",
s.variant or "inherit",
s.weight or "inherit",
@@ -382,11 +373,11 @@ local function allusedimages(xmlfile)
for element, details in sortedhash(usedimages) do
for detail, data in sortedhash(details) do
local name = data.name
- if file.extname(name) == "pdf" then
+ if file.suffix(name) == "pdf" then
-- temp hack .. we will have a remapper
name = file.replacesuffix(name,"svg")
end
- result[#result+1] = format(imagetemplate,element,detail,name,data.width,data.height)
+ result[#result+1] = formatters[imagetemplate](element,detail,name,data.width,data.height)
end
end
return concat(result,"\n\n")
@@ -397,7 +388,7 @@ local function uniqueusedimages()
for element, details in next, usedimages do
for detail, data in next, details do
local name = data.name
- if file.extname(name) == "pdf" then
+ if file.suffix(name) == "pdf" then
unique[file.replacesuffix(name,"svg")] = name
else
unique[name] = name
@@ -475,7 +466,7 @@ function extras.document(result,element,detail,n,fulltag,di)
local key = fields[i]
local value = identity[key]
if value and value ~= "" then
- result[#result+1] = format(" %s=%q",key,value)
+ result[#result+1] = formatters[" %s=%q"](key,value)
end
end
end
@@ -514,7 +505,7 @@ end
function extras.synonym(result,element,detail,n,fulltag,di)
local tag = synonyms[fulltag]
if tag then
- result[#result+1] = format(" tag='%s'",tag)
+ result[#result+1] = formatters[" tag='%s'"](tag)
end
end
@@ -527,7 +518,7 @@ end
function extras.sorting(result,element,detail,n,fulltag,di)
local tag = sortings[fulltag]
if tag then
- result[#result+1] = format(" tag='%s'",tag)
+ result[#result+1] = formatters[" tag='%s'"](tag)
end
end
@@ -575,14 +566,14 @@ end
function extras.description(result,element,detail,n,fulltag,di)
local id = linked[fulltag]
if id then
- result[#result+1] = format(" insert='%s'",id) -- maybe just fulltag
+ result[#result+1] = formatters[" insert='%s'"](id) -- maybe just fulltag
end
end
function extras.descriptionsymbol(result,element,detail,n,fulltag,di)
local id = linked[fulltag]
if id then
- result[#result+1] = format(" insert='%s'",id)
+ result[#result+1] = formatters[" insert='%s'"](id)
end
end
@@ -602,9 +593,9 @@ function extras.image(result,element,detail,n,fulltag,di)
if data then
result[#result+1] = attribute("name",data.name)
if tonumber(data.page) > 1 then
- result[#result+1] = format(" page='%s'",data.page)
+ result[#result+1] = formatters[" page='%s'"](data.page)
end
- result[#result+1] = format(" id='%s' width='%s' height='%s'",fulltag,data.width,data.height)
+ result[#result+1] = formatters[" id='%s' width='%s' height='%s'"](fulltag,data.width,data.height)
end
end
@@ -620,7 +611,7 @@ end
function extras.combination(result,element,detail,n,fulltag,di)
local data = combinations[fulltag]
if data then
- result[#result+1] = format(" nx='%s' ny='%s'",data.nx,data.ny)
+ result[#result+1] = formatters[" nx='%s' ny='%s'"](data.nx,data.ny)
end
end
@@ -693,7 +684,7 @@ end
function specials.internal(result,var)
local internal = references.checkedurl(var.operation)
if internal then
- result[#result+1] = format(" location='aut:%s'",internal)
+ result[#result+1] = formatters[" location='aut:%s'"](internal)
end
end
@@ -705,9 +696,9 @@ local function adddestination(result,references) -- todo: specials -> exporters
if reference and reference ~= "" then
local prefix = references.prefix
if prefix and prefix ~= "" then
- result[#result+1] = format(" prefix='%s'",prefix)
+ result[#result+1] = formatters[" prefix='%s'"](prefix)
end
- result[#result+1] = format(" destination='%s'",reference)
+ result[#result+1] = formatters[" destination='%s'"](reference)
for i=1,#references do
local r = references[i]
local e = evaluators[r.kind]
@@ -725,13 +716,13 @@ local function addreference(result,references)
if reference and reference ~= "" then
local prefix = references.prefix
if prefix and prefix ~= "" then
- result[#result+1] = format(" prefix='%s'",prefix)
+ result[#result+1] = formatters[" prefix='%s'"](prefix)
end
- result[#result+1] = format(" reference='%s'",reference)
+ result[#result+1] = formatters[" reference='%s'"](reference)
end
local internal = references.internal
if internal and internal ~= "" then
- result[#result+1] = format(" location='aut:%s'",internal)
+ result[#result+1] = formatters[" location='aut:%s'"](internal)
end
end
end
@@ -817,6 +808,24 @@ end
-- maybe delay __i__ till we need it
+local apply_function = {
+ {
+ element = "mo",
+ -- comment = "apply function",
+ -- data = { utfchar(0x2061) },
+ data = { "" },
+ nature = "mixed",
+ }
+}
+
+local functioncontent = { }
+
+setmetatableindex(functioncontent,function(t,k)
+ local v = { { content = k } }
+ t[k] = v
+ return v
+end)
+
local function checkmath(root) -- we can provide utf.toentities as an option
local data = root.data
if data then
@@ -963,18 +972,10 @@ local function checkmath(root) -- we can provide utf.toentities as an option
i = collapse(di,i,data,ndata,detail,"mi")
local tag = functions[category]
if tag then
- di.data = { tag }
+ di.data = functioncontent[tag]
end
if apply then
- di.after = {
- {
- element = "mo",
- -- comment = "apply function",
- -- data = { utfchar(0x2061) },
- data = { "" },
- nature = "mixed",
- }
- }
+ di.after = apply_function
elseif automathapply then -- make function
local following
if i <= ndata then
@@ -991,15 +992,7 @@ local function checkmath(root) -- we can provide utf.toentities as an option
if following then
local tg = following.tg
if tg == "mrow" or tg == "mfenced" then -- we need to figure out the right condition
- di.after = {
- {
- element = "mo",
- -- comment = "apply function",
- -- data = { utfchar(0x2061) },
- data = { "" },
- nature = "mixed",
- }
- }
+ di.after = apply_function
end
end
end
@@ -1162,11 +1155,11 @@ function extras.tablecell(result,element,detail,n,fulltag,di)
if hash then
local v = hash.columns
if v and v > 1 then
- result[#result+1] = format(" columns='%s'",v)
+ result[#result+1] = formatters[" columns='%s'"](v)
end
local v = hash.rows
if v and v > 1 then
- result[#result+1] = format(" rows='%s'",v)
+ result[#result+1] = formatters[" rows='%s'"](v)
end
local v = hash.align
if not v or v == 0 then
@@ -1239,19 +1232,19 @@ local function emptytag(result,element,nature,depth,di) -- currently only break
local a = di.attributes -- we might add detail etc
if a then -- happens seldom
if linedone then
- result[#result+1] = format("%s<%s",spaces[depth],namespaced[element])
+ result[#result+1] = formatters["%w<%s"](depth,namespaced[element])
else
- result[#result+1] = format("\n%s<%s",spaces[depth],namespaced[element])
+ result[#result+1] = formatters["\n%w<%s"](depth,namespaced[element])
end
for k, v in next, a do
- result[#result+1] = format(" %s=%q",k,v)
+ result[#result+1] = formatters[" %s=%q"](k,v)
end
result[#result+1] = "/>\n"
else
if linedone then
- result[#result+1] = format("%s<%s/>\n",spaces[depth],namespaced[element])
+ result[#result+1] = formatters["%w<%s/>\n"](depth,namespaced[element])
else
- result[#result+1] = format("\n%s<%s/>\n",spaces[depth],namespaced[element])
+ result[#result+1] = formatters["\n%w<%s/>\n"](depth,namespaced[element])
end
end
linedone = false
@@ -1267,57 +1260,57 @@ local function begintag(result,element,nature,depth,di,skip)
linedone = false
inlinedepth = inlinedepth + 1
if show_comment and comment then
- result[#result+1] = format("",comment)
+ result[#result+1] = formatters[""](comment)
end
elseif nature == "mixed" then
if inlinedepth > 0 then
if show_comment and comment then
- result[#result+1] = format("",comment)
+ result[#result+1] = formatters[""](comment)
end
elseif linedone then
result[#result+1] = spaces[depth]
if show_comment and comment then
- result[#result+1] = format("",comment)
+ result[#result+1] = formatters[""](comment)
end
else
- result[#result+1] = format("\n%s",spaces[depth])
+ result[#result+1] = formatters["\n%w"](depth)
linedone = false
if show_comment and comment then
- result[#result+1] = format("\n%s",comment,spaces[depth])
+ result[#result+1] = formatters["\n%w"](comment,depth)
end
end
inlinedepth = inlinedepth + 1
else
if inlinedepth > 0 then
if show_comment and comment then
- result[#result+1] = format("",comment)
+ result[#result+1] = formatters[""](comment)
end
elseif linedone then
result[#result+1] = spaces[depth]
if show_comment and comment then
- result[#result+1] = format("",comment)
+ result[#result+1] = formatters[""](comment)
end
else
- result[#result+1] = format("\n%s",spaces[depth]) -- can introduced extra line in mixed+mixed (filtered later on)
+ result[#result+1] = formatters["\n%w"](depth) -- can introduced extra line in mixed+mixed (filtered later on)
linedone = false
if show_comment and comment then
- result[#result+1] = format("\n%s",comment,spaces[depth])
+ result[#result+1] = formatters["\n%w"](comment,depth)
end
end
end
if skip == "comment" then
if show_comment then
- result[#result+1] = format("",namespaced[element])
+ result[#result+1] = formatters[""](namespaced[element])
end
elseif skip then
-- ignore
else
- result[#result+1] = format("<%s",namespaced[element])
+ result[#result+1] = formatters["<%s"](namespaced[element])
if detail then
- result[#result+1] = format(" detail=%q",detail)
+ result[#result+1] = formatters[" detail=%q"](detail)
end
if indexing and n then
- result[#result+1] = format(" n=%q",n)
+ result[#result+1] = formatters[" n=%q"](n)
end
local extra = extras[element]
if extra then
@@ -1326,13 +1319,13 @@ local function begintag(result,element,nature,depth,di,skip)
local u = userdata[fulltag]
if u then
for k, v in next, u do
- result[#result+1] = format(" %s=%q",k,v)
+ result[#result+1] = formatters[" %s=%q"](k,v)
end
end
local a = di.attributes
if a then
for k, v in next, a do
- result[#result+1] = format(" %s=%q",k,v)
+ result[#result+1] = formatters[" %s=%q"](k,v)
end
end
result[#result+1] = ">"
@@ -1349,12 +1342,12 @@ local function begintag(result,element,nature,depth,di,skip)
result[#result+1] = "\n"
linedone = true
end
- result[#result+1] = format("%s\n",spaces[depth])
+ result[#result+1] = formatters["%w\n"](depth)
for k, v in table.sortedpairs(metadata) do
- v = utfgsub(v,".",entities)
- result[#result+1] = format("%s%s \n",spaces[depth+1],k,v)
+ v = entityremapper(v)
+ result[#result+1] = formatters["%w%s \n"](depth+1,k,v)
end
- result[#result+1] = format("%s \n",spaces[depth])
+ result[#result+1] = formatters["%w \n"](depth)
end
end
@@ -1366,35 +1359,35 @@ local function endtag(result,element,nature,depth,skip)
end
if skip == "comment" then
if show_comment then
- result[#result+1] = format("%s\n",spaces[depth],namespaced[element])
+ result[#result+1] = formatters["%w\n"](depth,namespaced[element])
end
elseif skip then
-- ignore
else
- result[#result+1] = format("%s%s>\n",spaces[depth],namespaced[element])
+ result[#result+1] = formatters["%w%s>\n"](depth,namespaced[element])
end
linedone = true
else
if skip == "comment" then
if show_comment then
- result[#result+1] = format("",namespaced[element])
+ result[#result+1] = formatters[""](namespaced[element])
end
elseif skip then
-- ignore
else
- result[#result+1] = format("%s>",namespaced[element])
+ result[#result+1] = formatters["%s>"](namespaced[element])
end
end
else
inlinedepth = inlinedepth - 1
if skip == "comment" then
if show_comment then
- result[#result+1] = format("",namespaced[element])
+ result[#result+1] = formatters[""](namespaced[element])
end
elseif skip then
-- ignore
else
- result[#result+1] = format("%s>",namespaced[element])
+ result[#result+1] = formatters["%s>"](namespaced[element])
end
linedone = false
end
@@ -1405,22 +1398,22 @@ local function flushtree(result,data,nature,depth)
local nofdata = #data
for i=1,nofdata do
local di = data[i]
- if not di then
+ if not di then -- hm, di can be string
-- whatever
elseif di.content then
-- already has breaks
- local content = utfgsub(di.content,".",entities)
+ local content = entityremapper(di.content)
if i == nofdata and sub(content,-1) == "\n" then -- move check
-- can be an end of line in par but can also be the last line
if trace_spacing then
- result[#result+1] = format("%s ",di.parnumber or 0,sub(content,1,-2))
+ result[#result+1] = formatters["%s "](di.parnumber or 0,sub(content,1,-2))
else
result[#result+1] = sub(content,1,-2)
end
result[#result+1] = " "
else
if trace_spacing then
- result[#result+1] = format("%s ",di.parnumber or 0,content)
+ result[#result+1] = formatters["%s "](di.parnumber or 0,content)
else
result[#result+1] = content
end
@@ -1428,7 +1421,9 @@ local function flushtree(result,data,nature,depth)
linedone = false
elseif not di.collapsed then -- ignore collapsed data (is appended, reconstructed par)
local element = di.element
- if element == "break" then -- or element == "pagebreak"
+ if not element then
+ -- skip
+ elseif element == "break" then -- or element == "pagebreak"
emptytag(result,element,nature,depth,di)
elseif element == "" or di.skip == "ignore" then
-- skip
@@ -1443,9 +1438,9 @@ local function flushtree(result,data,nature,depth)
end
begintag(result,element,natu,depth,di,skip)
flushtree(result,di.data,natu,depth)
--- if sub(result[#result],-1) == " " and natu ~= "inline" then
--- result[#result] = sub(result[#result],1,-2)
--- end
+ -- if sub(result[#result],-1) == " " and natu ~= "inline" then
+ -- result[#result] = sub(result[#result],1,-2)
+ -- end
endtag(result,element,natu,depth,skip)
if di.after then
flushtree(result,di.after,nature,depth)
@@ -1662,9 +1657,9 @@ local function push(fulltag,depth)
treestack[currentdepth] = tree
if trace_export then
if detail and detail ~= "" then
- report_export("%s<%s trigger='%s' paragraph='%s' index='%s' detail='%s'>",spaces[currentdepth-1],fulltag,currentattribute or 0,currentparagraph or 0,#treedata,detail)
+ report_export("%w<%s trigger=%a paragraph=%a index=%a detail=%a>",currentdepth-1,fulltag,currentattribute or 0,currentparagraph or 0,#treedata,detail)
else
- report_export("%s<%s trigger='%s' paragraph='%s' index='%s'>",spaces[currentdepth-1],fulltag,currentattribute or 0,currentparagraph or 0,#treedata)
+ report_export("%w<%s trigger=%a paragraph=%a index=%a>",currentdepth-1,fulltag,currentattribute or 0,currentparagraph or 0,#treedata)
end
end
tree = t
@@ -1686,7 +1681,7 @@ local function pop()
currentdepth = currentdepth - 1
if trace_export then
if top then
- report_export("%s%s>",spaces[currentdepth],top)
+ report_export("%w%s>",currentdepth,top)
else
report_export("%s>",top)
end
@@ -1696,7 +1691,7 @@ end
local function continueexport()
if nofcurrentcontent > 0 then
if trace_export then
- report_export("%s",spaces[currentdepth])
+ report_export("%w",currentdepth)
end
nofcurrentcontent = nofcurrentcontent + 1
currentcontent[nofcurrentcontent] = " " -- pagebreak
@@ -1712,7 +1707,7 @@ local function pushentry(current)
local newdepth = #current
local olddepth = currentdepth
if trace_export then
- report_export("%s",spaces[currentdepth],olddepth,newdepth,current[newdepth])
+ report_export("%w",currentdepth,olddepth,newdepth,current[newdepth])
end
if olddepth <= 0 then
for i=1,newdepth do
@@ -1751,28 +1746,28 @@ local function pushentry(current)
pop()
end
elseif trace_export then
- report_export("%s",spaces[currentdepth],newdepth,nesting[newdepth] or "?")
+ report_export("%w",currentdepth,newdepth,nesting[newdepth] or "?")
end
end
return olddepth, newdepth
end
end
-local function pushcontent(addbreak)
+local function pushcontent(currentparagraph,newparagraph)
if nofcurrentcontent > 0 then
- if addbreak then
+ if currentparagraph then
if currentcontent[nofcurrentcontent] == "\n" then
if trace_export then
- report_export("%s",spaces[currentdepth])
+ report_export("%w",currentdepth)
end
nofcurrentcontent = nofcurrentcontent - 1
end
end
local content = concat(currentcontent,"",1,nofcurrentcontent)
if content == "" then
- -- omit; when addbreak we could push, remove spaces, pop
- elseif somespace[content] and addbreak then
- -- omit; when addbreak we could push, remove spaces, pop
+ -- omit; when currentparagraph we could push, remove spaces, pop
+ elseif somespace[content] and currentparagraph then
+ -- omit; when currentparagraph we could push, remove spaces, pop
else
local olddepth, newdepth
local list = taglist[currentattribute]
@@ -1783,9 +1778,9 @@ local function pushcontent(addbreak)
local nd = #td
td[nd+1] = { parnumber = currentparagraph, content = content }
if trace_export then
- report_export("%s",spaces[currentdepth],#content)
- report_export("%s%s",spaces[currentdepth],(gsub(content,"\n","\\n")))
- report_export("%s",spaces[currentdepth])
+ report_export("%w",currentdepth,#content)
+ report_export("%w%s",currentdepth,(gsub(content,"\n","\\n")))
+ report_export("%w",currentdepth)
end
if olddepth then
for i=newdepth-1,olddepth,-1 do
@@ -1795,22 +1790,22 @@ local function pushcontent(addbreak)
end
nofcurrentcontent = 0
end
- if addbreak then
+ if currentparagraph then
pushentry(makebreaklist(currentnesting))
if trace_export then
- report_export("%s",spaces[currentdepth],addbreak)
+ report_export("%w",currentdepth,currentparagraph,newparagraph)
end
end
end
local function finishexport()
if trace_export then
- report_export("%s",spaces[currentdepth])
+ report_export("%w",currentdepth)
end
if nofcurrentcontent > 0 then
if somespace[currentcontent[nofcurrentcontent]] then
if trace_export then
- report_export("%s",spaces[currentdepth])
+ report_export("%w",currentdepth)
end
nofcurrentcontent = nofcurrentcontent - 1
end
@@ -1821,32 +1816,22 @@ local function finishexport()
end
currentcontent = { } -- we're nice and do a cleanup
if trace_export then
- report_export("%s",spaces[currentdepth])
+ report_export("%w",currentdepth)
end
end
-- whatsit_code localpar_code
-local function tracedchar(c)
- if c == 0x20 then
- return "[space]"
- elseif c == 0 then
- return "[signal]"
- else
- return utfchar(c)
- end
-end
-
local function collectresults(head,list) -- is last used (we also have currentattribute)
local p
for n in traverse_nodes(head) do
local id = n.id -- 14: image, 8: literal (mp)
if id == glyph_code then
- local at = has_attribute(n,a_tagged)
+ local at = n[a_tagged]
if not at then
-- we need to tag the pagebody stuff as being valid skippable
--
- -- report_export("skipping character: 0x%05X %s (no attribute)",n.char,utfchar(n.char))
+ -- report_export("skipping character: %C (no attribute)",n.char)
else
-- we could add tonunicodes for ligatures (todo)
local components = n.components
@@ -1856,55 +1841,52 @@ local function collectresults(head,list) -- is last used (we also have currentat
local c = n.char
if last ~= at then
local tl = taglist[at]
--- if trace_export then
--- report_export("%s",spaces[currentdepth],utfchar(c),at)
--- end
pushcontent()
currentnesting = tl
- currentparagraph = has_attribute(n,a_taggedpar)
+ currentparagraph = n[a_taggedpar]
currentattribute = at
last = at
pushentry(currentnesting)
- if trace_export then
- report_export("%s",spaces[currentdepth],tracedchar(c),at)
- end
+ if trace_export then
+ report_export("%w",currentdepth,c,at)
+ end
-- We need to intercept this here; maybe I will also move this
-- to a regular setter at the tex end.
- local r = has_attribute(n,a_reference)
+ local r = n[a_reference]
if r then
referencehash[tl[#tl]] = r -- fulltag
end
--
elseif last then
- local ap = has_attribute(n,a_taggedpar)
+ local ap = n[a_taggedpar]
if ap ~= currentparagraph then
- pushcontent(format("new paragraph (%s -> %s)",tostring(currentparagraph),tostring(ap)))
+ pushcontent(currentparagraph,ap)
pushentry(currentnesting)
currentattribute = last
currentparagraph = ap
end
if trace_export then
- report_export("%s",spaces[currentdepth],tracedchar(c),last)
+ report_export("%w",currentdepth,c,last)
end
else
if trace_export then
- report_export("%s",spaces[currentdepth],tracedchar(c),at)
+ report_export("%w",currentdepth,c,at)
end
end
- local s = has_attribute(n,a_exportstatus)
+ local s = n[a_exportstatus]
if s then
c = s
end
if c == 0 then
if trace_export then
- report_export("%s",spaces[currentdepth])
+ report_export("%w",currentdepth)
end
elseif c == 0x20 then
- local a = has_attribute(n,a_characters)
+ local a = n[a_characters]
nofcurrentcontent = nofcurrentcontent + 1
if a then
if trace_export then
- report_export("%s",spaces[currentdepth],a)
+ report_export("%w",currentdepth,a)
end
currentcontent[nofcurrentcontent] = specialspaces[a] -- special space
else
@@ -1934,24 +1916,6 @@ local function collectresults(head,list) -- is last used (we also have currentat
end
end
end
- elseif id == hlist_code or id == vlist_code then
- local ai = has_attribute(n,a_image)
- if ai then
- local at = has_attribute(n,a_tagged)
- if nofcurrentcontent > 0 then
- pushcontent()
- pushentry(currentnesting) -- ??
- end
- pushentry(taglist[at]) -- has an index, todo: flag empty element
- if trace_export then
- report_export("%s",spaces[currentdepth],ca,a)
+ report_export("%w",currentdepth,ca,a)
end
pushcontent()
currentnesting = tl
- currentparagraph = has_attribute(n,a_taggedpar)
+ currentparagraph = n[a_taggedpar]
currentattribute = a
last = a
pushentry(currentnesting)
-- no reference check (see above)
elseif last then
- local ap = has_attribute(n,a_taggedpar)
+ local ap = n[a_taggedpar]
if ap ~= currentparagraph then
- pushcontent(format("new paragraph (%s -> %s)",tostring(currentparagraph),tostring(ap)))
+ pushcontent(currentparagraph,ap)
pushentry(currentnesting)
currentattribute = last
currentparagraph = ap
end
if trace_export then
- report_export("%s",spaces[currentdepth],ca,last)
+ report_export("%w",currentdepth,ca,last)
end
end
-- if somespace[currentcontent[nofcurrentcontent]] then
-- if trace_export then
- -- report_export("%s",spaces[currentdepth])
+ -- report_export("%w",currentdepth)
-- end
-- nofcurrentcontent = nofcurrentcontent - 1
-- end
@@ -2008,21 +1972,21 @@ local function collectresults(head,list) -- is last used (we also have currentat
if subtype == userskip_code then
if n.spec.width > threshold then
if last and not somespace[currentcontent[nofcurrentcontent]] then
- local a = has_attribute(n,a_tagged)
+ local a = n[a_tagged]
if a == last then
if trace_export then
- report_export("%s",spaces[currentdepth])
+ report_export("%w",currentdepth)
end
nofcurrentcontent = nofcurrentcontent + 1
currentcontent[nofcurrentcontent] = " "
elseif a then
-- e.g LOGOLOGO
if trace_export then
- report_export("%s",spaces[currentdepth],last,a)
+ report_export("%w",currentdepth,last,a)
end
pushcontent()
if trace_export then
- report_export("%s",spaces[currentdepth])
+ report_export("%w",currentdepth)
end
last = a
nofcurrentcontent = nofcurrentcontent + 1
@@ -2035,16 +1999,16 @@ local function collectresults(head,list) -- is last used (we also have currentat
end
elseif subtype == spaceskip_code or subtype == xspaceskip_code then
if not somespace[currentcontent[nofcurrentcontent]] then
- local a = has_attribute(n,a_tagged)
+ local a = n[a_tagged]
if a == last then
if trace_export then
- report_export("%s",spaces[currentdepth])
+ report_export("%w",currentdepth)
end
nofcurrentcontent = nofcurrentcontent + 1
currentcontent[nofcurrentcontent] = " "
else
if trace_export then
- report_export("%s",spaces[currentdepth])
+ report_export("%w",currentdepth)
end
last = a
pushcontent()
@@ -2064,16 +2028,16 @@ local function collectresults(head,list) -- is last used (we also have currentat
nofcurrentcontent = nofcurrentcontent - 1
end
elseif not somespace[r] then
- local a = has_attribute(n,a_tagged)
+ local a = n[a_tagged]
if a == last then
if trace_export then
- report_export("%s",spaces[currentdepth])
+ report_export("%w",currentdepth)
end
nofcurrentcontent = nofcurrentcontent + 1
currentcontent[nofcurrentcontent] = " "
else
if trace_export then
- report_export("%s",spaces[currentdepth])
+ report_export("%w",currentdepth)
end
last = a
pushcontent()
@@ -2091,6 +2055,24 @@ local function collectresults(head,list) -- is last used (we also have currentat
return
end
end
+ elseif id == hlist_code or id == vlist_code then
+ local ai = n[a_image]
+ if ai then
+ local at = n[a_tagged]
+ if nofcurrentcontent > 0 then
+ pushcontent()
+ pushentry(currentnesting) -- ??
+ end
+ pushentry(taglist[at]) -- has an index, todo: flag empty element
+ if trace_export then
+ report_export("%w",spaces[currentdepth],topoints(kern,true))
+ report_export("%w",currentdepth,kern)
end
nofcurrentcontent = nofcurrentcontent + 1
currentcontent[nofcurrentcontent] = " "
@@ -2112,12 +2094,12 @@ local function collectresults(head,list) -- is last used (we also have currentat
elseif a then
-- e.g LOGOLOGO
if trace_export then
- report_export("%s",spaces[currentdepth],topoints(limit,true),last,a)
+ report_export("%w",currentdepth,limit,last,a)
end
last = a
pushcontent()
if trace_export then
- report_export("%s",spaces[currentdepth],topoints(kern,true))
+ report_export("%w",currentdepth,kern)
end
nofcurrentcontent = nofcurrentcontent + 1
currentcontent[nofcurrentcontent] = " "
@@ -2136,13 +2118,13 @@ end
function nodes.handlers.export(head) -- hooks into the page builder
starttiming(treehash)
if trace_export then
- report_export("%s",spaces[currentdepth])
+ report_export("%w",currentdepth)
end
-- continueexport()
restart = true
collectresults(head)
if trace_export then
- report_export("%s",spaces[currentdepth])
+ report_export("%w",currentdepth)
end
stoptiming(treehash)
return head, true
@@ -2153,9 +2135,9 @@ function builders.paragraphs.tag(head)
for n in traverse_id(hlist_code,head) do
local subtype = n.subtype
if subtype == line_code then
- set_attribute(n,a_textblock,noftextblocks)
+ n[a_textblock] = noftextblocks
elseif subtype == glue_code or subtype == kern_code then
- set_attribute(n,a_textblock,0)
+ n[a_textblock] = 0
end
end
return false
@@ -2192,7 +2174,7 @@ local function allusedstylesheets(xmlfile,cssfiles,files)
cssfile = file.addsuffix(cssfile,"css")
end
files[#files+1] = cssfile
- report_export("adding css reference '%s",cssfile)
+ report_export("adding css reference '%s'",cssfile)
result[#result+1] = format(csspreamble,cssfile)
end
return concat(result)
@@ -2216,14 +2198,14 @@ local displaymapping = {
local function allusedelements(xmlfile)
local result = { format("/* template for file %s */",xmlfile) }
- for element, details in table.sortedhash(used) do
+ for element, details in sortedhash(used) do
result[#result+1] = format("/* category: %s */",element)
- for detail, nature in table.sortedhash(details) do
+ for detail, nature in sortedhash(details) do
local d = displaymapping[nature or "display"] or "block"
if detail == "" then
- result[#result+1] = format(e_template,element,d)
+ result[#result+1] = formatters[e_template](element,d)
else
- result[#result+1] = format(d_template,element,detail,d)
+ result[#result+1] = formatters[d_template](element,detail,d)
end
end
end
@@ -2340,16 +2322,16 @@ local function stopexport(v)
--
files = table.unique(files)
--
- report_export("saving xml data in '%s",xmlfile)
+ report_export("saving xml data in %a",xmlfile)
io.savedata(xmlfile,results)
--
- report_export("saving css image definitions in '%s",imagefilename)
+ report_export("saving css image definitions in %a",imagefilename)
io.savedata(imagefilename,allusedimages(xmlfile))
--
- report_export("saving css style definitions in '%s",stylefilename)
+ report_export("saving css style definitions in %a",stylefilename)
io.savedata(stylefilename,allusedstyles(xmlfile))
--
- report_export("saving css template in '%s",templatefilename)
+ report_export("saving css template in %a",templatefilename)
io.savedata(templatefilename,allusedelements(xmlfile))
--
if xhtmlfile then
@@ -2359,17 +2341,26 @@ local function stopexport(v)
xhtmlfile = file.addsuffix(xhtmlfile,"xhtml")
end
files[#files+1] = xhtmlfile
- report_export("saving xhtml variant in '%s",xhtmlfile)
+ report_export("saving xhtml variant in %a",xhtmlfile)
local xmltree = cleanxhtmltree(xml.convert(results))
xml.save(xmltree,xhtmlfile)
+ -- looking at identity is somewhat redundant as we also inherit from interaction
+ -- at the tex end
+ local identity = interactions.general.getidentity()
local specification = {
name = file.removesuffix(v),
identifier = os.uuid(),
images = uniqueusedimages(),
root = xhtmlfile,
files = files,
+ language = languagenames[tex.count.mainlanguagenumber],
+ title = validstring(finetuning.title) or validstring(identity.title),
+ subtitle = validstring(finetuning.subtitle) or validstring(identity.subtitle),
+ author = validstring(finetuning.author) or validstring(identity.author),
+ firstpage = validstring(finetuning.firstpage),
+ lastpage = validstring(finetuning.lastpage),
}
- report_export("saving specification in '%s' (mtxrun --script epub --make %s)",specificationfilename,specificationfilename)
+ report_export("saving specification in %a (mtxrun --script epub --make %s)",specificationfilename,specificationfilename)
io.savedata(specificationfilename,table.serialize(specification,true))
end
stoptiming(treehash)
diff --git a/Master/texmf-dist/tex/context/base/back-exp.mkiv b/Master/texmf-dist/tex/context/base/back-exp.mkiv
index 871d08b1991..9e65633d4b0 100644
--- a/Master/texmf-dist/tex/context/base/back-exp.mkiv
+++ b/Master/texmf-dist/tex/context/base/back-exp.mkiv
@@ -132,6 +132,11 @@
[\c!align=\number\raggedstatus,
\c!bodyfont=\bodyfontsize,
\c!width=\textwidth,
+ \c!title={\directinteractionparameter\c!title},
+ \c!subtitle={\directinteractionparameter\c!subtitle},
+ \c!author={\directinteractionparameter\c!author},
+ % \c!firstpage=, % imagename
+ % \c!lastpage=, % imagename
\c!hyphen=\v!no]
\def\dosynchronizeexport
@@ -141,12 +146,21 @@
bodyfont = \number\dimexpr\exportparameter\c!bodyfont,
width = \number\dimexpr\exportparameter\c!width,
hyphen = "\exportparameter\c!hyphen",
+ title = \!!bs\exportparameter\c!title\!!es,
+ subtitle = \!!bs\exportparameter\c!subtitle\!!es,
+ author = \!!bs\exportparameter\c!author\!!es,
+ firstpage = "\exportparameter\c!firstpage",
+ lastpage = "\exportparameter\c!lastpage",
}}}
\appendtoks
- \doifsomething{\backendparameter\c!export}{\dosynchronizeexport}%
+ \doifsomething{\backendparameter\c!export}\dosynchronizeexport
\to \everystarttext
+\appendtoks
+ \doifsomething{\backendparameter\c!export}\dosynchronizeexport % in case it is done inside \starttext
+\to \everysetupdocument
+
\appendtoks
\doifsomething{\backendparameter\c!xhtml}
{\enabledirectives[backend.export.xhtml=\backendparameter\c!xhtml]}%
@@ -155,11 +169,11 @@
\to \everysetupbackend
\appendtoks
- \doifsomething{\backendparameter\c!export}
- {\setuptagging
- [\c!state=\v!start]%
- \enabledirectives
- [backend.export=\backendparameter\c!export]}%
+ \doifelsenothing{\backendparameter\c!export}
+ {\resetsystemmode\v!export}
+ {\setuptagging[\c!state=\v!start]%
+ \enabledirectives[backend.export=\backendparameter\c!export]%
+ \setsystemmode\v!export}%
\to \everysetupbackend
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/back-ini.lua b/Master/texmf-dist/tex/context/base/back-ini.lua
index 0c02e201a68..bdd931abd33 100644
--- a/Master/texmf-dist/tex/context/base/back-ini.lua
+++ b/Master/texmf-dist/tex/context/base/back-ini.lua
@@ -59,7 +59,11 @@ function backends.install(what)
local backend = backends[what]
if backend then
if trace_backend then
- report_backend("initializing backend %s (%s)",what,backend.comment or "no comment")
+ if backend.comment then
+ report_backend("initializing backend %a, %a",what,backend.comment)
+ else
+ report_backend("initializing backend %a",what)
+ end
end
backends.current = what
for category, default in next, defaults do
@@ -68,7 +72,7 @@ function backends.install(what)
setmetatableindex(target, plugin)
end
elseif trace_backend then
- report_backend("no backend named %s",what)
+ report_backend("no backend named %a",what)
end
end
end
@@ -93,10 +97,10 @@ tables.vfspecials = allocate {
stopslant = comment,
}
--- -- experimental code --
+-- experimental code --
-function commands.pdfrotation(a)
+function commands.pdfrotation(a) -- somewhat weird here
local s, c = sind(a), cosd(a)
- context("%s %s %s %s",c,s,-s,c)
+ context("%0.6f %0.6f %0.6f %0.6f",c,s,-s,c)
end
diff --git a/Master/texmf-dist/tex/context/base/back-ini.mkiv b/Master/texmf-dist/tex/context/base/back-ini.mkiv
index 8ece8f6e13b..fc8759c14db 100644
--- a/Master/texmf-dist/tex/context/base/back-ini.mkiv
+++ b/Master/texmf-dist/tex/context/base/back-ini.mkiv
@@ -61,13 +61,13 @@
\let \dotransformnextbox\gobblesixarguments % and pass last box
%D \macros
-%D {doovalbox}
+%D {back_ovalbox}
%D
%D When we look at the implementation, this is a complicated
%D one. There are seven arguments.
%D
%D \starttyping
-%D \doovalbox {w} {h} {d} {linewidth} {radius} {stroke} {fill} {variant}
+%D \back_ovalbox {w} {h} {d} {linewidth} {radius} {stroke} {fill} {variant}
%D \stoptyping
%D
%D This command has to return a \type{\vbox} which can be used
@@ -75,7 +75,7 @@
%D degrees, the stroke and fill are~\type{1} (true) of~\type{0}
%D (false).
-\let \doovalbox \gobbleeightarguments
+\let\back_ovalbox \gobbleeightarguments
%D \macros
%D {dostartclipping,dostopclipping}
diff --git a/Master/texmf-dist/tex/context/base/back-pdf.mkiv b/Master/texmf-dist/tex/context/base/back-pdf.mkiv
index 9e441e224a6..1cf7a3703d2 100644
--- a/Master/texmf-dist/tex/context/base/back-pdf.mkiv
+++ b/Master/texmf-dist/tex/context/base/back-pdf.mkiv
@@ -68,16 +68,17 @@
{\ctxcommand{setxmpfile("\backendparameter{xmpfile}")}}%
\to \everysetupbackend
+% \doifsomething{\backendparameter\c!format} .. at the lua end
+
\appendtoks
- \doifsomething{\backendparameter\c!format}
- {\ctxcommand{setformat {
+ \ctxcommand{setformat {
format = "\backendparameter\c!format",
level = "\backendparameter\c!level",
option = "\backendparameter\c!option",
profile = "\backendparameter\c!profile",
intent = "\backendparameter\c!intent",
file = "\backendparameter\c!file",
- }}}%
+ }}%
\to \everysetupbackend
%D For the moment we keep these.
@@ -140,7 +141,7 @@
%
% function lpdf.rotationcm(a)
% local s, c = sind(a), cosd(a)
-% return format("%s %s %s %s 0 0 cm",c,s,-s,c)
+% return format("%f %f %f %f 0 0 cm",c,s,-s,c)
% end
%
% \def\dostartmirroring{\pdfliteral{-1 0 0 1 0 0 cm}}
@@ -186,7 +187,7 @@
\unexpanded\def\dodotransformnextbox#1#2#3%
{\hbox
- {\hskip#1\onebasepoint
+ {\kern#1\onebasepoint
\raise#2\onebasepoint\hbox
{\pdfsave
\pdfsetmatrix{#3}% 0 0 (no #5 #6 yet)
@@ -220,12 +221,12 @@
\newbox\objectbox
-\def\dostartobject#1#2#3#4#5%
+\unexpanded\def\dostartobject#1#2#3#4#5% needs to be \unexpanded
{\bgroup
\setbox\objectbox\vbox\bgroup
\def\back_object_stop{\egroup\back_object_register{#1}{#2}}}
-\def\dostopobject
+\unexpanded\def\dostopobject % needs to be \unexpanded
{\back_object_stop
\egroup}
@@ -237,9 +238,6 @@
\immediate\pdfxform resources {\pdfbackendcurrentresources}\objectbox
\dosetobjectreference{#1}{#2}{\the\pdflastxform}}
-\def\doresetobjects
- {}
-
\let\m_back_object_reference\empty
\def\doinsertobject#1#2%
@@ -263,7 +261,7 @@
% for the moment here
%D \macros
-%D {doovalbox}
+%D {back_ovalbox}
%D
%D Drawing frames with round corners is inherited from the
%D main module.
@@ -276,7 +274,7 @@
% \def\back_oval_calculate#1#2#3%
% {\PointsToBigPoints{\dimexpr#2+#3\relax}#1}
-\unexpanded\def\doovalbox#1#2#3#4#5#6#7#8%
+\unexpanded\def\back_ovalbox#1#2#3#4#5#6#7#8%
{\forcecolorhack
\bgroup
% \scratchdimen#4%
@@ -306,16 +304,16 @@
\PointsToBigPoints{\dimexpr #2-\scratchdimen}\yymax
\PointsToBigPoints{\dimexpr-#3+\scratchdimen}\yymin
%
- \edef\dostroke{#6}%
- \edef\dofill{#7}%
- \edef\mode{\number#8 \space}%
+ \edef\dostroke{\number#6}%
+ \edef\dofill{\number#7}%
+ \edef\mode{\number#8}%
% no \ifcase, else \relax in pdfcode
\setbox\scratchbox\hbox
{\ifnum\dostroke\dofill>\zerocount
\pdfliteral
{q
\stroke\space w
- \ifcase\mode
+ \ifcase\mode\space
\xxmin\space \ymin \space m
\xxmax\space \ymin \space l
\xmax \space \ymin \space \xmax \space \yymin\space y
@@ -495,7 +493,7 @@
\xmin \space \ymin \space \xmin \space \yymin\space y
\or % 28
\fi
- \ifnum\mode>8
+ \ifnum\mode>8\space
S
\else
\ifnum\dostroke=\plusone S \fi
diff --git a/Master/texmf-dist/tex/context/base/back-swf.mkiv b/Master/texmf-dist/tex/context/base/back-swf.mkiv
index 1d225b550ea..09745e0f93f 100644
--- a/Master/texmf-dist/tex/context/base/back-swf.mkiv
+++ b/Master/texmf-dist/tex/context/base/back-swf.mkiv
@@ -11,12 +11,12 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-% This is only a placeholder that demonstrates the usage of swf
-% resources.
-
-%D \starttyping
-%D \starttext
+%D This is only a placeholder that demonstrates the usage of swf resources.
+%D There is no need to include this file into the format. The module was
+%D tested by Luigi and Willi and based on their suggestions the functionality
+%D was improved.
%D
+%D \starttyping
%D \enabletrackers[graphics.locating]
%D \enabletrackers[backend.swf]
%D
@@ -41,8 +41,6 @@
%D \stopTEXpage
%D \stoptyping
-\stoptext
-
\endinput
\starttext
@@ -72,8 +70,6 @@
},
\stopluaparameterset
-\starttext
-
% preview=swf:myset:display:1
% controls=swf:myset:controls:1
% resources=swf:myset:resources:1
diff --git a/Master/texmf-dist/tex/context/base/back-u3d.mkiv b/Master/texmf-dist/tex/context/base/back-u3d.mkiv
index dfe8a90c2a6..89d26ee41e8 100644
--- a/Master/texmf-dist/tex/context/base/back-u3d.mkiv
+++ b/Master/texmf-dist/tex/context/base/back-u3d.mkiv
@@ -11,10 +11,9 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-% This is only a placeholder that demonstrates the usage of u3d
-% resources. The user interface is rather messy an might be
-% improved. The files and setup is derived from an example by
-% Michael Vidiassov.
+%D This is only a placeholder that demonstrates the usage of u3d resources. The
+%D user interface is rather messy an might be improved. The files and setup is
+%D derived from an example by Michael Vidiassov.
\endinput
diff --git a/Master/texmf-dist/tex/context/base/bibl-bib.lua b/Master/texmf-dist/tex/context/base/bibl-bib.lua
index 444f7e9bcc4..c86a0c0c263 100644
--- a/Master/texmf-dist/tex/context/base/bibl-bib.lua
+++ b/Master/texmf-dist/tex/context/base/bibl-bib.lua
@@ -12,7 +12,6 @@ bibtex files and converts them to xml so that the we access the content
in a convenient way. Actually handling the data takes place elsewhere.
--ldx]]--
-local utf = unicode.utf8
local lower, format, gsub, concat = string.lower, string.format, string.gsub, table.concat
local next = next
local utfchar = utf.char
@@ -22,6 +21,7 @@ local variables = interfaces and interfaces.variables
local settings_to_hash = utilities.parsers.settings_to_hash
local finalizers = xml.finalizers.tex
local xmlfilter, xmltext, getid = xml.filter, xml.text, lxml.getid
+local formatters = string.formatters
local P, R, S, C, Cc, Cs, Ct = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Cc, lpeg.Cs, lpeg.Ct
@@ -144,9 +144,9 @@ function bibtex.load(session,filename)
if filename ~= "" then
local data = io.loaddata(filename) or ""
if data == "" then
- report_xml("empty file '%s', no conversion to xml",filename)
+ report_xml("empty file %a, no conversion to xml",filename)
elseif trace_bibxml then
- report_xml("converting file '%s' to xml",filename)
+ report_xml("converting file %a to xml",filename)
end
bibtex.convert(session,data)
end
@@ -163,7 +163,7 @@ function bibtex.new()
}
end
-local escaped_pattern = lpegpatterns.xml.escaped
+local p_escaped = lpegpatterns.xml.escaped
local ihatethis = {
f = "\\f",
@@ -203,17 +203,16 @@ function bibtex.toxml(session,options)
local convert = options.convert -- todo: interface
local strip = options.strip -- todo: interface
local entries = session.entries
- r = r + 1 ; result[r] = format("")
- r = r + 1 ; result[r] = format("")
+ r = r + 1 ; result[r] = ""
+ r = r + 1 ; result[r] = ""
for id, categories in next, session.data do
id = lower(gsub(id,"^@",""))
for name, entry in next, categories do
if not entries or entries[name] then
- r = r + 1 ; result[r] = format("",lower(name),id)
+ r = r + 1 ; result[r] = formatters[""](lower(name),id)
for key, value in next, entry do
- value = gsub(value,"\\(.)",ihatethis)
- value = lpegmatch(escaped_pattern,value)
-
+ value = gsub(value,"\\(.)",ihatethis) -- this really needs checking
+ value = lpegmatch(p_escaped,value)
if value ~= "" then
if convert then
value = textoutf(value,true)
@@ -223,14 +222,14 @@ function bibtex.toxml(session,options)
-- kind of hackery ... bibtex databases are quite unportable
value = lpegmatch(filter,value) or value
end
- r = r + 1 ; result[r] = format(" %s ",key,value)
+ r = r + 1 ; result[r] = formatters[" %s "](key,value)
end
end
- r = r + 1 ; result[r] = format(" ")
+ r = r + 1 ; result[r] = " "
end
end
end
- r = r + 1 ; result[r] = format(" ")
+ r = r + 1 ; result[r] = " "
result = concat(result,"\n")
-- alternatively we could use lxml.convert
session.xml = xml.convert(result, {
diff --git a/Master/texmf-dist/tex/context/base/bibl-bib.mkiv b/Master/texmf-dist/tex/context/base/bibl-bib.mkiv
index 56007d21c1f..d9010294d55 100644
--- a/Master/texmf-dist/tex/context/base/bibl-bib.mkiv
+++ b/Master/texmf-dist/tex/context/base/bibl-bib.mkiv
@@ -340,14 +340,13 @@
% todo : lang en language
% todo : directions
-
% variables
-\newcount\bibtexblock \bibtexblock\plusone
+\ifdefined\bibtexblock \else \newcount\bibtexblock \fi \bibtexblock\plusone
+\ifdefined\bibtexcounter \else \newcount\bibtexcounter \fi
\newtoks \everysetupbibtexpublications
\newtoks \everysetupbibtexcitations
-\newcount\bibtexcounter
\def\bibtexrefprefix{\number\bibtexblock:}
@@ -626,7 +625,7 @@
\doifelse{\bibtexpublicationsparameter\c!method}\v!local
{\ctxlua{bibtex.hacks.reset(1)}}% function can take method
{\ctxlua{bibtex.hacks.reset(2)}}%
- \doplacestructurelist
+ \strc_lists_place_current
{\currentbibtexsession}
{\currentbibtexcriterium}
{\namedlistparameter\currentbibtexsession\c!number}%
diff --git a/Master/texmf-dist/tex/context/base/bibl-tra.lua b/Master/texmf-dist/tex/context/base/bibl-tra.lua
index 6341898eef5..6a70160230e 100644
--- a/Master/texmf-dist/tex/context/base/bibl-tra.lua
+++ b/Master/texmf-dist/tex/context/base/bibl-tra.lua
@@ -1,4 +1,4 @@
-if not modules then modules = { } end modules ['bibl-bib'] = {
+if not modules then modules = { } end modules ['bibl-tra'] = {
version = 1.001,
comment = "this module is the basis for the lxml-* ones",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
@@ -33,6 +33,12 @@ local template = utilities.strings.striplong([[
\bibdata{%s}
]])
+local bibtexbin = environment.arguments.mlbibtex and "mlbibcontext" or "bibtex"
+
+directives.register("publications.usemlbibtex", function(v)
+ bibtexbin = v and "mlbibcontext" or "bibtex"
+end)
+
function hacks.process(settings)
local style = settings.style or ""
local database = settings.database or ""
@@ -41,16 +47,16 @@ function hacks.process(settings)
interfaces.showmessage("publications",3)
io.savedata(file.addsuffix(jobname,"aux"),format(template,style,database))
if trace_bibtex then
- report_tex("processing bibtex file '%s'",jobname)
+ report_tex("processing bibtex file %a using %a",jobname,bibtexbin)
end
- os.execute(format("bibtex %s",jobname))
+ os.execute(format("%s %q",bibtexbin,jobname))
-- purge 'm
end
end
function hacks.register(str)
if trace_bibtex then
- report_tex("registering bibtex entry '%s'",str)
+ report_tex("registering bibtex entry %a",str)
end
registered[#registered+1] = str
ordered[str] = #registered
@@ -115,7 +121,7 @@ function hacks.registerplaced(str)
end
function hacks.doifalreadyplaced(str)
- commands.testcase(used[str])
+ commands.doifelse(used[str])
end
-- we ask for :tag but when we can't find it we go back
diff --git a/Master/texmf-dist/tex/context/base/bibl-tra.mkiv b/Master/texmf-dist/tex/context/base/bibl-tra.mkiv
index 3531703adc9..511212a9822 100644
--- a/Master/texmf-dist/tex/context/base/bibl-tra.mkiv
+++ b/Master/texmf-dist/tex/context/base/bibl-tra.mkiv
@@ -194,31 +194,32 @@
\installstructurelistprocessor{pubs:userdata}%
{\ctxlua{bibtex.hacks.add(structures.lists.uservalue("\currentlist",\currentlistindex,"bibref"),\currentlistindex)}}
-\newcount\bibtexblock \bibtexblock\plusone
+\ifdefined\bibtexblock \else \newcount\bibtexblock \fi \bibtexblock\plusone
+\ifdefined\bibtexcounter \else \newcount\bibtexcounter \fi
%D \macros{bibdoif,bibdoifnot,bibdoifelse}
%D
%D Here are a few small helpers that are used a lot in all the typesetting commands
%D (\type{\bibinsert...}) we will encounter later.
-\long\def\bibdoifelse#1%
- {\@EA\def\@EA\!!stringa\@EA{#1}%
+\unexpanded\def\bibdoifelse#1%
+ {\expandafter\def\expandafter\!!stringa\expandafter{#1}%
\ifx\!!stringa\empty
\expandafter\secondoftwoarguments
\else
\expandafter\firstoftwoarguments
\fi}
-\long\def\bibdoifnot#1%
- {\@EA\def\@EA\!!stringa\@EA{#1}%
+\unexpanded\def\bibdoifnot#1%
+ {\expandafter\def\expandafter\!!stringa\expandafter{#1}%
\ifx\!!stringa\empty
\expandafter\firstofoneargument
\else
\expandafter\gobbleoneargument
\fi}
-\long\def\bibdoif#1%
- {\@EA\def\@EA\!!stringa\@EA{#1}%
+\unexpanded\def\bibdoif#1%
+ {\expandafter\def\expandafter\!!stringa\expandafter{#1}%
\ifx\!!stringa\empty
\expandafter\gobbleoneargument
\else
@@ -248,12 +249,12 @@
\unexpanded\def\setupbibtex
{\dosingleempty\dosetupbibtex}
-\def\dosetupbibtex[#1]%
+\unexpanded\def\dosetupbibtex[#1]%
{\let\@@pbdatabase\empty
\getparameters[\??pb][#1]%
\the\everysetupbibtex}
-\def\installbibtexsorter#1#2%
+\unexpanded\def\installbibtexsorter#1#2%
{\setvalue{\??pb:\c!sort:#1}{#2}}
\installbibtexsorter\v!no {no}
@@ -284,7 +285,7 @@
\unexpanded\def\setuppublications
{\dosingleargument\dosetuppublications}
-\def\dosetuppublications[#1]%
+\unexpanded\def\dosetuppublications[#1]%
{\getparameters[\??pb][\c!alternative=,#1]%
\doifsomething\@@pbalternative
{\readsysfile{bibl-\@@pbalternative.tex}
@@ -330,7 +331,7 @@
\s!unknown=>\edef\@@citedefault{\@@pbrefcommand}]%
\to \everysetuppublications
-\def\bibleftnumber#1{#1\hfill~}
+\unexpanded\def\bibleftnumber#1{#1\hfill~}
%D \macros{usepublications}
%D
@@ -339,19 +340,22 @@
%D because similar numbers can be confusing. So, for the moment this is not
%D supported in \MKIV. (So no: see reference [3-5,9] in "some other document")
-\def\usepublications[#1]%
+\unexpanded\def\usepublications[#1]%
{\processcommalist[#1]\dousepublications}
-\def\dousepublications#1%
+\unexpanded\def\dousepublications#1%
{\doonlyonce{#1.\f!bibextension}{\dodousepublications{#1}}}
-\def\dodousepublications#1% brr, this par stuff
+\unexpanded\def\dodousepublications#1% brr, this par stuff
{\let\@@savedpar\par
\let\par\ignorespaces
\ifhmode\kern\zeropoint\fi
+ \pushcatcodetable
+ \setcatcodetable\ctxcatcodes
\readfile{#1.\f!bibextension}
{\showmessage\m!publications{4}{#1.\f!bibextension}}
{\showmessage\m!publications{2}{#1.\f!bibextension}}%
+ \popcatcodetable
\ifhmode\removeunwantedspaces\fi
\let\par\@@savedpar}
@@ -373,7 +377,7 @@
\unexpanded\def\setuppublicationlist
{\dosingleempty\dosetuppublicationlist}
-\def\dosetuppublicationlist[#1]%
+\unexpanded\def\dosetuppublicationlist[#1]%
{\getparameters[\??pv:l:][#1]%
\setuplist[pubs][\c!samplesize={AA99},\c!alternative=a,\c!interaction=,\c!pagenumber=\v!no,#1,\c!command=]}
@@ -415,14 +419,14 @@
\newtoks\initializebibdefinitions % we need to prevent clashes
-\def\simplebibdef#1% hh: funny expansion ?
- {\@EA\long\@EA\def\csname bib@#1\endcsname##1%
+\unexpanded\def\simplebibdef#1% hh: funny expansion ?
+ {\expandafter\def\csname bib@#1\endcsname##1%
{\setvalue{\??pb @#1}{##1}\ignorespaces}%
\expandafter \appendtoks
\expandafter\let\csname insert#1\expandafter\endcsname\csname bibinsert#1\endcsname
\to \initializebibdefinitions
- \@EA\unexpanded\@EA\def\csname bibinsert#1\endcsname##1##2##3%
- {\@EA\bibdoifelse\@EA{\csname\??pb @#1\endcsname}{##1\csname\??pb @#1\endcsname##2}{##3}}}
+ \expandafter\unexpanded\expandafter\def\csname bibinsert#1\endcsname##1##2##3%
+ {\expandafter\bibdoifelse\expandafter{\csname\??pb @#1\endcsname}{##1\csname\??pb @#1\endcsname##2}{##3}}}
\def\bibcommandlist
{abstract, annotate, arttitle, assignee, bibnumber, bibtype, biburl, chapter, city,
@@ -433,13 +437,13 @@
\processcommacommand[\bibcommandlist]\simplebibdef
-\def\bibinsertdoi#1#2#3% let's see how this fails
+\unexpanded\def\bibinsertdoi#1#2#3% let's see how this fails
{\bibdoifelse{\@@pb@doi}{#1\expanded{\bibgotoDOI{\@@pb@thekey}{\@@pb@doi}}#2}{#3}}
-\def\bibinsertbiburl#1#2#3% let's see how this fails
+\unexpanded\def\bibinsertbiburl#1#2#3% let's see how this fails
{\bibdoifelse{\@@pb@biburl}{#1\expanded{\bibgotoURL{\@@pb@thekey}{\@@pb@biburl}}#2}{#3}}
-\def\bibinsertmonth#1#2#3%
+\unexpanded\def\bibinsertmonth#1#2#3%
{\bibdoifelse\@@pb@month
{#1\doifnumberelse\@@pb@month
{\doifconversiondefinedelse\@@pbmonthconversion
@@ -452,7 +456,7 @@
\let\inserttype\bibinsertbibtype % for backward compat.
\to\initializebibdefinitions
-\def\newbibfield[#1]%
+\unexpanded\def\newbibfield[#1]%
{\simplebibdef{#1}%
\edef\bibcommandlist{\bibcommandlist,#1}}
@@ -473,7 +477,7 @@
% todo: instead of \getvalue{bla@num} in specs we should do
% \bibentrynum{bla} so that we can create a better namespace
-%D All of these \type{\@EA}'s and \type{\csnames} make this code
+%D All of these \type{\expandafter}'s and \type{\csnames} make this code
%D look far more complex than it really is. For example, the argument
%D \type{author} defines the macro \type{\bib@author} to do two
%D things: increment the counter \type{\author@num} (let's say to 2)
@@ -483,23 +487,23 @@
%D \specialbibinsert{author}{\author@num}{}{}{}
%D \stoptyping
-\def\docomplexbibdef#1%
+\unexpanded\def\docomplexbibdef#1%
{\dodoubleempty\dodocomplexbibdef[#1]}
-\def\dodocomplexbibdef[#1][#2]#3%
+\unexpanded\def\dodocomplexbibdef[#1][#2]#3%
{\doquadrupleempty\dododocomplexbibdef[#1][#2][#3]}
-\def\dododocomplexbibdef[#1][#2][#3][#4]#5#6%
- {\@EA\increment\csname#1@num\endcsname % todo: bib in name
+\unexpanded\def\dododocomplexbibdef[#1][#2][#3][#4]#5#6%
+ {\expandafter\increment\csname#1@num\endcsname % todo: bib in name
\setevalue{\??pb @#1\csname#1@num\endcsname}{{#3}{#5}{#6}{#4}{#2}}\ignorespaces}
-\def\complexbibdef#1%
- {\@EA\newcounter\csname #1@num\endcsname
- \@EA\def\csname bib@#1\endcsname{\docomplexbibdef{#1}}%
+\unexpanded\def\complexbibdef#1%
+ {\expandafter\newcounter\csname #1@num\endcsname
+ \expandafter\def\csname bib@#1\endcsname{\docomplexbibdef{#1}}%
\expandafter \appendtoks
\expandafter\let\csname insert#1s\expandafter\endcsname\csname bibinsert#1s\endcsname
\to \initializebibdefinitions
- \@EA\def\csname bibinsert#1s\endcsname##1##2##3{\specialbibinsert{#1}{\csname #1@num\endcsname}{##1}{\unskip ##2}{##3}}}
+ \expandafter\def\csname bibinsert#1s\endcsname##1##2##3{\specialbibinsert{#1}{\csname #1@num\endcsname}{##1}{\unskip ##2}{##3}}}
\processcommalist[author,artauthor,editor]\complexbibdef
@@ -510,7 +514,7 @@
\newcount\etaldisplaycounter
\newcount\todocounter
-\def\specialbibinsert#1#2#3#4#5%
+\unexpanded\def\specialbibinsert#1#2#3#4#5%
{\bgroup
\ifnum#2>\zerocount
\etallimitcounter =0\bibalternative{#1etallimit}\relax
@@ -528,7 +532,7 @@
% find the current author list
\let\templist\empty
\dorecurse{#2}
- {\scratchtoks\@EA\@EA\@EA{\csname\??pb @#1\recurselevel\endcsname}%
+ {\scratchtoks\doubleexpandafter{\csname\??pb @#1\recurselevel\endcsname}%
\edef\templist{\ifx\templist\empty\else\templist,\fi\the\scratchtoks}}%
#3\publicationlistparameter\c!command{#1}{\todocounter}{\templist}#4\relax
\else
@@ -547,7 +551,7 @@
%D \#2 = number of items to be typeset
%D \#3 = commacommand containing authors
-\def\doprocessauthoritem#1#2#3%
+\unexpanded\def\doprocessauthoritem#1#2#3%
{\advance\scratchcounter\plusone
\ifnum\numexpr\scratchcounter-\plusone\relax<#2\relax
\publicationlistparameter{#1}#3%
@@ -566,7 +570,7 @@
\fi\fi
\fi}
-\def\dospecialbibinsert#1#2#3%
+\unexpanded\def\dospecialbibinsert#1#2#3%
{\getcommacommandsize[#3]%
\scratchcounter\zerocount
\processcommacommand[#3]{\doprocessauthoritem{#1}{#2}}}
@@ -588,25 +592,25 @@
%D \type{#5} junior
%D \stoplines
-\def\normalauthor#1#2#3#4#5%
+\unexpanded\def\normalauthor#1#2#3#4#5%
{\bibdoif{#1}{#1\bibalternative\c!firstnamesep}%
\bibdoif{#2}{#2\bibalternative\c!vonsep}%
#3%
\bibdoif{#5}{\bibalternative\c!surnamesep#5\unskip}}
-\def\normalshortauthor#1#2#3#4#5%
+\unexpanded\def\normalshortauthor#1#2#3#4#5%
{\bibdoif{#4}{#4\bibalternative\c!firstnamesep}%
\bibdoif{#2}{#2\bibalternative\c!vonsep}%
#3%
\bibdoif{#5}{\bibalternative\c!surnamesep#5\unskip}}
-\def\invertedauthor#1#2#3#4#5%
+\unexpanded\def\invertedauthor#1#2#3#4#5%
{\bibdoif{#2}{#2\bibalternative\c!vonsep}%
#3%
\bibdoif{#5}{\bibalternative\c!juniorsep#5}%
\bibdoif{#1}{\bibalternative\c!surnamesep#1\unskip}}
-\def\invertedshortauthor#1#2#3#4#5%
+\unexpanded\def\invertedshortauthor#1#2#3#4#5%
{\bibdoif{#2}{#2\bibalternative\c!vonsep}%
#3%
\bibdoif{#5}{\bibalternative\c!juniorsep#5}%
@@ -617,16 +621,16 @@
%D These are used in \type{\typesetapublication} to do
%D initializations and cleanups.
-\def\clearbibitem#1{\setvalue{\??pb @#1}{}}%
+\unexpanded\def\clearbibitem#1{\setvalue{\??pb @#1}{}}%
-\def\clearbibitemtwo#1% is this reset really needed? after all we reset the counter and we are local
+\unexpanded\def\clearbibitemtwo#1% is this reset really needed? after all we reset the counter and we are local
{%\dofastrecurse\plusone{\csname#1@num\endcsname}\plusone{\expandafter\let\csname\??pb @#1\recurselevel\undefined}%
\letvalue{#1@num}\!!zerocount}
-\def\bibitemdefs#1%
- {\@EA\let\csname#1\expandafter\endcsname\csname bib@#1\endcsname}
+\unexpanded\def\bibitemdefs#1%
+ {\expandafter\let\csname#1\expandafter\endcsname\csname bib@#1\endcsname}
-\def\presetbibvariables % make a fast resetter (toks)
+\unexpanded\def\presetbibvariables % make a fast resetter (toks)
{\processcommacommand[\bibcommandlist,crossref]\clearbibitem
\processcommalist [artauthor,author,editor]\clearbibitemtwo
\processcommacommand[\bibcommandlist]\bibitemdefs
@@ -637,8 +641,6 @@
%D We are coming to the end of this module, to the macros that
%D do typesetting and read the \type{bbl} file.
-\newcount\bibtexcounter
-
%D Just a \type{\dosingleempty} is the most friendly
%D of doing this: there need not even be an argument
%D to \type{\startpublication}. Of course, then there
@@ -677,7 +679,7 @@
% hm, we can store at the lua end ...
-\def\dostartpublication[#1]%
+\unexpanded\def\dostartpublication[#1]%
{\begingroup
\doifassignmentelse{#1}%
{\getparameters[\??pb][k=\s!unknown,t=article,n=,s=,a=,y=,o=,u=,#1]}%
@@ -686,7 +688,7 @@
\catcode\commentasciicode\othercatcode
\dodostartpublication}
-\def\dodostartpublication#1\stoppublication
+\unexpanded\def\dodostartpublication#1\stoppublication
{\setxvalue{pbd:\@@pbk}##1{\noexpand\ifcase##1\noexpand\or
\@@pbk\noexpand\or
\@@pba\noexpand\or
@@ -710,7 +712,7 @@
\def\bibgetvaru#1{\csname pbd:#1\endcsname\pluseight}
\def\bibgetvard#1{\csname pbd:#1\endcsname\plusnine }
-\def\doifbibreferencefoundelse#1%
+\unexpanded\def\doifbibreferencefoundelse#1%
{\preloadbiblist
\doifdefinedelse{pbd:#1}
\firstoftwoarguments
@@ -726,10 +728,10 @@
% used in bib self
-\def\bib@crossref#1% called via \csname \endcsname
+\unexpanded\def\bib@crossref#1% called via \csname \endcsname
{\setvalue{\??pb @crossref}{#1}\ignorespaces}
-\def\bibinsertcrossref#1#2#3%
+\unexpanded\def\bibinsertcrossref#1#2#3%
{\bibdoifelse\@@pb@crossref{#1\cite[\@@pb@crossref]#2}{#3}}
\let\insertcrossref\gobblethreearguments
@@ -741,7 +743,7 @@
%D item (like the 'short' key). For this, the ID of the current
%D item is passed in the implict parameter \type{\currentpublicationkey}
-\def\doprocessbibtexentry#1{\typesetapublication{#1}}
+\unexpanded\def\doprocessbibtexentry#1{\typesetapublication{#1}}
\unexpanded\def\typesetpubslist
{\begingroup
@@ -755,7 +757,7 @@
\ctxlua{bibtex.hacks.filterall()}}
{\doif{\listparameter\c!criterium}\v!cite
{\setuplist[pubs][\c!criterium=\v!here]}%
- \doplacestructurelist
+ \strc_lists_place_current
{pubs}%
{\listparameter\c!criterium}%
{\listparameter\c!number}%
@@ -814,7 +816,7 @@
\unexpanded\def\completepublications
{\dosingleempty\docompletepublications}
-\def\docompletepublications[#1]%
+\unexpanded\def\docompletepublications[#1]%
{\begingroup
\setuplist[pubs][#1]%
\edef\currentbibtexsessiontitle{\publicationlistparameter\c!title}%
@@ -834,13 +836,13 @@
\unexpanded\def\placepublications
{\dosingleempty\doplacepublications}
-\def\doplacepublications[#1]%
+\unexpanded\def\doplacepublications[#1]%
{\begingroup
\setuplist[pubs][#1]%
\dodoplacepublications
\endgroup}
-\def\dodoplacepublications
+\unexpanded\def\dodoplacepublications
{\determinelistcharacteristics[pubs]%
\initializepubslist
\doifnot{\namedlistparameter{pubs}\c!option}\v!continue
@@ -870,7 +872,7 @@
% we'll define proper handlers later
-\def\doplacepublicationindeed#1%
+\unexpanded\def\doplacepublicationindeed#1%
{\doifbibreferencefoundelse{#1}
{\global\advance\bibtexcounter\plusone
\def\currentpublicationkey{#1}%
@@ -882,11 +884,11 @@
\strc_lists_apply_renderingsetup}
{}} % invalid
-\def\bibtexpubtext
+\unexpanded\def\bibtexpubtext
{\expanded{\reference[\bibrefprefix\currentpublicationkey]{\number\bibtexcounter}}%
\strut\dotypesetapublication\currentpublicationkey\strut}
-\def\dotypesetapublication#1%
+\unexpanded\def\dotypesetapublication#1%
{\bgroup
\the\initializebibdefinitions % NEW
\def\@@currentalternative{:l:}%
@@ -907,9 +909,9 @@
%D This is the result of bibtex's `language' field.
-\def\setbiblanguage#1#2{\setvalue{\??pb\s!language#1}{#2}}
+\unexpanded\def\setbiblanguage#1#2{\setvalue{\??pb\s!language#1}{#2}}
-\def\lang#1%
+\unexpanded\def\lang#1%
{\edef\biblanguage{#1}%
\ifcsname\??pb\s!language#1\endcsname
\language[\getvalue{\??pb\s!language#1}]%
@@ -927,13 +929,13 @@
\unexpanded\def\cite
{\strictdoifnextoptionalelse\dodocite\dobibref}
-\def\dobibref#1%
+\unexpanded\def\dobibref#1%
{\docite[#1][]}
-\def\dodocite[#1]%
+\unexpanded\def\dodocite[#1]%
{\strictdoifnextoptionalelse{\docite[#1]}{\docite[#1][]}}
-\def\docite[#1][#2]%
+\unexpanded\def\docite[#1][#2]%
{\begingroup
\doifelsenothing{#2}\secondargumentfalse\secondargumenttrue
\ifsecondargument
@@ -943,7 +945,7 @@
\fi
\endgroup}
-\def\dowhatevercite#1#2%
+\unexpanded\def\dowhatevercite#1#2%
{\processcommalist[#2]\docitation
\setupinteraction[\c!style=]%
\doifassignmentelse
@@ -971,7 +973,7 @@
\doifelsevalue{@@pv\@@currentalternative\c!compress}\v!no\bibcitecompressfalse\bibcitecompresstrue
\getvalue{bib\@@currentalternative ref}[#2]}
-\def\donumberedcite#1%
+\unexpanded\def\donumberedcite#1%
{\processcommalist[#1]\docitation
\setupinteraction[\c!style=]%
\edef\@@currentalternative{\@@citedefault}%
@@ -980,14 +982,14 @@
%D \macros{nocite}
-\def\nocite[#1]%
+\unexpanded\def\nocite[#1]%
{\processcommalist[#1]\docitation}
%D \macros{setupcite}
\unexpanded\def\setupcite{\dodoubleempty\dosetupcite}
-\def\dosetupcite[#1][#2]%
+\unexpanded\def\dosetupcite[#1][#2]%
{\ifsecondargument
\def\dodosetupcite##1{\getparameters[\??pv##1][#2]}%
\processcommalist[#1]\dodosetupcite
@@ -997,7 +999,7 @@
%D Low-level stuff
-\def\getcitedata#1[#2]#3[#4]#5to#6%
+\unexpanded\def\getcitedata#1[#2]#3[#4]#5to#6%
{\bgroup
\dofetchapublication{#4}%
\doifdefinedelse{\??pb @bib#2}%
@@ -1005,12 +1007,12 @@
{\xdef#6{\getvalue{\??pb @#2}}}%
\egroup}
-\def\dofetchapublication#1%
+\unexpanded\def\dofetchapublication#1%
{\def\currentpublicationkey{#1}%
\presetbibvariables
\ignorespaces\bibgetvard{#1}}
-\def\docitation#1%
+\unexpanded\def\docitation#1%
{\iftrialtypesetting \else
\expanded{\writedatatolist[pubs][bibref=#1]}%
\fi}
@@ -1044,7 +1046,16 @@
%D Delegate this to \LUA.
-\def\ixbibauthoryear#1#2#3#4%
+% \let\ixlastcommand \relax
+% \let\ixsecondcomman \relax
+% \let\ixfirstcommand \relax
+% \let\thebibauthors \empty
+% \let\thebibyears \empty
+% \let\authorcount \!!zerocount
+
+\let\currentbibauthor\empty
+
+\unexpanded\def\ixbibauthoryear#1#2#3#4%
{\bgroup
\gdef\ixlastcommand {#4}%
\gdef\ixsecondcommand{#3}%
@@ -1066,17 +1077,17 @@
%D This macro only has to make sure that the lists
%D \type{\thebibauthors} and \type{\thebibyears} are printed.
-\def\dobibauthoryear
+\unexpanded\def\dobibauthoryear
{\scratchcounter\zerocount
\getcommacommandsize[\thebibauthors]%
\edef\authorcount{\commalistsize}%
- \@EA\processcommalist\@EA[\thebibauthors]\dodobibauthoryear}
+ \expandafter\processcommalist\expandafter[\thebibauthors]\dodobibauthoryear}
-\def\dodobibauthoryear#1%
+\unexpanded\def\dodobibauthoryear#1%
{\advance\scratchcounter\plusone
\edef\wantednumber{\the\scratchcounter}%
\getfromcommacommand[\thebibyears][\wantednumber]%
- \@EA\def\@EA\currentbibyear\@EA{\commalistelement}%
+ \expandafter\def\expandafter\currentbibyear\expandafter{\commalistelement}%
\setcurrentbibauthor{#1}%
\ifnum\scratchcounter=\plusone
\ixfirstcommand
@@ -1086,25 +1097,25 @@
\ixsecondcommand
\fi\fi}
-\def\setcurrentbibauthor#1%
- {\getcommacommandsize[#1]%
- \ifcase\commalistsize
- % anonymous?
- \let\currentbibauthor\empty
- \or
- \def\currentbibauthor{#1}%
- \or
- \expanded{\docurrentbibauthor#1}%
- \else
- \handlemultiplebibauthors{\commalistsize}{#1}%
- \fi}
+\unexpanded\def\setcurrentbibauthor#1% sensitive for empty entries but I don't want to touch this
+ {\getcommacommandsize[#1]%
+ \ifcase\commalistsize
+ % anonymous?
+ \let\currentbibauthor\empty
+ \or
+ \def\currentbibauthor{#1}%
+ \or
+ \expanded{\docurrentbibauthor#1}%
+ \else
+ \handlemultiplebibauthors{\commalistsize}{#1}%
+ \fi}
\newcount\citescratchcounter
-\def\handlemultiplebibauthors#1#2%
+\unexpanded\def\handlemultiplebibauthors#1#2%
{\citescratchcounter\zerocount
\let\currentbibauthor\empty
- \def\bibprocessauthoritem##1%
+ \unexpanded\def\bibprocessauthoritem##1%
{\advance\citescratchcounter\plusone
\ifnum \citescratchcounter=#1\relax
\edef\currentbibauthor{\currentbibauthor##1}%
@@ -1122,10 +1133,10 @@
%D This discovery of authoretallimit is not the best one,
%D but it will do for now.
-\def\docurrentbibauthor#1,#2%
+\unexpanded\def\docurrentbibauthor#1,#2%
{\doifemptyelse{#2}
{\def\currentbibauthor{#1\bibalternative{otherstext}}}
- {\@EA\ifx\csname\??pv\@@currentalternative authoretallimit\endcsname\relax
+ {\expandafter\ifx\csname\??pv\@@currentalternative authoretallimit\endcsname\relax
\edef\currentbibauthor{#1\bibalternative{andtext}#2}%
\else
\edef\currentbibauthor{#1%
@@ -1137,7 +1148,7 @@
%D edef, and the \type{\robustdoifinsetelse} doesn't listen to
%D \type{\doglobal }
-\def\robustaddtocommalist#1#2% {item} \cs
+\unexpanded\def\robustaddtocommalist#1#2% {item} \cs
{\robustdoifinsetelse{#1}#2\resetglobal
{\dodoglobal\xdef#2{\ifx#2\empty\else#2,\fi#1}}}
@@ -1146,15 +1157,15 @@
%D Now we get to the macros that fill the two lists.
%D The `simple' one really is quite simple.
-\def\donormalbibauthoryear#1%
+\unexpanded\def\donormalbibauthoryear#1%
{\def\myauthor{Xxxxxxxxxx}%
\def\myyear{0000}%
\doifbibreferencefoundelse{#1}
{\def\myauthor{{\bibgetvara{#1}}}%
\def\myyear {\bibgetvary{#1}}}%
{}%
- \@EA\doglobal\@EA\appendtocommalist\@EA{\myauthor}\thebibauthors
- \@EA\doglobal\@EA\appendtocommalist\@EA{\myyear }\thebibyears}
+ \expandafter\doglobal\expandafter\appendtocommalist\expandafter{\myauthor}\thebibauthors
+ \expandafter\doglobal\expandafter\appendtocommalist\expandafter{\myyear }\thebibyears}
%D \macros{docompressbibauthoryear}
%D
@@ -1162,7 +1173,7 @@
%D the reference is not found or the reference does not contain
%D author data. No questions marks o.s.s. (to be fixed later)
-\def\docompressbibauthoryear#1%
+\unexpanded\def\docompressbibauthoryear#1%
{\def\myauthor{Xxxxxxxxxx}%
\def\myyear {0000}%
\doifbibreferencefoundelse{#1}
@@ -1185,14 +1196,14 @@
%D \type{\bibitemwanted} are needed later to insert the year
%D information in the correct item of \type{\thebibyears}
-\def\checkifmyauthoralreadyexists
+\unexpanded\def\checkifmyauthoralreadyexists
{\doifemptyelsevalue{thebibauthors}
{\global\bibitemwanted \plusone
\global\bibitemcounter\plusone
\xdef\thebibauthors{{\myauthor}}}
{% the next weirdness is because according to \getcommalistsize,
% the length of \type{[{{},{}}]} is 2.
- \@EA\getcommalistsize\@EA[\thebibauthors,]%
+ \expandafter\getcommalistsize\expandafter[\thebibauthors,]%
\global\bibitemcounter\numexpr\commalistsize+\minusone\relax
\global\bibitemwanted \zerocount
\processcommacommand[\thebibauthors]\docomparemyauthor}}
@@ -1204,7 +1215,7 @@
%D the counters will stay at their present values and everything
%D will be setup properly to insert the year info.
-\def\docomparemyauthor#1%
+\unexpanded\def\docomparemyauthor#1%
{\global\advance\bibitemwanted \plusone
\def\mytempc{#1}%
\ifx\mytempc\myauthor
@@ -1212,12 +1223,12 @@
\else\ifnum\bibitemwanted=\bibitemcounter\relax
\global\advance\bibitemwanted \plusone
\global\bibitemcounter\bibitemwanted\relax
- \@EA\doglobal\@EA\robustaddtocommalist\@EA{{\myauthor}}\thebibauthors
+ \expandafter\doglobal\expandafter\robustaddtocommalist\expandafter{{\myauthor}}\thebibauthors
\fi\fi}
%D This macro should be clear now.
-\def\findmatchingyear
+\unexpanded\def\findmatchingyear
{\edef\wantednumber{\the\bibitemwanted}%
\getfromcommacommand[\thebibyears][\wantednumber]%
\ifx\commalistelement\empty
@@ -1234,9 +1245,9 @@
%D Beware, we can have cites without reference match.
-\def\gotobiblink#1[#2]{\doifreferencefoundelse{\bibrefprefix#2}{\goto{#1}[\bibrefprefix#2]}{#1}}
-\def\atbiblink [#1]{\doifreferencefoundelse{\bibrefprefix#1}{\at [\bibrefprefix#1]}{#1}}
-\def\inbiblink [#1]{\doifreferencefoundelse{\bibrefprefix#1}{\expanded{\goto{\currentreferencetext}}[\bibrefprefix#1]}{#1}}
+\unexpanded\def\gotobiblink#1[#2]{\doifreferencefoundelse{\bibrefprefix#2}{\goto{#1}[\bibrefprefix#2]}{#1}}
+\unexpanded\def\atbiblink [#1]{\doifreferencefoundelse{\bibrefprefix#1}{\at [\bibrefprefix#1]}{#1}}
+\unexpanded\def\inbiblink [#1]{\doifreferencefoundelse{\bibrefprefix#1}{\expanded{\goto{\currentreferencetext}}[\bibrefprefix#1]}{#1}}
%D \macros{bibauthoryearref,bibauthoryearsref,bibauthorref,bibyearref}
%D
@@ -1244,35 +1255,29 @@
%D \type{\ixbibauthoryearref} stores the data in the macros
%D \type{\currentbibauthor} and \type{\currentbibyear}.
-\def\ifbibinteractionelse
+\unexpanded\def\doifbibinteractionelse
{\iflocation
\edef\test{\bibalternative\c!interaction}%
\ifx\test\v!stop
- \@EA\@EA\@EA\secondoftwoarguments
+ \doubleexpandafter\secondoftwoarguments
\else
- \@EA\@EA\@EA\firstoftwoarguments
+ \doubleexpandafter\firstoftwoarguments
\fi
\else
- \@EA\secondoftwoarguments
+ \expandafter\secondoftwoarguments
\fi}
-\def\ifbibinteractionelse
- {\iflocation
- \doifelse{\bibalternative\c!interaction}\v!stop
- {\@EA\secondoftwoarguments}
- {\@EA\firstoftwoarguments}%
- \else
- \@EA\secondoftwoarguments
- \fi}
+% \unexpanded\def\bibmaybeinteractive#1#2%
+% {\ifbibcitecompress
+% #2%
+% \else
+% \doifbibinteractionelse{\gotobiblink{#2}[#1]}{#2}%
+% \fi}
-\def\bibmaybeinteractive#1#2%
- {\ifbibcitecompress
- #2%
- \else
- \ifbibinteractionelse{\gotobiblink{#2}[#1]}{#2}%
- \fi}
+\unexpanded\def\bibmaybeinteractive#1#2%
+ {\doifbibinteractionelse{\gotobiblink{#2}[#1]}{#2}}
-\def\bibauthoryearref[#1]%
+\unexpanded\def\bibauthoryearref[#1]%
{\ixbibauthoryear{#1}%
{\bibmaybeinteractive{#1}{{\currentbibauthor}\bibalternative\c!inbetween
\bibalternative\v!left{\currentbibyear}\bibalternative\v!right}}
@@ -1283,7 +1288,7 @@
\bibmaybeinteractive{#1}{{\currentbibauthor}\bibalternative\c!inbetween
\bibalternative\v!left {\currentbibyear}\bibalternative\v!right}}}
-\def\bibauthoryearsref[#1]%
+\unexpanded\def\bibauthoryearsref[#1]%
{\bibalternative\v!left
\ixbibauthoryear{#1}
{\bibmaybeinteractive{#1}{{\currentbibauthor}\bibalternative\c!inbetween{\currentbibyear}}}
@@ -1293,7 +1298,7 @@
\bibmaybeinteractive{#1}{{\currentbibauthor}\bibalternative\c!inbetween{\currentbibyear}}}%
\bibalternative\v!right}
-\def\bibauthorref[#1]%
+\unexpanded\def\bibauthorref[#1]%
{\bibalternative\v!left
\ixbibauthoryear{#1}%
{\bibmaybeinteractive{#1}{{\currentbibauthor}}}
@@ -1301,7 +1306,7 @@
{\bibalternative\c!lastpubsep\bibmaybeinteractive{#1}{{\currentbibauthor}}}%
\bibalternative\v!right}
-\def\bibyearref[#1]%
+\unexpanded\def\bibyearref[#1]%
{\bibalternative\v!left
\ixbibauthoryear{#1}%
{\bibmaybeinteractive{#1}{{\currentbibyear}}}
@@ -1318,109 +1323,109 @@
\newconditional\firstbibrefsep
-\def\bibresetrefsep
+\unexpanded\def\bibresetrefsep
{\settrue\firstbibrefsep}
-\def\bibinsertrefsep
+\unexpanded\def\bibinsertrefsep
{\ifconditional\firstbibrefsep
\setfalse\firstbibrefsep
\else
\bibalternative\c!pubsep
\fi}
-\def\bibshortref[#1]%
+\unexpanded\def\bibshortref[#1]%
{\bibalternative\v!left
\bibresetrefsep\processcommalist[#1]\dobibshortref
\bibalternative\v!right}
-\def\dobibshortref#1%
+\unexpanded\def\dobibshortref#1%
{\bibinsertrefsep
\doifbibreferencefoundelse{#1}
{\gotobiblink{\bibgetvars{#1}}[#1]}
{}}
-\def\bibserialref[#1]%
+\unexpanded\def\bibserialref[#1]%
{\bibalternative\v!left
\bibresetrefsep\processcommalist[#1]\dobibserialref
\bibalternative\v!right}
-\def\dobibserialref#1%
+\unexpanded\def\dobibserialref#1%
{\bibinsertrefsep
\doifbibreferencefoundelse{#1}
{\gotobiblink{\bibgetvarn{#1}}[#1]}
{}}
-\def\bibkeyref[#1]%
+\unexpanded\def\bibkeyref[#1]%
{\bibalternative\v!left
\bibresetrefsep\processcommalist[#1]\dobibkeyref
\bibalternative\v!right}
-\def\dobibkeyref#1%
+\unexpanded\def\dobibkeyref#1%
{\bibinsertrefsep
\gotobiblink{#1}[#1]}
-\def\bibgotoDOI#1#2%
- {\ifbibinteractionelse
+\unexpanded\def\bibgotoDOI#1#2%
+ {\doifbibinteractionelse
{\useURL[bibfooDoi#1][#2]%
\useURL[bibfoo#1][http://dx.doi.org/#2]%
\goto{\url[bibfooDoi#1]}[url(bibfoo#1)]}
{\hyphenatedurl{#2}}}
-\def\bibdoiref[#1]%
+\unexpanded\def\bibdoiref[#1]%
{\bibalternative\v!left
\bibresetrefsep\processcommalist[#1]\dobibdoiref
\bibalternative\v!right}
-\def\dobibdoiref#1%
+\unexpanded\def\dobibdoiref#1%
{\bibinsertrefsep
\doifbibreferencefoundelse{#1}
{\expanded{\bibgotoDOI{#1}{\bibgetvaro{#1}}}}
{}}
-\def\biburlref[#1]%
+\unexpanded\def\biburlref[#1]%
{\bibalternative\v!left
\bibresetrefsep\processcommalist[#1]\dobiburlref
\bibalternative\v!right}
-\def\bibgotoURL#1#2%
- {\ifbibinteractionelse
+\unexpanded\def\bibgotoURL#1#2%
+ {\doifbibinteractionelse
{\useURL[bibfoo#1][#2]\goto{\url[bibfoo#1]}[url(bibfoo#1)]}
{\hyphenatedurl{#2}}}
-\def\dobiburlref#1%
+\unexpanded\def\dobiburlref#1%
{\bibinsertrefsep
\doifbibreferencefoundelse{#1}
{\expanded{\bibgotoURL{#1}{\bibgetvaru{#1}}}}
{}}
-\def\bibtyperef[#1]%
+\unexpanded\def\bibtyperef[#1]%
{\bibalternative\v!left
\bibresetrefsep\processcommalist[#1]\dobibtyperef
\bibalternative\v!right}
-\def\dobibtyperef#1%
+\unexpanded\def\dobibtyperef#1%
{\bibinsertrefsep
\doifbibreferencefoundelse{#1}
{\gotobiblink{\bibgetvart{#1}}[#1]}
{}}
-\def\bibpageref[#1]%
+\unexpanded\def\bibpageref[#1]%
{\bibalternative\v!left
\bibresetrefsep\processcommalist[#1]\dobibpageref
\bibalternative\v!right}
-\def\dobibpageref#1%
+\unexpanded\def\dobibpageref#1%
{\bibinsertrefsep
- \ifbibinteractionelse
+ \doifbibinteractionelse
{\atbiblink[#1]}
{{\referencingfalse\at[#1]}}}
-\def\bibdataref[#1]%
+\unexpanded\def\bibdataref[#1]%
{\bibalternative\v!left
\bibresetrefsep\processcommalist[#1]\dobibdata
\bibalternative\v!right}
-\def\dobibdata#1%
+\unexpanded\def\dobibdata#1%
{\bibinsertrefsep
\doifbibreferencefoundelse{#1}
{\dotypesetapublication{#1}}
@@ -1430,7 +1435,7 @@
%D \macros{bibnumref}
-\def\bibnumref[#1]%
+\unexpanded\def\bibnumref[#1]%
{\begingroup
\bibalternative\v!left
\penalty\plustenthousand
@@ -1438,7 +1443,7 @@
\bibalternative\v!right
\endgroup}
-\def\dowithbibtexnumrefconnector#1#2%
+\unexpanded\def\dowithbibtexnumrefconnector#1#2%
{\ifnum#1>\plusone
\ifnum#2>\plusone
\ifnum#2=#1\relax
@@ -1449,12 +1454,12 @@
\fi
\fi}
-\def\dowithbibtexnumref#1#2#3#4#5% n, i, prefix block ref
+\unexpanded\def\dowithbibtexnumref#1#2#3#4#5% n, i, prefix block ref
{\dowithbibtexnumrefconnector{#1}{#2}%
\def\bibrefprefix{#4:}%
\inbiblink[#5]}
-\def\dowithbibtexnumrefrange#1#2#3#4#5#6#7% n, i, prefix block ref
+\unexpanded\def\dowithbibtexnumrefrange#1#2#3#4#5#6#7% n, i, prefix block ref
{\dowithbibtexnumrefconnector{#1}{#2}%
\def\bibrefprefix{#4:}%
\inbiblink[#5]%
@@ -1465,27 +1470,24 @@
%D By request from Sanjoy. This makes it easier to implement
%D \type{\citeasnoun}.
-\def\bibauthornumref[#1]%
+\unexpanded\def\bibauthornumref[#1]%
{\getcommalistsize[#1]%
\global\bibitemcounter\commalistsize
\bibresetrefsep
\processcommalist[#1]\dobibauthornumref}
-\def\dobibauthornumref#1%
- {\bibinsertrefsep
- \doifbibreferencefoundelse{#1}
- {\begingroup
- \bibgetvara{#1}%
- \bibalternative\c!inbetween
- \setuppublications[\c!refcommand=num]%
- \cite[#1]%
- \endgroup}
- {}}
+\unexpanded\def\dobibauthornumref#1%
+ {\bibinsertrefsep
+ \doifbibreferencefoundelse{#1}
+ {\begingroup
+ \cite[\c!left=,\c!right=,\c!alternative=\v!author][#1]%
+ \bibalternative\c!inbetween
+ \cite[num][#1]%
+ \endgroup}
+ {}}
%D And some defaults are loaded from bibl-apa:
-\def\c!monthconversion{monthconversion} % todo
-
\setuppublications
[\c!monthconversion=,
\c!alternative=apa,
@@ -1495,11 +1497,13 @@
\c!refcommand=num,
\c!numbercommand=\bibleftnumber]
-\def\preloadbiblist
+\unexpanded\def\preloadbiblist
{\globallet\preloadbiblist\relax
\dousepublications\jobname}
% \appendtoks \preloadbiblist \to \everysetuppublications
% \appendtoks \preloadbiblist \to \everystarttext
+\let\ifbibinteractionelse\doifbibinteractionelse
+
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/blob-ini.lua b/Master/texmf-dist/tex/context/base/blob-ini.lua
index b97485b1b93..4debaf94c5c 100644
--- a/Master/texmf-dist/tex/context/base/blob-ini.lua
+++ b/Master/texmf-dist/tex/context/base/blob-ini.lua
@@ -74,7 +74,7 @@ function blobs.dispose(t)
end
end
-function blobs.append(t,str) -- will be link nodes.link
+function blobs.append(t,str) -- compare concat and link
local typ = type(str)
local dummy = nil
if typ == "number" then
diff --git a/Master/texmf-dist/tex/context/base/buff-ini.lua b/Master/texmf-dist/tex/context/base/buff-ini.lua
index 7098679ca17..475d23efe84 100644
--- a/Master/texmf-dist/tex/context/base/buff-ini.lua
+++ b/Master/texmf-dist/tex/context/base/buff-ini.lua
@@ -13,21 +13,27 @@ local trace_visualize = false trackers.register("buffers.visualize", function(v
local report_buffers = logs.reporter("buffers","usage")
local report_grabbing = logs.reporter("buffers","grabbing")
+local context, commands = context, commands
+
local concat = table.concat
-local type, next = type, next
-local sub, format, match, find = string.sub, string.format, string.match, string.find
-local count, splitlines = string.count, string.splitlines
+local type, next, load = type, next, load
+local sub, format = string.sub, string.format
+local splitlines, validstring = string.splitlines, string.valid
+local P, Cs, patterns, lpegmatch = lpeg.P, lpeg.Cs, lpeg.patterns, lpeg.match
-local variables = interfaces.variables
+local variables = interfaces.variables
local settings_to_array = utilities.parsers.settings_to_array
+local formatters = string.formatters
+
+local v_yes = variables.yes
-local ctxcatcodes = tex.ctxcatcodes
-local txtcatcodes = tex.txtcatcodes
+local catcodenumbers = catcodes.numbers
-buffers = { }
+local ctxcatcodes = catcodenumbers.ctxcatcodes
+local txtcatcodes = catcodenumbers.txtcatcodes
+buffers = buffers or { }
local buffers = buffers
-local context = context
local cache = { }
@@ -84,6 +90,44 @@ local function collectcontent(names,separator) -- no print
end
end
+local function loadcontent(names) -- no print
+ if type(names) == "string" then
+ names = settings_to_array(names)
+ end
+ local nnames = #names
+ local ok = false
+ if nnames == 0 then
+ ok = load(getcontent("")) -- default buffer
+ elseif nnames == 1 then
+ ok = load(getcontent(names[1]))
+ else
+ -- lua 5.2 chunked load
+ local i = 0
+ ok = load(function()
+ while true do
+ i = i + 1
+ if i > nnames then
+ return nil
+ end
+ local c = getcontent(names[i])
+ if c == "" then
+ -- would trigger end of load
+ else
+ return c
+ end
+ end
+ end)
+ end
+ if ok then
+ return ok()
+ elseif nnames == 0 then
+ report_buffers("invalid lua code in default buffer")
+ else
+ report_buffers("invalid lua code in buffer %a",concat(names,","))
+ end
+end
+
+
buffers.raw = getcontent
buffers.erase = erase
buffers.assign = assign
@@ -92,22 +136,24 @@ buffers.exists = exists
buffers.getcontent = getcontent
buffers.getlines = getlines
buffers.collectcontent = collectcontent
+buffers.loadcontent = loadcontent
-- the context interface
commands.erasebuffer = erase
commands.assignbuffer = assign
-local P, patterns, lpegmatch = lpeg.P, lpeg.patterns, lpeg.match
+local anything = patterns.anything
+local alwaysmatched = patterns.alwaysmatched
local function countnesting(b,e)
local n
local g = P(b) / function() n = n + 1 end
+ P(e) / function() n = n - 1 end
- + patterns.anything
- local p = patterns.alwaysmatched / function() n = 0 end
+ + anything
+ local p = alwaysmatched / function() n = 0 end
* g^0
- * patterns.alwaysmatched / function() return n end
+ * alwaysmatched / function() return n end
return p
end
@@ -123,6 +169,67 @@ local continue = false
-- An \n is unlikely to show up as \r is the endlinechar but \n is more generic
-- for us.
+-- This fits the way we fetch verbatim: the indentatio before the sentinel
+-- determines the stripping.
+
+-- str = [[
+-- test test test test test test test
+-- test test test test test test test
+-- test test test test test test test
+--
+-- test test test test test test test
+-- test test test test test test test
+-- test test test test test test test
+-- ]]
+
+-- local function undent(str)
+-- local margin = match(str,"[\n\r]( +)[\n\r]*$") or ""
+-- local indent = #margin
+-- if indent > 0 then
+-- local lines = splitlines(str)
+-- local ok = true
+-- local pattern = "^" .. margin
+-- for i=1,#lines do
+-- local l = lines[i]
+-- if find(l,pattern) then
+-- lines[i] = sub(l,indent+1)
+-- else
+-- ok = false
+-- break
+-- end
+-- end
+-- if ok then
+-- return concat(lines,"\n")
+-- end
+-- end
+-- return str
+-- end
+
+-- how about tabs
+
+local getmargin = (Cs(P(" ")^1)*P(-1)+1)^1
+local eol = patterns.eol
+local whatever = (P(1)-eol)^0 * eol^1
+
+local strippers = { }
+
+local function undent(str) -- new version, needs testing
+ local margin = lpegmatch(getmargin,str)
+ if type(margin) ~= "string" then
+ return str
+ end
+ local indent = #margin
+ if indent == 0 then
+ return str
+ end
+ local stripper = strippers[indent]
+ if not stripper then
+ stripper = Cs((P(margin)/"" * whatever + eol^1)^1)
+ strippers[indent] = stripper
+ end
+ return lpegmatch(stripper,str) or str
+end
+
function commands.grabbuffer(name,begintag,endtag,bufferdata,catcodes) -- maybe move \\ to call
local dn = getcontent(name)
if dn == "" then
@@ -150,47 +257,27 @@ function commands.grabbuffer(name,begintag,endtag,bufferdata,catcodes) -- maybe
else
if continue then
dn = dn .. sub(bufferdata,2,-2) -- no \r, \n is more generic
+ elseif dn == "" then
+ dn = sub(bufferdata,2,-2)
else
- if dn == "" then
- dn = sub(bufferdata,2,-2)
- else
- dn = dn .. "\n" .. sub(bufferdata,2,-2) -- no \r, \n is more generic
- end
+ dn = dn .. "\n" .. sub(bufferdata,2,-2) -- no \r, \n is more generic
end
local last = sub(dn,-1)
if last == "\n" or last == "\r" then -- \n is unlikely as \r is the endlinechar
dn = sub(dn,1,-2)
end
if autoundent then
- local margin = match(dn,"[\n\r]( +)[\n\r]*$") or ""
- local indent = #margin
- if indent > 0 then
- local lines = splitlines(dn)
- local ok = true
- local pattern = "^" .. margin
- for i=1,#lines do
- local l = lines[i]
- if find(l,pattern) then
- lines[i] = sub(l,indent+1)
- else
- ok = false
- break
- end
- end
- if ok then
- dn = concat(lines,"\n")
- end
- end
+ dn = undent(dn)
end
end
assign(name,dn,catcodes)
- commands.testcase(more)
+ commands.doifelse(more)
end
-- The optional prefix hack is there for the typesetbuffer feature and
-- in mkii we needed that (this hidden feature is used in a manual).
-local function prepared(name,list) -- list is optional
+local function prepared(name,list,prefix) -- list is optional
if not list or list == "" then
list = name
end
@@ -201,7 +288,12 @@ local function prepared(name,list) -- list is optional
if content == "" then
content = "empty buffer"
end
- return tex.jobname .. "-" .. name .. ".tmp", content
+ if prefix then
+ local name = file.addsuffix(name,"tmp")
+ return tex.jobname .. "-" .. name, content
+ else
+ return name, content
+ end
end
local capsule = "\\starttext\n%s\n\\stoptext\n"
@@ -215,29 +307,29 @@ function commands.runbuffer(name,list,encapsulate)
local data = io.loaddata(name)
if data ~= content then
if trace_run then
- report_buffers("changes in '%s', processing forced",name)
+ report_buffers("changes in %a, processing forced",name)
end
io.savedata(name,content)
os.execute(format(command,name))
elseif trace_run then
- report_buffers("no changes in '%s', not processed",name)
+ report_buffers("no changes in %a, not processed",name)
end
end
-function commands.savebuffer(list,name) -- name is optional
- local name, content = prepared(name,list)
+function commands.savebuffer(list,name,prefix) -- name is optional
+ local name, content = prepared(name,list,prefix==v_yes)
io.savedata(name,content)
end
function commands.getbuffer(name)
local str = getcontent(name)
if str ~= "" then
- context.viafile(str)
+ context.viafile(str,formatters["buffer.%s"](validstring(name,"noname")))
end
end
function commands.getbuffermkvi(name) -- rather direct !
- context.viafile(resolvers.macros.preprocessed(getcontent(name)))
+ context.viafile(resolvers.macros.preprocessed(getcontent(name)),formatters["buffer.%s.mkiv"](validstring(name,"noname")))
end
function commands.gettexbuffer(name)
@@ -255,17 +347,10 @@ function commands.gettexbuffer(name)
end
end
-function commands.getbufferctxlua(name)
- local ok = loadstring(getcontent(name))
- if ok then
- ok()
- else
- report_buffers("invalid lua code in buffer '%s'",name)
- end
-end
+commands.getbufferctxlua = loadcontent
function commands.doifelsebuffer(name)
- commands.testcase(exists(name))
+ commands.doifelse(exists(name))
end
-- This only used for mp buffers and is a kludge. Don't change the
diff --git a/Master/texmf-dist/tex/context/base/buff-ini.mkii b/Master/texmf-dist/tex/context/base/buff-ini.mkii
index 40baaec9354..7fdb89e45cd 100644
--- a/Master/texmf-dist/tex/context/base/buff-ini.mkii
+++ b/Master/texmf-dist/tex/context/base/buff-ini.mkii
@@ -126,8 +126,8 @@
\let\processnextbufferline\processnextbufferlineA
\fi}
{\letbeundefined{#4}% \letvalue{#4}=\relax % \undefined
- \@EA\defconvertedargument\@EA\beginofblock\@EA{\csname#3\endcsname}% we could use defconvertedcommand here (no \@EA)
- \@EA\defconvertedargument\@EA\endofblock \@EA{\csname#4\endcsname}% we could use defconvertedcommand here (no \@EA)
+ \expandafter\defconvertedargument\expandafter\beginofblock\expandafter{\csname#3\endcsname}% we could use defconvertedcommand here (no \expandafter)
+ \expandafter\defconvertedargument\expandafter\endofblock \expandafter{\csname#4\endcsname}% we could use defconvertedcommand here (no \expandafter)
\ifcase\buffernestmode
\let\processnextbufferline\processnextbufferlineB
\or
@@ -314,17 +314,17 @@
\ifnum\currentbufferparagraph>\zerocount
\expandafter\dostartbufferparagraph
\else
- \expandafter\gobbleoneargument
+ \expandafter\gobblebufferparagraph
\fi}
\def\filterbufferparagraph#1#2%
{\advance\currentbufferparagraph \plusone
\ifcase\currentbufferparagraph
- \@EA\gobblebufferparagraph
+ \expandafter\gobblebufferparagraph
\else
\doifinsetelse{\the\currentbufferparagraph}{#2}
- {\@EA\dostartbufferparagraph}
- {\@EA\fakebufferparagraph}%
+ {\expandafter\dostartbufferparagraph}
+ {\expandafter\fakebufferparagraph}%
\fi
{#1}}
diff --git a/Master/texmf-dist/tex/context/base/buff-ini.mkiv b/Master/texmf-dist/tex/context/base/buff-ini.mkiv
index 239a274c0a8..7616a1deec9 100644
--- a/Master/texmf-dist/tex/context/base/buff-ini.mkiv
+++ b/Master/texmf-dist/tex/context/base/buff-ini.mkiv
@@ -34,9 +34,9 @@
\setuvalue{\e!start\v!buffer}%
{\begingroup % (3)
\obeylines
- \dosingleempty\buff_start}
+ \dodoubleempty\buff_start}
-\def\buff_start[#1]%
+\def\buff_start[#1][#2]%
{\buff_start_indeed{}{#1}{\e!start\v!buffer}{\e!stop\v!buffer}}
\def\buff_start_indeed#1#2#3#4% \donothing needed !
@@ -163,13 +163,28 @@
% x
% \stopbuffer
%
-% \savebuffer[x][temp.log]
+% \savebuffer[x] [temp] % gets name: jobname-temp.tmp
+% \savebufferinfile[x][temp.log] % gets name: temp.log
+
+\installcorenamespace{savebuffer}
+
+\installsetuponlycommandhandler \??savebuffer {savebuffer}
+
+\setupsavebuffer
+ [\c!list=,
+ \c!file=,
+ \c!prefix=\v!yes]
\unexpanded\def\savebuffer
{\dodoubleempty\buff_save}
\def\buff_save[#1][#2]%
- {\ctxcommand{savebuffer("#1","#2")}}
+ {\begingroup
+ \doifassignmentelse{#1}
+ {\setupcurrentsavebuffer[#1]}%
+ {\setupcurrentsavebuffer[\c!list={#1},\c!file=#2]}%
+ \ctxcommand{savebuffer("\directsavebufferparameter\c!list","\directsavebufferparameter\c!file","\directsavebufferparameter\c!prefix")}%
+ \endgroup}
%D Experimental: no expansion of commands in buffer!
@@ -199,4 +214,28 @@
\def\getbufferdata[#1]{\buff_get_stored_indeed{#1}}
+%D This is a weird one, moved from cont-new. Do we really need it? If not
+%D it will go away.
+
+\bgroup \permitcircumflexescape
+
+\obeylines % don't remove %'s !
+
+\gdef\collapsedspace#1%
+ {\ifx#1^^M%
+ \expandafter\collapsedspace
+ \else
+ \space
+ \expandafter#1%
+ \fi}
+
+\unexpanded\gdef\collapsespaces
+ {\prependtoksonce\relax\to\everyeof%
+ \ignorelines%
+ \ignoretabs%
+ \let\obeyedspace\collapsedspace%
+ \obeyspaces}
+
+\egroup
+
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/buff-par.lua b/Master/texmf-dist/tex/context/base/buff-par.lua
index 2015b0bc0a4..2c1cd40e9d1 100644
--- a/Master/texmf-dist/tex/context/base/buff-par.lua
+++ b/Master/texmf-dist/tex/context/base/buff-par.lua
@@ -1,4 +1,4 @@
-if not modules then modules = { } end modules ['buff-ini'] = {
+if not modules then modules = { } end modules ['buff-par'] = {
version = 1.001,
comment = "companion to buff-ini.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
@@ -6,21 +6,26 @@ if not modules then modules = { } end modules ['buff-ini'] = {
license = "see context related readme files"
}
-local trace_parallel = false trackers.register("buffers.parallel", function(v) trace_parallel = v end)
-
-local report_parallel = logs.reporter("buffers","parallel")
+local context, commands = context, commands
local insert, remove, find, gmatch = table.insert, table.remove, string.find, string.gmatch
local strip, format = string.strip, string.format
-local variables = interfaces.variables
+local trace_parallel = false trackers.register("buffers.parallel", function(v) trace_parallel = v end)
+
+local report_parallel = logs.reporter("buffers","parallel")
+
+local variables = interfaces.variables
+
+local parallel = buffers.parallel or { }
+buffers.parallel = parallel
-buffers.parallel = { } local parallel = buffers.parallel
+local settings_to_array = utilities.parsers.settings_to_array
-local data = { }
+local data = { }
function parallel.define(category,tags)
- local tags = utilities.parsers.settings_to_array(tags)
+ local tags = settings_to_array(tags)
local entries = { }
data[category] = {
tags = tags,
@@ -38,7 +43,7 @@ function parallel.reset(category,tags)
if not tags or tags == "" or tags == variables.all then
tags = table.keys(entries)
else
- tags = utilities.parsers.settings_to_array(tags)
+ tags = settings_to_array(tags)
end
for i=1,#tags do
entries[tags[i]] = {
@@ -76,7 +81,7 @@ function parallel.save(category,tag,content)
end
-- maybe no strip
-- use lpeg
- if find(content,"^%s*%[") then
+ if find(content,"%s*%[") then
local done = false
for label, content in gmatch(content,"%s*%[(.-)%]%s*([^%[]+)") do
if done then
@@ -86,7 +91,7 @@ function parallel.save(category,tag,content)
done = true
end
if trace_parallel and label ~= "" then
- report_parallel("reference found: category '%s', tag '%s', label '%s'",category,tag,label)
+ report_parallel("reference found of category %a, tag %a, label %a",category,tag,label)
end
line.label = label
line.content = strip(content)
@@ -175,5 +180,5 @@ commands.placeparallel = parallel.place
commands.resetparallel = parallel.reset
function commands.doifelseparallel(category,tags)
- commands.testcase(parallel.hassomecontent(category,tags))
+ commands.doifelse(parallel.hassomecontent(category,tags))
end
diff --git a/Master/texmf-dist/tex/context/base/buff-par.mkiv b/Master/texmf-dist/tex/context/base/buff-par.mkiv
deleted file mode 100644
index 7d35676bdec..00000000000
--- a/Master/texmf-dist/tex/context/base/buff-par.mkiv
+++ /dev/null
@@ -1,151 +0,0 @@
-%D \module
-%D [ file=buff-par,
-%D version=2010.12.05,
-%D title=\CONTEXT\ Buffer Macros,
-%D subtitle=Parallel,
-%D author=Hans Hagen,
-%D date=\currentdate,
-%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
-%C
-%C This module is part of the \CONTEXT\ macro||package and is
-%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
-%C details.
-
-\writestatus{loading}{ConTeXt Buffer Macros / Parallel}
-
-\registerctxluafile{buff-par}{1.001}
-
-%D This module is developped for Thomas Schmitz as part of
-%D a project.
-
-\unprotect
-
-\letvalue{\??px:}\empty
-
-\def\parallelparameter#1%
- {\csname\??px:%
- \ifcsname\??px:\currentparallel:\currentparallelinstance:#1\endcsname
- \currentparallel:\currentparallelinstance:#1%
- \else\ifcsname\??px:\currentparallel:#1\endcsname
- \currentparallel:#1%
- \else\ifcsname\??px:#1\endcsname
- #1%
- \fi\fi\fi
- \endcsname}
-
-\unexpanded\def\defineparallel
- {\dodoubleargument\dodefineparallel}
-
-\def\dodefineparallel[#1][#2]%
- {\ctxcommand{defineparallel("#1","#2")}%
- \processcommalist[#2]\dododefineparallel
- \setuvalue{\e!start#1}{\dostartparallelset{#1}}%
- \setuvalue{\e!stop #1}{\dostopparallelset}}
-
-\def\dododefineparallel#1%
- {\definebuffer[#1]%%
- \setuvalue{\e!stop#1}{\dowithparallel{#1}}}
-
-\def\dostartparallelset#1%
- {\def\currentparallel{#1}%
- \ctxcommand{nextparallel("\currentparallel")}}
-
-\def\dostopparallelset#1%
- {}
-
-\def\dowithparallel#1% defined moet ook aan de lua kant kunnen
- {\ctxcommand{saveparallel("\currentparallel","#1",buffers.raw("\thedefinedbuffer{#1}"))}}
-
-\unexpanded\def\placeparallel
- {\dotripleempty\doplaceparallel}
-
-\def\doplaceparallel[#1][#2][#3]%
- {\begingroup
- \def\currentparallel{#1}%
- \ctxcommand{placeparallel("\currentparallel","#2","#3")}%
- \endgroup}
-
-% was: \parallelparameter\c!command}
-
-\def\doflushparallel#1#2#3#4#5% {instance}{status}{line}{label}{content}
- {\begingroup
- \def\currentparallelinstance{#1}%
- \def\currentparallelnumber {#2}%
- \def\currentparallelline {#3}%
- \def\currentparallellabel {#4}%
- \def\currentparallelcontent {#5}%
- \ifcase#2\relax
- \expandafter\noflushparalleldefault
- \or
- \expandafter\doflushparalleldefault
- \fi
- \endgroup}
-
-\def\noflushparalleldefault{}
-\def\doflushparalleldefault{\directsetup{\parallelparameter\c!setups}}
-
-\startsetups parallel:place:default
- \hangafter\plusone
- \hangindent4em
- \dontleavehmode
- \hbox to 3em \bgroup
- \hss
- \bf
- \doifsomething \currentparallellabel {
- \textreference[\currentparallellabel]{\currentparallelline}
- }
- \currentparallelline
- \quad
- \egroup
- \currentparallelcontent
- \par
-\stopsetups
-
-\unexpanded\def\setupparallel
- {\dotripleempty\dosetupparallel}
-
-\def\dosetupparallel[#1][#2][#3]%
- {\ifthirdargument
- \getparameters[\??px:#1:#2:][#3]%
- \else\ifsecondargument
- \getparameters[\??px:#1:][#2]%
- \else
- \getparameters[\??px:][#1]% maybe no : here
- \fi\fi}
-
-\setupparallel
-% [\c!command=\doflushparalleldefault]
- [\c!setups=parallel:place:default]
-
-\def\doifelseparallel#1#2%
- {\cldcontext{commands.doifelseparallel("#1","#2")}}
-
-\def\resetparallel
- {\dodoubleempty\doresetparallel}
-
-\def\resetparallel[#1][#2]%
- {\ctxcommand{resetparallel("#1","#2"))}}
-
-% default
-
-% \def\doflushparalleldefault#1#2#3#4% todo: setups instead
-% {\ifcase#1\or
-% \begingroup
-% \hangafter1
-% \hangindent4em
-% \dontleavehmode
-% \hbox to 3em{\hss\bf\doifsomething{#3}{\textreference[#3]{#2}}#2\quad}#4\par
-% \endgroup
-% \fi}
-
-\protect \endinput
-
-% \def\dododefineparallel#1%
-% {\setuvalue{\e!stop #1}{}%
-% \setuvalue{\e!start#1}{\dostartparallel{#1}}}
-%
-% \def\dostartparallel#1%
-% {\grabuntil{\e!stop#1}{\dododostartparallel{#1}}}
-%
-% \def\dododostartparallel#1#2%
-% {\ctxcommand{saveparallel("\currentparallel","#1",\!!bs\detokenize{#2}\!!es)}}
diff --git a/Master/texmf-dist/tex/context/base/buff-par.mkvi b/Master/texmf-dist/tex/context/base/buff-par.mkvi
new file mode 100644
index 00000000000..404fa8ef30e
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/buff-par.mkvi
@@ -0,0 +1,131 @@
+%D \module
+%D [ file=buff-par,
+%D version=2010.12.05,
+%D title=\CONTEXT\ Buffer Macros,
+%D subtitle=Parallel,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Buffer Macros / Parallel}
+
+\registerctxluafile{buff-par}{1.001}
+
+%D This module is developped for Thomas Schmitz as part of a project. There is
+%D no documentation yet.
+%D
+%D \starttyping
+%D \defineparallel[main][one,two]
+%D
+%D \startmain
+%D \startone
+%D first 1
+%D [reference] first 2
+%D first 3
+%D \stopone
+%D \starttwo
+%D second 1
+%D \stoptwo
+%D \stopmain
+%D
+%D \placeparallel[main][one,two][criterium=all]
+
+%D criterium=all start= n=
+
+\unprotect
+
+\installcorenamespace{parallel}
+
+\installcommandhandler \??parallel {parallel} \??parallel
+
+\setupparallel
+ [\c!setups=parallel:place:default]
+
+\let\buff_parallel_define_saved\defineparallel
+
+\unexpanded\def\defineparallel
+ {\dodoubleargument\buff_parallel_define}
+
+\def\buff_parallel_define[#name][#instances]%
+ {\buff_parallel_define_saved[#name]
+ \ctxcommand{defineparallel("#name","#instances")}%
+ \processcommalist[#instances]\buff_parallel_define_instance
+ \setuevalue{\e!start#name}{\buff_parallel_start{#name}}%
+ \setuevalue{\e!stop #name}{\buff_parallel_stop}}
+
+\def\buff_parallel_define_instance#instance%
+ {\normalexpanded{\buff_parallel_define_saved[#instance][\currentparallel]}%
+ \definebuffer[#instance]%
+ \setuevalue{\e!stop#instance}{\buff_parallel_save{#instance}}}
+
+\unexpanded\def\buff_parallel_start#name%
+ {\pushmacro\currentparallel
+ \edef\currentparallel{#name}%
+ \ctxcommand{nextparallel("\currentparallel")}}
+
+\unexpanded\def\buff_parallel_stop
+ {\popmacro\currentparallel}
+
+\unexpanded\def\buff_parallel_save#instance% defined moet ook aan de lua kant kunnen
+ {\ctxcommand{saveparallel("\currentparallel","#instance",buffers.raw("\thedefinedbuffer{#instance}"))}}
+
+\unexpanded\def\placeparallel
+ {\dotripleempty\buff_parallel_place}
+
+\def\buff_parallel_place[#name][#instance][#settings]%
+ {\begingroup
+ \edef\currentparallel{#name}%
+ \ctxcommand{placeparallel("\currentparallel","#instance","#settings")}% -- todo: pass options as k/v
+ \endgroup}
+
+\def\doflushparallel#instance#status#line#label#content% called at lua end
+ {\begingroup
+ \def\currentparallelinstance{#instance}%
+ \def\currentparallelnumber {#status}%
+ \def\currentparallelline {#line}%
+ \def\currentparallellabel {#label}%
+ \def\currentparallelcontent {#content}%
+ \ifcase#status\relax
+ \expandafter\buff_parallel_flush_nop
+ \or
+ \expandafter\buff_parallel_flush_yes
+ \fi
+ \endgroup}
+
+\def\buff_parallel_flush_nop
+ {}
+
+\def\buff_parallel_flush_yes
+ {\directsetup{\namedparallelparameter\currentparallelinstance\c!setups}}
+
+\unexpanded\def\doifelseparallel#name#instance%
+ {\ctxcommand{doifelseparallel("#name","#instance")}}
+
+\unexpanded\def\resetparallel
+ {\dodoubleempty\buff_parallel_reset}
+
+\def\buff_parallel_reset[#name][#instance]%
+ {\ctxcommand{resetparallel("#name","#instance"))}}
+
+\startsetups parallel:place:default
+ \hangafter\plusone
+ \hangindent4em
+ \dontleavehmode
+ \hbox to 3em \bgroup
+ \hss
+ \bf
+ \doifsomething \currentparallellabel {
+ \textreference[\currentparallellabel]{\currentparallelline}
+ }
+ \currentparallelline
+ \quad
+ \egroup
+ \currentparallelcontent
+ \par
+\stopsetups
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/buff-ver.lua b/Master/texmf-dist/tex/context/base/buff-ver.lua
index 004d8985896..e327a59dd9d 100644
--- a/Master/texmf-dist/tex/context/base/buff-ver.lua
+++ b/Master/texmf-dist/tex/context/base/buff-ver.lua
@@ -18,6 +18,8 @@ local concat = table.concat
local C, P, R, S, V, Carg, Cc, Cs = lpeg.C, lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.Carg, lpeg.Cc, lpeg.Cs
local patterns, lpegmatch, is_lpeg = lpeg.patterns, lpeg.match, lpeg.is_lpeg
+local context, commands = context, commands
+
local trace_visualize = false trackers.register("buffers.visualize", function(v) trace_visualize = v end)
local report_visualizers = logs.reporter("buffers","visualizers")
@@ -30,7 +32,6 @@ visualizers.specifications = specifications
local tabtospace = utilities.strings.tabtospace
local variables = interfaces.variables
local settings_to_array = utilities.parsers.settings_to_array
-local verbatim = context.verbatim
local variables = interfaces.variables
local findfile = resolvers.findfile
local addsuffix = file.addsuffix
@@ -52,6 +53,7 @@ local dodisplayverbatimemptyline = context.dodisplayverbatimemptyline
local dodisplayverbatimstart = context.dodisplayverbatimstart
local dodisplayverbatimstop = context.dodisplayverbatimstop
+local verbatim = context.verbatim
local doverbatimspace = context.doverbatimspace
local CargOne = Carg(1)
@@ -162,7 +164,7 @@ function visualizers.newgrammar(name,t)
g = g and g.grammar
if g then
if trace_visualize then
- report_visualizers("cloning grammar '%s'",name)
+ report_visualizers("cloning grammar %a",name)
end
for k,v in next, g do
if not t[k] then
@@ -181,12 +183,12 @@ local function getvisualizer(method,nature)
local m = specifications[method] or specifications.default
if nature then
if trace_visualize then
- report_visualizers("getting visualizer '%s' with nature '%s'",method,nature)
+ report_visualizers("getting visualizer %a with nature %a",method,nature)
end
return m and (m[nature] or m.parser) or nil
else
if trace_visualize then
- report_visualizers("getting visualizer '%s'",method)
+ report_visualizers("getting visualizer %a",method)
end
return m and m.parser or nil
end
@@ -196,7 +198,7 @@ local fallback = context.verbatim
local function makepattern(visualizer,replacement,pattern)
if not pattern then
- report_visualizers("error in visualizer: %s",replacement)
+ report_visualizers("error in visualizer %a",replacement)
return patterns.alwaystrue
else
if type(visualizer) == "table" and type(replacement) == "string" then
@@ -235,11 +237,11 @@ function visualizers.load(name)
end
if texname == "" or luaname == "" then
if trace_visualize then
- report_visualizers("unknown visualizer '%s'",name)
+ report_visualizers("unknown visualizer %a",name)
end
else
if trace_visualize then
- report_visualizers("loading visualizer '%s'",name)
+ report_visualizers("loading visualizer %a",name)
end
lua.registercode(luaname)
context.input(texname)
@@ -253,7 +255,7 @@ end
function visualizers.register(name,specification)
name = lower(name)
if trace_visualize then
- report_visualizers("registering visualizer '%s'",name)
+ report_visualizers("registering visualizer %a",name)
end
specifications[name] = specification
local parser, handler = specification.parser, specification.handler
@@ -356,7 +358,7 @@ function visualizers.registerescapepattern(name,befores,afters,normalmethod,esca
local after = afters[i]
local processor = processors[i]
if trace_visualize then
- report_visualizers("registering escape pattern, name: '%s', index: '%s', before: '%s', after: '%s', processor: '%s'",
+ report_visualizers("registering escape pattern, name %a, index %a, before %a, after %a, processor %a",
name,i,before,after,processor or "default")
end
before = P(before) * space_pattern
@@ -392,7 +394,7 @@ function visualizers.registerescapeline(name,befores,normalmethod,escapemethod,p
local before = befores[i]
local processor = processors[i]
if trace_visualize then
- report_visualizers("registering escape line pattern, name: '%s', before: '%s', after: <>",name,before)
+ report_visualizers("registering escape line pattern, name %a, before %a, after <>",name,before)
end
before = P(before) * space_pattern
after = space_pattern * P("\n")
@@ -422,7 +424,7 @@ function visualizers.registerescapecommand(name,token,normalmethod,escapecommand
local escapepattern = escapepatterns[name]
if not escapepattern then
if trace_visualize then
- report_visualizers("registering escape token, name: '%s', token: '%s'",name,token)
+ report_visualizers("registering escape token, name %a, token %a",name,token)
end
token = P(token)
local notoken = hack((1 - token)^1)
@@ -491,12 +493,12 @@ local function visualize(content,settings) -- maybe also method in settings
local n = m and m[nature]
if n then
if trace_visualize then
- report_visualizers("visualize using method '%s' and nature '%s'",method,nature)
+ report_visualizers("visualize using method %a and nature %a",method,nature)
end
n(content,settings)
else
if trace_visualize then
- report_visualizers("visualize using method '%s'",method)
+ report_visualizers("visualize using method %a",method)
end
fallback(content,1,settings)
end
@@ -506,9 +508,12 @@ end
visualizers.visualize = visualize
visualizers.getvisualizer = getvisualizer
+local fallbacks = { } table.setmetatableindex(fallbacks,function(t,k) local v = { nature = k } t[k] = v return v end)
+
local function checkedsettings(settings,nature)
if not settings then
- return { nature = nature }
+ -- let's avoid dummy tables as much as possible
+ return fallbacks[nature]
else
if not settings.nature then
settings.nature = nature
@@ -688,19 +693,19 @@ local getlines = buffers.getlines
-- interface
function commands.doifelsevisualizer(name)
- commands.testcase(specifications[lower(name)])
+ commands.doifelse(specifications[lower(name)])
end
commands.loadvisualizer = visualizers.load
---~ local decodecomment = resolvers.macros.decodecomment -- experiment
+-- local decodecomment = resolvers.macros.decodecomment -- experiment
function commands.typebuffer(settings)
local lines = getlines(settings.name)
if lines then
local content, m = filter(lines,settings)
if content and content ~= "" then
---~ content = decodecomment(content)
+ -- content = decodecomment(content)
content = dotabs(content,settings)
visualize(content,checkedsettings(settings,"display"))
end
@@ -732,7 +737,7 @@ local strip = Cs((P("\\") * ((1-S("\\ "))^1) * (P(" ")/"") + 1)^0) --
function commands.typestring(settings)
local content = settings.data
if content and content ~= "" then
- content = lpegmatch(strip,content) -- can be an option, btu needed in e.g. tabulate
+ content = #content > 1 and lpegmatch(strip,content) or content -- can be an option, but needed in e.g. tabulate
-- content = decodecomment(content)
-- content = dotabs(content,settings)
visualize(content,checkedsettings(settings,"inline"))
@@ -750,7 +755,7 @@ function commands.typefile(settings)
str = regimes.translate(str,regime)
end
if str and str~= "" then
---~ content = decodecomment(content)
+ -- content = decodecomment(content)
local lines = splitlines(str)
local content, m = filter(lines,settings)
if content and content ~= "" then
diff --git a/Master/texmf-dist/tex/context/base/buff-ver.mkiv b/Master/texmf-dist/tex/context/base/buff-ver.mkiv
index 5336c4458bd..430834a30d8 100644
--- a/Master/texmf-dist/tex/context/base/buff-ver.mkiv
+++ b/Master/texmf-dist/tex/context/base/buff-ver.mkiv
@@ -11,6 +11,8 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
+% check after-first and before-last breaks
+
\writestatus{loading}{ConTeXt Buffer Macros / Verbatim}
\registerctxluafile{buff-ver}{1.001}
@@ -70,21 +72,22 @@
\csname\??typingspace\typeparameter\c!space\endcsname
\relax\the\everyinitializeverbatim\relax}
+\unexpanded\def\doinitializeverbatim % for use elsewhere .. temp hack (see lxml-ini)
+ {\buff_verbatim_initialize_type_one
+ \buff_verbatim_initialize_type_two}
+
\let\buff_verbatim_set_line_margin\relax
\def\buff_verbatim_set_line_margin_indeed
- {\getpagestatus
- \hskip\ifrightpage\typingparameter\c!oddmargin\else\typingparameter\c!evenmargin\fi\relax}
+ {\hskip\doifoddpageelse{\typingparameter\c!oddmargin}{\typingparameter\c!evenmargin}\relax}
\def\buff_verbatim_check_margins
{\scratchskip\typingparameter\c!oddmargin\relax
- \ifzeropt\scratchskip
- \else
+ \ifzeropt\scratchskip \else
\let\buff_verbatim_set_line_margin\buff_verbatim_set_line_margin_indeed
\fi
\scratchskip\typingparameter\c!evenmargin\relax
- \ifzeropt\scratchskip
- \else
+ \ifzeropt\scratchskip \else
\let\buff_verbatim_set_line_margin\buff_verbatim_set_line_margin_indeed
\fi
\ifx\buff_verbatim_set_line_margin\relax
@@ -331,7 +334,7 @@
\unexpanded\def\specialfixedspace {\kern\interwordspace\relax}
\unexpanded\def\specialobeyedspace {\hskip\interwordspace\relax} % better than spaceskip
-\unexpanded\def\specialstretchedspace{\hskip.5\interwordspace\!!plus.125\interwordstretch\relax} % more but not less
+\unexpanded\def\specialstretchedspace{\hskip.5\interwordspace\s!plus.125\interwordstretch\relax} % more but not less
\unexpanded\def\specialcontrolspace {\hskip\zeropoint\hbox{\normalcontrolspace}\hskip\zeropoint\relax}
\unexpanded\def\obeyhyphens
@@ -369,7 +372,7 @@
\let\inlinemathmarker \textdollar
\def\displaymathmarker{\textdollar\textdollar}
-\def\buff_verbatim_special_type#1#2%
+\def\buff_verbatim_special_type#1#2#% # gobbles spaces
{\dontleavehmode\bgroup
\buff_verbatim_initialize_type_one
\catcode\leftbraceasciicode \begingroupcatcode
@@ -390,6 +393,8 @@
\unexpanded\def\astype{\bgroup\usetypestyleandcolor\c!style\c!color\let\nexttoken}
+\unexpanded\def\asciistr#1{\dontleavehmode{\verbatimfont\detokenize{#1}}} % use in some old styles
+
%D The basic display verbatim commands are defined in an indirect way. As we
%D will see, they are a specific case of a more general mechanism.
@@ -641,9 +646,9 @@
\c!text=\v!no,
\c!style=\tt,
\c!indentnext=\v!yes,
- \c!margin=\!!zeropoint,
- \c!evenmargin=\!!zeropoint,
- \c!oddmargin=\!!zeropoint,
+ \c!margin=\zeropoint,
+ \c!evenmargin=\zeropoint,
+ \c!oddmargin=\zeropoint,
\c!blank=\v!line,
%\c!escape=, % yes | no | {START,STOP} | default when yes: {BTEX,ETEX}
\c!numbering=\v!no,
@@ -836,4 +841,9 @@
% \usevisualizerstyleandcolor\c!style\c!color
% \let\next}
+\appendtoks
+ \def\type#1{\letterbackslash\checkedstrippedcsname#1}% or maybe detokenize
+ \def\tex #1{\letterbackslash#1}%
+\to \everysimplifycommands
+
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/catc-ctx.mkiv b/Master/texmf-dist/tex/context/base/catc-ctx.mkiv
index bd5c16d69a3..ddade7f52c3 100644
--- a/Master/texmf-dist/tex/context/base/catc-ctx.mkiv
+++ b/Master/texmf-dist/tex/context/base/catc-ctx.mkiv
@@ -128,11 +128,18 @@
% for the moment here:
-\def\starttexcode
+\normalprotected\def\starttexcode
{\pushcatcodetable
\catcodetable\prtcatcodes}
-\def\stoptexcode
+\normalprotected\def\stoptexcode
+ {\popcatcodetable}
+
+\normalprotected\def\startcontextcode
+ {\pushcatcodetable
+ \catcodetable\ctxcatcodes}
+
+\normalprotected\def\stopcontextcode
{\popcatcodetable}
\endinput
diff --git a/Master/texmf-dist/tex/context/base/catc-def.mkiv b/Master/texmf-dist/tex/context/base/catc-def.mkiv
index 26e8cb11ea2..cfbaed171e4 100644
--- a/Master/texmf-dist/tex/context/base/catc-def.mkiv
+++ b/Master/texmf-dist/tex/context/base/catc-def.mkiv
@@ -123,7 +123,7 @@
%D shortcuts to their character representation.
\chardef \^ = \circumflexasciicode
-\chardef \_ = \underscoreasciicode % but way too wide in lm, so ... until that's fixed:
+\chardef \_ = \underscoreasciicode
\chardef \& = \ampersandasciicode
\chardef \% = \commentasciicode
\chardef \# = \hashasciicode
@@ -133,8 +133,9 @@
\chardef \\ = \backslashasciicode
\chardef \| = \barasciicode
-%def\_{\leavevmode \kern.06em \vbox{\hrule width.3em}}
-\def\_{\dontleavehmode \kern.06em \vbox{\hrule width.3em}} % this will become a \chardef
+% way too wide in lm, so one can also use:
+%
+% \def\_{\dontleavehmode \kern.06em \vbox{\hrule width.3em}} % this will become a \chardef
%D From now on we can use the protection mechanisms.
diff --git a/Master/texmf-dist/tex/context/base/catc-ini.lua b/Master/texmf-dist/tex/context/base/catc-ini.lua
index b2c793a6a98..d4f9b65af07 100644
--- a/Master/texmf-dist/tex/context/base/catc-ini.lua
+++ b/Master/texmf-dist/tex/context/base/catc-ini.lua
@@ -6,8 +6,6 @@ if not modules then modules = { } end modules ['catc-ini'] = {
license = "see context related readme files"
}
--- todo: everywhere replace tex.ctxcatcodes -> catcodes.numbers.ctxcatcodes
-
catcodes = catcodes or { }
catcodes.numbers = catcodes.numbers or { }
catcodes.names = catcodes.names or { }
@@ -15,26 +13,29 @@ catcodes.names = catcodes.names or { }
storage.register("catcodes/numbers", catcodes.numbers, "catcodes.numbers")
storage.register("catcodes/names", catcodes.names, "catcodes.names")
+local numbers = catcodes.numbers
+local names = catcodes.names
+
-- this only happens at initime
function catcodes.register(name,number)
- catcodes.numbers[name] = number
- local cnn = catcodes.names[number]
+ numbers[name] = number
+ local cnn = names[number]
if cnn then
cnn[#cnn+1] = name
else
- catcodes.names[number] = { name }
+ names[number] = { name }
end
- tex[name] = number
+ tex[name] = number -- downward compatible
end
-- this only happens at runtime
-for k, v in next, catcodes.numbers do
- tex[k] = v
+for k, v in next, numbers do
+ tex[k] = v -- downward compatible
end
-- nasty
-table.setmetatableindex(catcodes.numbers,function(t,k) if type(k) == "number" then t[k] = k return k end end)
-table.setmetatableindex(catcodes.names, function(t,k) if type(k) == "string" then t[k] = k return k end end)
+table.setmetatableindex(numbers,function(t,k) if type(k) == "number" then t[k] = k return k end end)
+table.setmetatableindex(names, function(t,k) if type(k) == "string" then t[k] = k return k end end)
diff --git a/Master/texmf-dist/tex/context/base/catc-ini.mkiv b/Master/texmf-dist/tex/context/base/catc-ini.mkiv
index 26c3ceee990..791ce31c467 100644
--- a/Master/texmf-dist/tex/context/base/catc-ini.mkiv
+++ b/Master/texmf-dist/tex/context/base/catc-ini.mkiv
@@ -87,6 +87,17 @@
\xdef\outputnewlinechar{^^J}%
\endgroup}
+%D We predefine some prefixes ahead of syst-aux and mult-sys. We reserve 8 slots
+%D for catcodes.
+
+\def\??catcodelet {1>>} % let : \let
+\def\??catcodedef {2>>} % def : \def
+\def\??catcodeued {3>>} % ued : \unexpanded\def
+\def\??catcodeget {4>>} % \meaning
+
+\def\??catcodetablet{5>>}
+\def\??catcodetablen{6>>}
+
\newcount\c_syst_catcodes_n \c_syst_catcodes_n\zerocount % 0 = signal, so advance before allocate
\newcount\c_syst_catcodes_a
\newcount\c_syst_catcodes_b
@@ -94,7 +105,7 @@
\normalprotected\def\newcatcodetable#1% we could move the cctdefcounter to lua
{\global\advance\c_syst_catcodes_n\plusone
- \expandafter\xdef\csname\??qm:n:\number\c_syst_catcodes_n\endcsname{\string#1}% logging
+ \expandafter\xdef\csname\??catcodetablen\number\c_syst_catcodes_n\endcsname{\string#1}% logging
\newconstant#1%
#1\c_syst_catcodes_n
\ctxlua{catcodes.register("\expandafter\gobbleoneargument\string#1",\number#1)}}
@@ -151,12 +162,7 @@
\setnewconstant\c_syst_catcodes_hack\tildeasciicode
%D Once a catcode is assigned, the next assignments will happen
-%D faster. We predefine some prefixes ahead of mult-sys.
-
-\def\??ql{@@ql} % let : \let
-\def\??qd{@@qd} % def : \def
-\def\??qu{@@qu} % ued : \unexpanded\def
-\def\??qm{@@qm} % \meaning
+%D faster.
\def\letcatcodecommand{\afterassignment\syst_catcodes_let_a\c_syst_catcodes_a}
\def\defcatcodecommand{\afterassignment\syst_catcodes_def_a\c_syst_catcodes_a}
@@ -167,46 +173,46 @@
\def\syst_catcodes_ued_a{\afterassignment\syst_catcodes_ued_b\c_syst_catcodes_b}
\def\syst_catcodes_let_b % each time
- {\ifcsname\??ql:\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname
- \csname\??ql:\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\expandafter\endcsname
+ {\ifcsname\??catcodelet\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname
+ \csname\??catcodelet\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\expandafter\endcsname
\else
\expandafter\syst_catcodes_let_c
\fi}
\def\syst_catcodes_def_b % each time
- {\ifcsname\??qd:\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname
- \csname\??qd:\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\expandafter\endcsname
+ {\ifcsname\??catcodedef\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname
+ \csname\??catcodedef\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\expandafter\endcsname
\else
\expandafter\syst_catcodes_def_c
\fi}
\def\syst_catcodes_ued_b % each time
- {\ifcsname\??qu:\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname
- \csname\??qu:\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\expandafter\endcsname
+ {\ifcsname\??catcodeued\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname
+ \csname\??catcodeued\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\expandafter\endcsname
\else
\expandafter\syst_catcodes_ued_c
\fi}
\def\syst_catcodes_let_c % only first time
- {\expandafter\gdef\csname\??ql:\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\expandafter\endcsname\expandafter
- {\expandafter\let\csname\??qm:\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname}%
+ {\expandafter\gdef\csname\??catcodelet\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\expandafter\endcsname\expandafter
+ {\expandafter\let\csname\??catcodeget\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname}%
\syst_catcodes_reinstate_unexpanded
- \csname\??ql:\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname}
+ \csname\??catcodelet\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname}
\def\syst_catcodes_def_c % only first time (we could use \normalexpanded here)
- {\expandafter\gdef\csname\??qd:\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\expandafter\endcsname
+ {\expandafter\gdef\csname\??catcodedef\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\expandafter\endcsname
\expandafter##\expandafter1\expandafter
- {\expandafter\def\csname\??qm:\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname{##1}}%
+ {\expandafter\def\csname\??catcodeget\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname{##1}}%
\syst_catcodes_reinstate_normal
- \csname\??qd:\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname}
+ \csname\??catcodedef\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname}
\def\syst_catcodes_ued_c % only first time
- {\expandafter\gdef\csname\??qu:\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\expandafter\endcsname
+ {\expandafter\gdef\csname\??catcodeued\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\expandafter\endcsname
\expandafter##\expandafter1\expandafter
- {\expandafter\normalprotected\expandafter\def\csname\??qm:\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname{##1}}%
+ {\expandafter\normalprotected\expandafter\def\csname\??catcodeget\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname{##1}}%
\syst_catcodes_reinstate_unexpanded
- \csname\??qu:\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname}
+ \csname\??catcodeued\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname}
\def\reinstatecatcodecommand{\afterassignment\syst_catcodes_reinstate_normal\c_syst_catcodes_b}
@@ -227,8 +233,8 @@
\newconstant\defaultcatcodetable
\def\catcodecommand#1%
- {\csname\??qm:\number
- \ifcsname\??qm:\number\currentcatcodetable:\number#1\endcsname
+ {\csname\??catcodeget\number
+ \ifcsname\??catcodeget\number\currentcatcodetable:\number#1\endcsname
\currentcatcodetable \else \defaultcatcodetable
\fi
:\number#1\endcsname}
@@ -251,13 +257,13 @@
\normalprotected\def\pushcatcodetable
{\advance\c_syst_catcodes_level\plusone
\syst_catcodes_trace_push
- \expandafter\chardef\csname\??qm:t:\number\c_syst_catcodes_level\endcsname\currentcatcodetable}
+ \expandafter\chardef\csname\??catcodetablet\number\c_syst_catcodes_level\endcsname\currentcatcodetable}
\normalprotected\def\popcatcodetable
{\ifcase\c_syst_catcodes_level
\syst_catcodes_trace_nesting_error
\else
- \expandafter\catcodetable\csname\??qm:t:\number\c_syst_catcodes_level\endcsname
+ \expandafter\catcodetable\csname\??catcodetablet\number\c_syst_catcodes_level\endcsname
\syst_catcodes_trace_pop
\advance\c_syst_catcodes_level\minusone
\fi}
@@ -269,7 +275,7 @@
\normalprotected\def\restorecatcodes % takes previous level
{\ifnum\c_syst_catcodes_level>\plusone
- \expandafter\catcodetable\csname\??qm:t:\number\numexpr\c_syst_catcodes_level-1\relax\endcsname
+ \expandafter\catcodetable\csname\??catcodetablet\number\numexpr\c_syst_catcodes_level-1\relax\endcsname
\fi}
% \newtoks\everycatcodetable
@@ -294,14 +300,14 @@
\def\syst_catcodes_prev
{\ifnum\numexpr\c_syst_catcodes_level-1\relax>\zerocount
- \csname\??qm:n:\number\csname\??qm:t:\number\numexpr\c_syst_catcodes_level-1\relax\endcsname\endcsname
+ \csname\??catcodetablen\number\csname\??catcodetablet\number\numexpr\c_syst_catcodes_level-1\relax\endcsname\endcsname
\else
-%
\fi}
\def\catcodetablename
{\ifnum\currentcatcodetable>\zerocount
- \csname\??qm:n:\number\currentcatcodetable\endcsname
+ \csname\??catcodetablen\number\currentcatcodetable\endcsname
\else
-%
\fi}
diff --git a/Master/texmf-dist/tex/context/base/char-cjk.lua b/Master/texmf-dist/tex/context/base/char-cjk.lua
index b077f4a3e0e..3d7de142333 100644
--- a/Master/texmf-dist/tex/context/base/char-cjk.lua
+++ b/Master/texmf-dist/tex/context/base/char-cjk.lua
@@ -12,7 +12,8 @@ local floor = math.floor
local format = string.format
local utfchar = utf.char
-local ranges = characters.ranges
+local ranges = characters.ranges
+local allocate = utilities.storage.allocate
-- Hangul Syllable
@@ -209,7 +210,7 @@ local remapped = { -- this might be merged into char-def.lua
[0x11C2] = 0x314E, -- H
}
-characters.hangul = {
+characters.hangul = allocate {
decomposed = decomposed,
description = description,
leadconsonant = leadconsonant,
@@ -226,24 +227,6 @@ local hangul_syllable_basetable = {
linebreak = "h2",
}
---~ local hangul_syllable_metatable = {
---~ __index = function(t,k)
---~ local u = t.unicodeslot
---~ if k == "fscode" then
---~ -- no need to cache this as we normally use fscodes
---~ return leadconsonant(u)
---~ elseif k == "shcode" then
---~ return { decomposed(u) }
---~ elseif k == "specials" then
---~ return { "char", decomposed(u) }
---~ elseif k == "description" then
---~ return description(u)
---~ else
---~ return hangul_syllable_basetable[k]
---~ end
---~ end
---~ }
-
local hangul_syllable_metatable = {
__index = function(t,k)
local u = t.unicodeslot
diff --git a/Master/texmf-dist/tex/context/base/char-def.lua b/Master/texmf-dist/tex/context/base/char-def.lua
index 804468c2db4..8580fb6990b 100644
--- a/Master/texmf-dist/tex/context/base/char-def.lua
+++ b/Master/texmf-dist/tex/context/base/char-def.lua
@@ -3,15 +3,19 @@ if not modules then modules = { } end modules ['char-def'] = {
comment = "companion to char-ini.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
+ license = "see context related readme files",
+ dataonly = true,
}
--[[
-The first version of this table was generated from unicode tables
-but after that was mostly updated manual using data present in
-ConTeXt and elsewhere. I did my best to make this table as complete
-as needed for proper use in ConTeXt MkIV. All errors are mine. If
-you find an error or ommision, just let me know.
+The first version of this table was generated from unicode tables but after that was
+mostly updated manual using data present in ConTeXt and elsewhere. I did my best to
+make this table as complete as needed for proper use in ConTeXt MkIV. All errors are
+mine. If you find an error or ommision, just let me know. This file is updated every
+now and then using mtx-unicode where we check against the latest unicode txt files
+(normally once per year around the tex live code freeze) and checked afterwards for
+differences. We could save some bytes by sharing variant tables but it's not worth
+the trouble. Some additional data is kept in other files.
]]--
characters = characters or { }
@@ -310,6 +314,10 @@ characters.data={
direction="et",
linebreak="al",
unicodeslot=0x0023,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
{
adobename="dollar",
@@ -406,15 +414,6 @@ characters.data={
direction="cs",
linebreak="is",
mathclass="punctuation",
---mathspec={
--- {
--- class="punctuation",
--- },
--- {
--- class="ord",
--- name="mathcomma",
--- },
---},
unicodeslot=0x002C,
},
{
@@ -424,6 +423,8 @@ characters.data={
description="HYPHEN-MINUS",
direction="es",
linebreak="hy",
+ mathextensible="h",
+ mathfiller="relfill",
mathsymbol=0x2212,
unicodeslot=0x002D,
},
@@ -431,18 +432,13 @@ characters.data={
adobename="period",
category="po",
cjkwd="na",
+ comment="class needed for autopunctuation",
contextname="textperiod",
description="FULL STOP",
direction="cs",
linebreak="is",
- mathclass="ord",
+ mathclass="punctuation",
mathspec={
--- {
--- class="ord",
--- },
--- {
--- class="punctuation",
--- },
{
class="punctuation",
name="ldotp",
@@ -454,12 +450,21 @@ characters.data={
adobename="slash",
category="po",
cjkwd="na",
+ comment="mathsymbol=0x2044",
contextname="textslash",
description="SOLIDUS",
direction="cs",
linebreak="sy",
- mathclass="ord",
- mathsymbol=0x2044,
+ mathspec={
+ {
+ class="middle",
+ unicode=0x2044,
+ },
+ {
+ class="ordinary",
+ unicode=0x2044,
+ },
+ },
unicodeslot=0x002F,
},
{
@@ -471,6 +476,10 @@ characters.data={
linebreak="nu",
mathclass="number",
unicodeslot=0x0030,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
{
adobename="one",
@@ -481,6 +490,10 @@ characters.data={
linebreak="nu",
mathclass="number",
unicodeslot=0x0031,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
{
adobename="two",
@@ -491,6 +504,10 @@ characters.data={
linebreak="nu",
mathclass="number",
unicodeslot=0x0032,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
{
adobename="three",
@@ -501,6 +518,10 @@ characters.data={
linebreak="nu",
mathclass="number",
unicodeslot=0x0033,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
{
adobename="four",
@@ -511,6 +532,10 @@ characters.data={
linebreak="nu",
mathclass="number",
unicodeslot=0x0034,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
{
adobename="five",
@@ -521,6 +546,10 @@ characters.data={
linebreak="nu",
mathclass="number",
unicodeslot=0x0035,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
{
adobename="six",
@@ -531,6 +560,10 @@ characters.data={
linebreak="nu",
mathclass="number",
unicodeslot=0x0036,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
{
adobename="seven",
@@ -541,6 +574,10 @@ characters.data={
linebreak="nu",
mathclass="number",
unicodeslot=0x0037,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
{
adobename="eight",
@@ -551,6 +588,10 @@ characters.data={
linebreak="nu",
mathclass="number",
unicodeslot=0x0038,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
{
adobename="nine",
@@ -561,6 +602,10 @@ characters.data={
linebreak="nu",
mathclass="number",
unicodeslot=0x0039,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
{
adobename="colon",
@@ -603,15 +648,17 @@ characters.data={
description="EQUALS SIGN",
direction="on",
linebreak="al",
+ mathextensible="h",
+ mathfiller="equalfill",
mathspec={
- {
- class="relation",
- name="eq",
- },
- {
- class="relation",
- name="Relbar",
- },
+ {
+ class="relation",
+ name="eq",
+ },
+ {
+ class="relation",
+ name="Relbar",
+ },
},
unicodeslot=0x003D,
},
@@ -979,7 +1026,7 @@ characters.data={
description="CIRCUMFLEX ACCENT",
direction="on",
linebreak="al",
- mathclass="accent",
+ mathclass="topaccent",
unicodeslot=0x005E,
},
{
@@ -1000,7 +1047,7 @@ characters.data={
description="GRAVE ACCENT",
direction="on",
linebreak="al",
- mathclass="accent",
+ mathclass="topaccent",
mathname="grave",
unicodeslot=0x0060,
},
@@ -1684,7 +1731,7 @@ characters.data={
description="DIAERESIS",
direction="on",
linebreak="ai",
- mathclass="accent",
+ mathclass="topaccent",
mathname="ddot",
specials={ "compat", 0x0020, 0x0308 },
unicodeslot=0x00A8,
@@ -1729,11 +1776,11 @@ characters.data={
linebreak="al",
mathspec={
{
- class="ord",
+ class="ordinary",
name="lnot",
},
{
- class="ord",
+ class="ordinary",
name="neg",
},
},
@@ -1767,7 +1814,7 @@ characters.data={
description="MACRON",
direction="on",
linebreak="al",
- mathclass="accent",
+ mathclass="topaccent",
mathname="bar",
specials={ "compat", 0x0020, 0x0304 },
unicodeslot=0x00AF,
@@ -1824,7 +1871,7 @@ characters.data={
description="ACUTE ACCENT",
direction="on",
linebreak="bb",
- mathclass="accent",
+ mathclass="topaccent",
mathname="acute",
specials={ "compat", 0x0020, 0x0301 },
unicodeslot=0x00B4,
@@ -2538,7 +2585,7 @@ characters.data={
description="LATIN SMALL LETTER ETH",
direction="l",
linebreak="al",
- mathclass="ord",
+ mathclass="ordinary",
mathname="eth",
uccode=0x00D0,
unicodeslot=0x00F0,
@@ -3205,8 +3252,6 @@ characters.data={
description="LATIN SMALL LETTER H WITH STROKE",
direction="l",
linebreak="al",
- mathclass="ord",
- mathname="hbar",
shcode=0x0068,
uccode=0x0126,
unicodeslot=0x0127,
@@ -7479,7 +7524,7 @@ characters.data={
description="MODIFIER LETTER CIRCUMFLEX ACCENT",
direction="on",
linebreak="al",
- mathclass="accent",
+ mathclass="topaccent",
mathname="hat",
specials={ "compat", 0x0020, 0x0302 },
unicodeslot=0x02C6,
@@ -7493,7 +7538,7 @@ characters.data={
description="CARON",
direction="on",
linebreak="ai",
- mathclass="accent",
+ mathclass="topaccent",
mathname="check",
specials={ "compat", 0x0020, 0x030C },
unicodeslot=0x02C7,
@@ -7639,7 +7684,7 @@ characters.data={
description="BREVE",
direction="on",
linebreak="ai",
- mathclass="accent",
+ mathclass="topaccent",
mathname="breve",
specials={ "compat", 0x0020, 0x0306 },
unicodeslot=0x02D8,
@@ -7652,7 +7697,7 @@ characters.data={
description="DOT ABOVE",
direction="on",
linebreak="ai",
- mathclass="accent",
+ mathclass="topaccent",
mathname="dot",
specials={ "compat", 0x0020, 0x0307 },
unicodeslot=0x02D9,
@@ -7665,7 +7710,7 @@ characters.data={
description="RING ABOVE",
direction="on",
linebreak="ai",
- mathclass="accent",
+ mathclass="topaccent",
mathname="mathring",
specials={ "compat", 0x0020, 0x030A },
unicodeslot=0x02DA,
@@ -7688,7 +7733,7 @@ characters.data={
description="SMALL TILDE",
direction="on",
linebreak="al",
- mathclass="accent",
+ mathclass="topaccent",
mathname="tilde",
specials={ "compat", 0x0020, 0x0303 },
unicodeslot=0x02DC,
@@ -7982,6 +8027,8 @@ characters.data={
description="COMBINING CIRCUMFLEX ACCENT",
direction="nsm",
linebreak="cm",
+ mathclass="topaccent",
+ mathname="widehat",
mathstretch="h",
unicodeslot=0x0302,
},
@@ -7992,6 +8039,8 @@ characters.data={
description="COMBINING TILDE",
direction="nsm",
linebreak="cm",
+ mathclass="topaccent",
+ mathname="widetilde",
mathstretch="h",
unicodeslot=0x0303,
},
@@ -10252,7 +10301,7 @@ characters.data={
description="GREEK KAPPA SYMBOL",
direction="l",
linebreak="al",
- mathclass="ord",
+ mathclass="ordinary",
mathname="varkappa",
specials={ "compat", 0x03BA },
uccode=0x039A,
@@ -14174,6 +14223,13 @@ characters.data={
linebreak="ba",
unicodeslot=0x058A,
},
+ [0x058F]={
+ category="sc",
+ description="ARMENIAN DRAM SIGN",
+ direction="et",
+ linebreak="pr",
+ unicodeslot=0x058F,
+ },
[0x0591]={
adobename="etnahtalefthebrew",
category="mn",
@@ -14615,7 +14671,7 @@ characters.data={
contextname="hebrewAlef",
description="HEBREW LETTER ALEF",
direction="r",
- linebreak="al",
+ linebreak="hl",
unicodeslot=0x05D0,
},
[0x05D1]={
@@ -14624,7 +14680,7 @@ characters.data={
contextname="hebrewBet",
description="HEBREW LETTER BET",
direction="r",
- linebreak="al",
+ linebreak="hl",
unicodeslot=0x05D1,
},
[0x05D2]={
@@ -14633,7 +14689,7 @@ characters.data={
contextname="hebrewGimel",
description="HEBREW LETTER GIMEL",
direction="r",
- linebreak="al",
+ linebreak="hl",
unicodeslot=0x05D2,
},
[0x05D3]={
@@ -14642,7 +14698,7 @@ characters.data={
contextname="hebrewDalet",
description="HEBREW LETTER DALET",
direction="r",
- linebreak="al",
+ linebreak="hl",
unicodeslot=0x05D3,
},
[0x05D4]={
@@ -14651,7 +14707,7 @@ characters.data={
contextname="hebrewHe",
description="HEBREW LETTER HE",
direction="r",
- linebreak="al",
+ linebreak="hl",
unicodeslot=0x05D4,
},
[0x05D5]={
@@ -14660,7 +14716,7 @@ characters.data={
contextname="hebrewVav",
description="HEBREW LETTER VAV",
direction="r",
- linebreak="al",
+ linebreak="hl",
unicodeslot=0x05D5,
},
[0x05D6]={
@@ -14669,7 +14725,7 @@ characters.data={
contextname="hebrewZayin",
description="HEBREW LETTER ZAYIN",
direction="r",
- linebreak="al",
+ linebreak="hl",
unicodeslot=0x05D6,
},
[0x05D7]={
@@ -14678,7 +14734,7 @@ characters.data={
contextname="hebrewHet",
description="HEBREW LETTER HET",
direction="r",
- linebreak="al",
+ linebreak="hl",
unicodeslot=0x05D7,
},
[0x05D8]={
@@ -14687,7 +14743,7 @@ characters.data={
contextname="hebrewTet",
description="HEBREW LETTER TET",
direction="r",
- linebreak="al",
+ linebreak="hl",
unicodeslot=0x05D8,
},
[0x05D9]={
@@ -14696,7 +14752,7 @@ characters.data={
contextname="hebrewYod",
description="HEBREW LETTER YOD",
direction="r",
- linebreak="al",
+ linebreak="hl",
unicodeslot=0x05D9,
},
[0x05DA]={
@@ -14705,7 +14761,7 @@ characters.data={
contextname="hebrewKaffinal",
description="HEBREW LETTER FINAL KAF",
direction="r",
- linebreak="al",
+ linebreak="hl",
unicodeslot=0x05DA,
},
[0x05DB]={
@@ -14714,7 +14770,7 @@ characters.data={
contextname="hebrewKaf",
description="HEBREW LETTER KAF",
direction="r",
- linebreak="al",
+ linebreak="hl",
unicodeslot=0x05DB,
},
[0x05DC]={
@@ -14723,7 +14779,7 @@ characters.data={
contextname="hebrewLamed",
description="HEBREW LETTER LAMED",
direction="r",
- linebreak="al",
+ linebreak="hl",
unicodeslot=0x05DC,
},
[0x05DD]={
@@ -14732,7 +14788,7 @@ characters.data={
contextname="hebrewMemfinal",
description="HEBREW LETTER FINAL MEM",
direction="r",
- linebreak="al",
+ linebreak="hl",
unicodeslot=0x05DD,
},
[0x05DE]={
@@ -14741,7 +14797,7 @@ characters.data={
contextname="hebrewMem",
description="HEBREW LETTER MEM",
direction="r",
- linebreak="al",
+ linebreak="hl",
unicodeslot=0x05DE,
},
[0x05DF]={
@@ -14750,7 +14806,7 @@ characters.data={
contextname="hebrewNunfinal",
description="HEBREW LETTER FINAL NUN",
direction="r",
- linebreak="al",
+ linebreak="hl",
unicodeslot=0x05DF,
},
[0x05E0]={
@@ -14759,7 +14815,7 @@ characters.data={
contextname="hebrewNun",
description="HEBREW LETTER NUN",
direction="r",
- linebreak="al",
+ linebreak="hl",
unicodeslot=0x05E0,
},
[0x05E1]={
@@ -14768,7 +14824,7 @@ characters.data={
contextname="hebrewSamekh",
description="HEBREW LETTER SAMEKH",
direction="r",
- linebreak="al",
+ linebreak="hl",
unicodeslot=0x05E1,
},
[0x05E2]={
@@ -14777,7 +14833,7 @@ characters.data={
contextname="hebrewAyin",
description="HEBREW LETTER AYIN",
direction="r",
- linebreak="al",
+ linebreak="hl",
unicodeslot=0x05E2,
},
[0x05E3]={
@@ -14786,7 +14842,7 @@ characters.data={
contextname="hebrewPefinal",
description="HEBREW LETTER FINAL PE",
direction="r",
- linebreak="al",
+ linebreak="hl",
unicodeslot=0x05E3,
},
[0x05E4]={
@@ -14795,7 +14851,7 @@ characters.data={
contextname="hebrewPe",
description="HEBREW LETTER PE",
direction="r",
- linebreak="al",
+ linebreak="hl",
unicodeslot=0x05E4,
},
[0x05E5]={
@@ -14804,7 +14860,7 @@ characters.data={
contextname="hebrewTsadifinal",
description="HEBREW LETTER FINAL TSADI",
direction="r",
- linebreak="al",
+ linebreak="hl",
unicodeslot=0x05E5,
},
[0x05E6]={
@@ -14813,7 +14869,7 @@ characters.data={
contextname="hebrewTsadi",
description="HEBREW LETTER TSADI",
direction="r",
- linebreak="al",
+ linebreak="hl",
unicodeslot=0x05E6,
},
[0x05E7]={
@@ -14822,7 +14878,7 @@ characters.data={
contextname="hebrewQof",
description="HEBREW LETTER QOF",
direction="r",
- linebreak="al",
+ linebreak="hl",
unicodeslot=0x05E7,
},
[0x05E8]={
@@ -14831,7 +14887,7 @@ characters.data={
contextname="hebrewResh",
description="HEBREW LETTER RESH",
direction="r",
- linebreak="al",
+ linebreak="hl",
unicodeslot=0x05E8,
},
[0x05E9]={
@@ -14840,7 +14896,7 @@ characters.data={
contextname="hebrewShin",
description="HEBREW LETTER SHIN",
direction="r",
- linebreak="al",
+ linebreak="hl",
unicodeslot=0x05E9,
},
[0x05EA]={
@@ -14849,7 +14905,7 @@ characters.data={
contextname="hebrewTav",
description="HEBREW LETTER TAV",
direction="r",
- linebreak="al",
+ linebreak="hl",
unicodeslot=0x05EA,
},
[0x05F0]={
@@ -14857,7 +14913,7 @@ characters.data={
category="lo",
description="HEBREW LIGATURE YIDDISH DOUBLE VAV",
direction="r",
- linebreak="al",
+ linebreak="hl",
unicodeslot=0x05F0,
},
[0x05F1]={
@@ -14865,7 +14921,7 @@ characters.data={
category="lo",
description="HEBREW LIGATURE YIDDISH VAV YOD",
direction="r",
- linebreak="al",
+ linebreak="hl",
unicodeslot=0x05F1,
},
[0x05F2]={
@@ -14873,7 +14929,7 @@ characters.data={
category="lo",
description="HEBREW LIGATURE YIDDISH DOUBLE YOD",
direction="r",
- linebreak="al",
+ linebreak="hl",
unicodeslot=0x05F2,
},
[0x05F3]={
@@ -14893,6 +14949,7 @@ characters.data={
unicodeslot=0x05F4,
},
[0x0600]={
+ arabic="u",
category="cf",
description="ARABIC NUMBER SIGN",
direction="an",
@@ -14901,6 +14958,7 @@ characters.data={
visible="yes",
},
[0x0601]={
+ arabic="u",
category="cf",
description="ARABIC SIGN SANAH",
direction="an",
@@ -14909,6 +14967,7 @@ characters.data={
visible="yes",
},
[0x0602]={
+ arabic="u",
category="cf",
description="ARABIC FOOTNOTE MARKER",
direction="an",
@@ -14917,6 +14976,7 @@ characters.data={
visible="yes",
},
[0x0603]={
+ arabic="u",
category="cf",
description="ARABIC SIGN SAFHA",
direction="an",
@@ -14924,6 +14984,14 @@ characters.data={
unicodeslot=0x0603,
visible="yes",
},
+ [0x0604]={
+ arabic="u",
+ category="cf",
+ description="ARABIC SIGN SAMVAT",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x0604,
+ },
[0x0606]={
category="sm",
description="ARABIC-INDIC CUBE ROOT",
@@ -14939,6 +15007,7 @@ characters.data={
unicodeslot=0x0607,
},
[0x0608]={
+ arabic="u",
category="sm",
description="ARABIC RAY",
direction="al",
@@ -14960,6 +15029,7 @@ characters.data={
unicodeslot=0x060A,
},
[0x060B]={
+ arabic="u",
category="sc",
description="AFGHANI SIGN",
direction="al",
@@ -15096,6 +15166,7 @@ characters.data={
unicodeslot=0x061F,
},
[0x0620]={
+ arabic="d",
category="lo",
description="ARABIC LETTER KASHMIRI YEH",
direction="al",
@@ -15104,6 +15175,7 @@ characters.data={
},
[0x0621]={
adobename="hamzasukunarabic",
+ arabic="u",
category="lo",
description="ARABIC LETTER HAMZA",
direction="al",
@@ -15112,6 +15184,7 @@ characters.data={
},
[0x0622]={
adobename="alefmaddaabovearabic",
+ arabic="r",
category="lo",
description="ARABIC LETTER ALEF WITH MADDA ABOVE",
direction="al",
@@ -15122,6 +15195,7 @@ characters.data={
},
[0x0623]={
adobename="alefhamzaabovearabic",
+ arabic="r",
category="lo",
description="ARABIC LETTER ALEF WITH HAMZA ABOVE",
direction="al",
@@ -15132,6 +15206,7 @@ characters.data={
},
[0x0624]={
adobename="wawhamzaabovearabic",
+ arabic="r",
category="lo",
description="ARABIC LETTER WAW WITH HAMZA ABOVE",
direction="al",
@@ -15142,6 +15217,7 @@ characters.data={
},
[0x0625]={
adobename="alefhamzabelowarabic",
+ arabic="r",
category="lo",
description="ARABIC LETTER ALEF WITH HAMZA BELOW",
direction="al",
@@ -15152,6 +15228,7 @@ characters.data={
},
[0x0626]={
adobename="yehhamzaabovearabic",
+ arabic="d",
category="lo",
description="ARABIC LETTER YEH WITH HAMZA ABOVE",
direction="al",
@@ -15162,6 +15239,7 @@ characters.data={
},
[0x0627]={
adobename="alefarabic",
+ arabic="r",
category="lo",
description="ARABIC LETTER ALEF",
direction="al",
@@ -15170,6 +15248,7 @@ characters.data={
},
[0x0628]={
adobename="beharabic",
+ arabic="d",
category="lo",
description="ARABIC LETTER BEH",
direction="al",
@@ -15178,6 +15257,7 @@ characters.data={
},
[0x0629]={
adobename="tehmarbutaarabic",
+ arabic="r",
category="lo",
description="ARABIC LETTER TEH MARBUTA",
direction="al",
@@ -15186,6 +15266,7 @@ characters.data={
},
[0x062A]={
adobename="teharabic",
+ arabic="d",
category="lo",
description="ARABIC LETTER TEH",
direction="al",
@@ -15194,6 +15275,7 @@ characters.data={
},
[0x062B]={
adobename="theharabic",
+ arabic="d",
category="lo",
description="ARABIC LETTER THEH",
direction="al",
@@ -15202,6 +15284,7 @@ characters.data={
},
[0x062C]={
adobename="jeemarabic",
+ arabic="d",
category="lo",
description="ARABIC LETTER JEEM",
direction="al",
@@ -15210,6 +15293,7 @@ characters.data={
},
[0x062D]={
adobename="haharabic",
+ arabic="d",
category="lo",
description="ARABIC LETTER HAH",
direction="al",
@@ -15218,6 +15302,7 @@ characters.data={
},
[0x062E]={
adobename="khaharabic",
+ arabic="d",
category="lo",
description="ARABIC LETTER KHAH",
direction="al",
@@ -15226,6 +15311,7 @@ characters.data={
},
[0x062F]={
adobename="dalarabic",
+ arabic="r",
category="lo",
description="ARABIC LETTER DAL",
direction="al",
@@ -15234,6 +15320,7 @@ characters.data={
},
[0x0630]={
adobename="thalarabic",
+ arabic="r",
category="lo",
description="ARABIC LETTER THAL",
direction="al",
@@ -15242,6 +15329,7 @@ characters.data={
},
[0x0631]={
adobename="rehyehaleflamarabic",
+ arabic="r",
category="lo",
description="ARABIC LETTER REH",
direction="al",
@@ -15250,6 +15338,7 @@ characters.data={
},
[0x0632]={
adobename="zainarabic",
+ arabic="r",
category="lo",
description="ARABIC LETTER ZAIN",
direction="al",
@@ -15258,6 +15347,7 @@ characters.data={
},
[0x0633]={
adobename="seenarabic",
+ arabic="d",
category="lo",
description="ARABIC LETTER SEEN",
direction="al",
@@ -15266,6 +15356,7 @@ characters.data={
},
[0x0634]={
adobename="sheenarabic",
+ arabic="d",
category="lo",
description="ARABIC LETTER SHEEN",
direction="al",
@@ -15274,6 +15365,7 @@ characters.data={
},
[0x0635]={
adobename="sadarabic",
+ arabic="d",
category="lo",
description="ARABIC LETTER SAD",
direction="al",
@@ -15282,6 +15374,7 @@ characters.data={
},
[0x0636]={
adobename="dadarabic",
+ arabic="d",
category="lo",
description="ARABIC LETTER DAD",
direction="al",
@@ -15290,6 +15383,7 @@ characters.data={
},
[0x0637]={
adobename="taharabic",
+ arabic="d",
category="lo",
description="ARABIC LETTER TAH",
direction="al",
@@ -15298,6 +15392,7 @@ characters.data={
},
[0x0638]={
adobename="zaharabic",
+ arabic="d",
category="lo",
description="ARABIC LETTER ZAH",
direction="al",
@@ -15306,6 +15401,7 @@ characters.data={
},
[0x0639]={
adobename="ainarabic",
+ arabic="d",
category="lo",
description="ARABIC LETTER AIN",
direction="al",
@@ -15314,6 +15410,7 @@ characters.data={
},
[0x063A]={
adobename="ghainarabic",
+ arabic="d",
category="lo",
description="ARABIC LETTER GHAIN",
direction="al",
@@ -15321,6 +15418,7 @@ characters.data={
unicodeslot=0x063A,
},
[0x063B]={
+ arabic="d",
category="lo",
description="ARABIC LETTER KEHEH WITH TWO DOTS ABOVE",
direction="al",
@@ -15328,6 +15426,7 @@ characters.data={
unicodeslot=0x063B,
},
[0x063C]={
+ arabic="d",
category="lo",
description="ARABIC LETTER KEHEH WITH THREE DOTS BELOW",
direction="al",
@@ -15335,6 +15434,7 @@ characters.data={
unicodeslot=0x063C,
},
[0x063D]={
+ arabic="d",
category="lo",
description="ARABIC LETTER FARSI YEH WITH INVERTED V",
direction="al",
@@ -15342,6 +15442,7 @@ characters.data={
unicodeslot=0x063D,
},
[0x063E]={
+ arabic="d",
category="lo",
description="ARABIC LETTER FARSI YEH WITH TWO DOTS ABOVE",
direction="al",
@@ -15349,6 +15450,7 @@ characters.data={
unicodeslot=0x063E,
},
[0x063F]={
+ arabic="d",
category="lo",
description="ARABIC LETTER FARSI YEH WITH THREE DOTS ABOVE",
direction="al",
@@ -15357,6 +15459,7 @@ characters.data={
},
[0x0640]={
adobename="tatweelarabic",
+ arabic="c",
category="lm",
description="ARABIC TATWEEL",
direction="al",
@@ -15365,6 +15468,7 @@ characters.data={
},
[0x0641]={
adobename="feharabic",
+ arabic="d",
category="lo",
description="ARABIC LETTER FEH",
direction="al",
@@ -15373,6 +15477,7 @@ characters.data={
},
[0x0642]={
adobename="qafarabic",
+ arabic="d",
category="lo",
description="ARABIC LETTER QAF",
direction="al",
@@ -15381,6 +15486,7 @@ characters.data={
},
[0x0643]={
adobename="kafarabic",
+ arabic="d",
category="lo",
description="ARABIC LETTER KAF",
direction="al",
@@ -15389,6 +15495,7 @@ characters.data={
},
[0x0644]={
adobename="lamarabic",
+ arabic="d",
category="lo",
description="ARABIC LETTER LAM",
direction="al",
@@ -15397,6 +15504,7 @@ characters.data={
},
[0x0645]={
adobename="meemarabic",
+ arabic="d",
category="lo",
description="ARABIC LETTER MEEM",
direction="al",
@@ -15405,6 +15513,7 @@ characters.data={
},
[0x0646]={
adobename="noonarabic",
+ arabic="d",
category="lo",
description="ARABIC LETTER NOON",
direction="al",
@@ -15413,6 +15522,7 @@ characters.data={
},
[0x0647]={
adobename="heharabic",
+ arabic="d",
category="lo",
description="ARABIC LETTER HEH",
direction="al",
@@ -15421,6 +15531,7 @@ characters.data={
},
[0x0648]={
adobename="wawarabic",
+ arabic="r",
category="lo",
description="ARABIC LETTER WAW",
direction="al",
@@ -15429,6 +15540,7 @@ characters.data={
},
[0x0649]={
adobename="alefmaksuraarabic",
+ arabic="d",
category="lo",
description="ARABIC LETTER ALEF MAKSURA",
direction="al",
@@ -15437,6 +15549,7 @@ characters.data={
},
[0x064A]={
adobename="yeharabic",
+ arabic="d",
category="lo",
description="ARABIC LETTER YEH",
direction="al",
@@ -15711,6 +15824,7 @@ characters.data={
unicodeslot=0x066D,
},
[0x066E]={
+ arabic="d",
category="lo",
description="ARABIC LETTER DOTLESS BEH",
direction="al",
@@ -15718,6 +15832,7 @@ characters.data={
unicodeslot=0x066E,
},
[0x066F]={
+ arabic="d",
category="lo",
description="ARABIC LETTER DOTLESS QAF",
direction="al",
@@ -15732,6 +15847,7 @@ characters.data={
unicodeslot=0x0670,
},
[0x0671]={
+ arabic="r",
category="lo",
description="ARABIC LETTER ALEF WASLA",
direction="al",
@@ -15739,6 +15855,7 @@ characters.data={
unicodeslot=0x0671,
},
[0x0672]={
+ arabic="r",
category="lo",
description="ARABIC LETTER ALEF WITH WAVY HAMZA ABOVE",
direction="al",
@@ -15747,6 +15864,7 @@ characters.data={
unicodeslot=0x0672,
},
[0x0673]={
+ arabic="r",
category="lo",
description="ARABIC LETTER ALEF WITH WAVY HAMZA BELOW",
direction="al",
@@ -15755,6 +15873,7 @@ characters.data={
unicodeslot=0x0673,
},
[0x0674]={
+ arabic="u",
category="lo",
description="ARABIC LETTER HIGH HAMZA",
direction="al",
@@ -15762,6 +15881,7 @@ characters.data={
unicodeslot=0x0674,
},
[0x0675]={
+ arabic="r",
category="lo",
description="ARABIC LETTER HIGH HAMZA ALEF",
direction="al",
@@ -15770,6 +15890,7 @@ characters.data={
unicodeslot=0x0675,
},
[0x0676]={
+ arabic="r",
category="lo",
description="ARABIC LETTER HIGH HAMZA WAW",
direction="al",
@@ -15778,6 +15899,7 @@ characters.data={
unicodeslot=0x0676,
},
[0x0677]={
+ arabic="r",
category="lo",
description="ARABIC LETTER U WITH HAMZA ABOVE",
direction="al",
@@ -15787,6 +15909,7 @@ characters.data={
unicodeslot=0x0677,
},
[0x0678]={
+ arabic="d",
category="lo",
description="ARABIC LETTER HIGH HAMZA YEH",
direction="al",
@@ -15796,6 +15919,7 @@ characters.data={
},
[0x0679]={
adobename="tteharabic",
+ arabic="d",
category="lo",
description="ARABIC LETTER TTEH",
direction="al",
@@ -15803,6 +15927,7 @@ characters.data={
unicodeslot=0x0679,
},
[0x067A]={
+ arabic="d",
category="lo",
description="ARABIC LETTER TTEHEH",
direction="al",
@@ -15810,6 +15935,7 @@ characters.data={
unicodeslot=0x067A,
},
[0x067B]={
+ arabic="d",
category="lo",
description="ARABIC LETTER BEEH",
direction="al",
@@ -15817,6 +15943,7 @@ characters.data={
unicodeslot=0x067B,
},
[0x067C]={
+ arabic="d",
category="lo",
description="ARABIC LETTER TEH WITH RING",
direction="al",
@@ -15825,6 +15952,7 @@ characters.data={
unicodeslot=0x067C,
},
[0x067D]={
+ arabic="d",
category="lo",
description="ARABIC LETTER TEH WITH THREE DOTS ABOVE DOWNWARDS",
direction="al",
@@ -15834,6 +15962,7 @@ characters.data={
},
[0x067E]={
adobename="peharabic",
+ arabic="d",
category="lo",
description="ARABIC LETTER PEH",
direction="al",
@@ -15841,6 +15970,7 @@ characters.data={
unicodeslot=0x067E,
},
[0x067F]={
+ arabic="d",
category="lo",
description="ARABIC LETTER TEHEH",
direction="al",
@@ -15848,6 +15978,7 @@ characters.data={
unicodeslot=0x067F,
},
[0x0680]={
+ arabic="d",
category="lo",
description="ARABIC LETTER BEHEH",
direction="al",
@@ -15855,6 +15986,7 @@ characters.data={
unicodeslot=0x0680,
},
[0x0681]={
+ arabic="d",
category="lo",
description="ARABIC LETTER HAH WITH HAMZA ABOVE",
direction="al",
@@ -15863,6 +15995,7 @@ characters.data={
unicodeslot=0x0681,
},
[0x0682]={
+ arabic="d",
category="lo",
description="ARABIC LETTER HAH WITH TWO DOTS VERTICAL ABOVE",
direction="al",
@@ -15871,6 +16004,7 @@ characters.data={
unicodeslot=0x0682,
},
[0x0683]={
+ arabic="d",
category="lo",
description="ARABIC LETTER NYEH",
direction="al",
@@ -15878,6 +16012,7 @@ characters.data={
unicodeslot=0x0683,
},
[0x0684]={
+ arabic="d",
category="lo",
description="ARABIC LETTER DYEH",
direction="al",
@@ -15885,6 +16020,7 @@ characters.data={
unicodeslot=0x0684,
},
[0x0685]={
+ arabic="d",
category="lo",
description="ARABIC LETTER HAH WITH THREE DOTS ABOVE",
direction="al",
@@ -15894,6 +16030,7 @@ characters.data={
},
[0x0686]={
adobename="tcheharabic",
+ arabic="d",
category="lo",
description="ARABIC LETTER TCHEH",
direction="al",
@@ -15901,6 +16038,7 @@ characters.data={
unicodeslot=0x0686,
},
[0x0687]={
+ arabic="d",
category="lo",
description="ARABIC LETTER TCHEHEH",
direction="al",
@@ -15909,6 +16047,7 @@ characters.data={
},
[0x0688]={
adobename="ddalarabic",
+ arabic="r",
category="lo",
description="ARABIC LETTER DDAL",
direction="al",
@@ -15916,6 +16055,7 @@ characters.data={
unicodeslot=0x0688,
},
[0x0689]={
+ arabic="r",
category="lo",
description="ARABIC LETTER DAL WITH RING",
direction="al",
@@ -15924,6 +16064,7 @@ characters.data={
unicodeslot=0x0689,
},
[0x068A]={
+ arabic="r",
category="lo",
description="ARABIC LETTER DAL WITH DOT BELOW",
direction="al",
@@ -15932,6 +16073,7 @@ characters.data={
unicodeslot=0x068A,
},
[0x068B]={
+ arabic="r",
category="lo",
description="ARABIC LETTER DAL WITH DOT BELOW AND SMALL TAH",
direction="al",
@@ -15940,6 +16082,7 @@ characters.data={
unicodeslot=0x068B,
},
[0x068C]={
+ arabic="r",
category="lo",
description="ARABIC LETTER DAHAL",
direction="al",
@@ -15947,6 +16090,7 @@ characters.data={
unicodeslot=0x068C,
},
[0x068D]={
+ arabic="r",
category="lo",
description="ARABIC LETTER DDAHAL",
direction="al",
@@ -15954,6 +16098,7 @@ characters.data={
unicodeslot=0x068D,
},
[0x068E]={
+ arabic="r",
category="lo",
description="ARABIC LETTER DUL",
direction="al",
@@ -15961,6 +16106,7 @@ characters.data={
unicodeslot=0x068E,
},
[0x068F]={
+ arabic="r",
category="lo",
description="ARABIC LETTER DAL WITH THREE DOTS ABOVE DOWNWARDS",
direction="al",
@@ -15969,6 +16115,7 @@ characters.data={
unicodeslot=0x068F,
},
[0x0690]={
+ arabic="r",
category="lo",
description="ARABIC LETTER DAL WITH FOUR DOTS ABOVE",
direction="al",
@@ -15978,6 +16125,7 @@ characters.data={
},
[0x0691]={
adobename="rreharabic",
+ arabic="r",
category="lo",
description="ARABIC LETTER RREH",
direction="al",
@@ -15985,6 +16133,7 @@ characters.data={
unicodeslot=0x0691,
},
[0x0692]={
+ arabic="r",
category="lo",
description="ARABIC LETTER REH WITH SMALL V",
direction="al",
@@ -15993,6 +16142,7 @@ characters.data={
unicodeslot=0x0692,
},
[0x0693]={
+ arabic="r",
category="lo",
description="ARABIC LETTER REH WITH RING",
direction="al",
@@ -16001,6 +16151,7 @@ characters.data={
unicodeslot=0x0693,
},
[0x0694]={
+ arabic="r",
category="lo",
description="ARABIC LETTER REH WITH DOT BELOW",
direction="al",
@@ -16009,6 +16160,7 @@ characters.data={
unicodeslot=0x0694,
},
[0x0695]={
+ arabic="r",
category="lo",
description="ARABIC LETTER REH WITH SMALL V BELOW",
direction="al",
@@ -16017,6 +16169,7 @@ characters.data={
unicodeslot=0x0695,
},
[0x0696]={
+ arabic="r",
category="lo",
description="ARABIC LETTER REH WITH DOT BELOW AND DOT ABOVE",
direction="al",
@@ -16025,6 +16178,7 @@ characters.data={
unicodeslot=0x0696,
},
[0x0697]={
+ arabic="r",
category="lo",
description="ARABIC LETTER REH WITH TWO DOTS ABOVE",
direction="al",
@@ -16034,6 +16188,7 @@ characters.data={
},
[0x0698]={
adobename="jeharabic",
+ arabic="r",
category="lo",
description="ARABIC LETTER JEH",
direction="al",
@@ -16041,6 +16196,7 @@ characters.data={
unicodeslot=0x0698,
},
[0x0699]={
+ arabic="r",
category="lo",
description="ARABIC LETTER REH WITH FOUR DOTS ABOVE",
direction="al",
@@ -16049,6 +16205,7 @@ characters.data={
unicodeslot=0x0699,
},
[0x069A]={
+ arabic="d",
category="lo",
description="ARABIC LETTER SEEN WITH DOT BELOW AND DOT ABOVE",
direction="al",
@@ -16057,6 +16214,7 @@ characters.data={
unicodeslot=0x069A,
},
[0x069B]={
+ arabic="d",
category="lo",
description="ARABIC LETTER SEEN WITH THREE DOTS BELOW",
direction="al",
@@ -16065,6 +16223,7 @@ characters.data={
unicodeslot=0x069B,
},
[0x069C]={
+ arabic="d",
category="lo",
description="ARABIC LETTER SEEN WITH THREE DOTS BELOW AND THREE DOTS ABOVE",
direction="al",
@@ -16073,6 +16232,7 @@ characters.data={
unicodeslot=0x069C,
},
[0x069D]={
+ arabic="d",
category="lo",
description="ARABIC LETTER SAD WITH TWO DOTS BELOW",
direction="al",
@@ -16081,6 +16241,7 @@ characters.data={
unicodeslot=0x069D,
},
[0x069E]={
+ arabic="d",
category="lo",
description="ARABIC LETTER SAD WITH THREE DOTS ABOVE",
direction="al",
@@ -16089,6 +16250,7 @@ characters.data={
unicodeslot=0x069E,
},
[0x069F]={
+ arabic="d",
category="lo",
description="ARABIC LETTER TAH WITH THREE DOTS ABOVE",
direction="al",
@@ -16097,6 +16259,7 @@ characters.data={
unicodeslot=0x069F,
},
[0x06A0]={
+ arabic="d",
category="lo",
description="ARABIC LETTER AIN WITH THREE DOTS ABOVE",
direction="al",
@@ -16105,6 +16268,7 @@ characters.data={
unicodeslot=0x06A0,
},
[0x06A1]={
+ arabic="d",
category="lo",
description="ARABIC LETTER DOTLESS FEH",
direction="al",
@@ -16112,6 +16276,7 @@ characters.data={
unicodeslot=0x06A1,
},
[0x06A2]={
+ arabic="d",
category="lo",
description="ARABIC LETTER FEH WITH DOT MOVED BELOW",
direction="al",
@@ -16120,6 +16285,7 @@ characters.data={
unicodeslot=0x06A2,
},
[0x06A3]={
+ arabic="d",
category="lo",
description="ARABIC LETTER FEH WITH DOT BELOW",
direction="al",
@@ -16129,6 +16295,7 @@ characters.data={
},
[0x06A4]={
adobename="veharabic",
+ arabic="d",
category="lo",
description="ARABIC LETTER VEH",
direction="al",
@@ -16136,6 +16303,7 @@ characters.data={
unicodeslot=0x06A4,
},
[0x06A5]={
+ arabic="d",
category="lo",
description="ARABIC LETTER FEH WITH THREE DOTS BELOW",
direction="al",
@@ -16144,6 +16312,7 @@ characters.data={
unicodeslot=0x06A5,
},
[0x06A6]={
+ arabic="d",
category="lo",
description="ARABIC LETTER PEHEH",
direction="al",
@@ -16151,6 +16320,7 @@ characters.data={
unicodeslot=0x06A6,
},
[0x06A7]={
+ arabic="d",
category="lo",
description="ARABIC LETTER QAF WITH DOT ABOVE",
direction="al",
@@ -16159,6 +16329,7 @@ characters.data={
unicodeslot=0x06A7,
},
[0x06A8]={
+ arabic="d",
category="lo",
description="ARABIC LETTER QAF WITH THREE DOTS ABOVE",
direction="al",
@@ -16167,6 +16338,7 @@ characters.data={
unicodeslot=0x06A8,
},
[0x06A9]={
+ arabic="d",
category="lo",
description="ARABIC LETTER KEHEH",
direction="al",
@@ -16174,6 +16346,7 @@ characters.data={
unicodeslot=0x06A9,
},
[0x06AA]={
+ arabic="d",
category="lo",
description="ARABIC LETTER SWASH KAF",
direction="al",
@@ -16181,6 +16354,7 @@ characters.data={
unicodeslot=0x06AA,
},
[0x06AB]={
+ arabic="d",
category="lo",
description="ARABIC LETTER KAF WITH RING",
direction="al",
@@ -16189,6 +16363,7 @@ characters.data={
unicodeslot=0x06AB,
},
[0x06AC]={
+ arabic="d",
category="lo",
description="ARABIC LETTER KAF WITH DOT ABOVE",
direction="al",
@@ -16197,6 +16372,7 @@ characters.data={
unicodeslot=0x06AC,
},
[0x06AD]={
+ arabic="d",
category="lo",
description="ARABIC LETTER NG",
direction="al",
@@ -16204,6 +16380,7 @@ characters.data={
unicodeslot=0x06AD,
},
[0x06AE]={
+ arabic="d",
category="lo",
description="ARABIC LETTER KAF WITH THREE DOTS BELOW",
direction="al",
@@ -16213,6 +16390,7 @@ characters.data={
},
[0x06AF]={
adobename="gafarabic",
+ arabic="d",
category="lo",
description="ARABIC LETTER GAF",
direction="al",
@@ -16220,6 +16398,7 @@ characters.data={
unicodeslot=0x06AF,
},
[0x06B0]={
+ arabic="d",
category="lo",
description="ARABIC LETTER GAF WITH RING",
direction="al",
@@ -16228,6 +16407,7 @@ characters.data={
unicodeslot=0x06B0,
},
[0x06B1]={
+ arabic="d",
category="lo",
description="ARABIC LETTER NGOEH",
direction="al",
@@ -16235,6 +16415,7 @@ characters.data={
unicodeslot=0x06B1,
},
[0x06B2]={
+ arabic="d",
category="lo",
description="ARABIC LETTER GAF WITH TWO DOTS BELOW",
direction="al",
@@ -16243,6 +16424,7 @@ characters.data={
unicodeslot=0x06B2,
},
[0x06B3]={
+ arabic="d",
category="lo",
description="ARABIC LETTER GUEH",
direction="al",
@@ -16250,6 +16432,7 @@ characters.data={
unicodeslot=0x06B3,
},
[0x06B4]={
+ arabic="d",
category="lo",
description="ARABIC LETTER GAF WITH THREE DOTS ABOVE",
direction="al",
@@ -16258,6 +16441,7 @@ characters.data={
unicodeslot=0x06B4,
},
[0x06B5]={
+ arabic="d",
category="lo",
description="ARABIC LETTER LAM WITH SMALL V",
direction="al",
@@ -16266,6 +16450,7 @@ characters.data={
unicodeslot=0x06B5,
},
[0x06B6]={
+ arabic="d",
category="lo",
description="ARABIC LETTER LAM WITH DOT ABOVE",
direction="al",
@@ -16274,6 +16459,7 @@ characters.data={
unicodeslot=0x06B6,
},
[0x06B7]={
+ arabic="d",
category="lo",
description="ARABIC LETTER LAM WITH THREE DOTS ABOVE",
direction="al",
@@ -16282,6 +16468,7 @@ characters.data={
unicodeslot=0x06B7,
},
[0x06B8]={
+ arabic="d",
category="lo",
description="ARABIC LETTER LAM WITH THREE DOTS BELOW",
direction="al",
@@ -16290,6 +16477,7 @@ characters.data={
unicodeslot=0x06B8,
},
[0x06B9]={
+ arabic="d",
category="lo",
description="ARABIC LETTER NOON WITH DOT BELOW",
direction="al",
@@ -16299,6 +16487,7 @@ characters.data={
},
[0x06BA]={
adobename="noonghunnaarabic",
+ arabic="d",
category="lo",
description="ARABIC LETTER NOON GHUNNA",
direction="al",
@@ -16306,6 +16495,7 @@ characters.data={
unicodeslot=0x06BA,
},
[0x06BB]={
+ arabic="d",
category="lo",
description="ARABIC LETTER RNOON",
direction="al",
@@ -16313,6 +16503,7 @@ characters.data={
unicodeslot=0x06BB,
},
[0x06BC]={
+ arabic="d",
category="lo",
description="ARABIC LETTER NOON WITH RING",
direction="al",
@@ -16321,6 +16512,7 @@ characters.data={
unicodeslot=0x06BC,
},
[0x06BD]={
+ arabic="d",
category="lo",
description="ARABIC LETTER NOON WITH THREE DOTS ABOVE",
direction="al",
@@ -16329,6 +16521,7 @@ characters.data={
unicodeslot=0x06BD,
},
[0x06BE]={
+ arabic="d",
category="lo",
description="ARABIC LETTER HEH DOACHASHMEE",
direction="al",
@@ -16336,6 +16529,7 @@ characters.data={
unicodeslot=0x06BE,
},
[0x06BF]={
+ arabic="d",
category="lo",
description="ARABIC LETTER TCHEH WITH DOT ABOVE",
direction="al",
@@ -16344,6 +16538,7 @@ characters.data={
unicodeslot=0x06BF,
},
[0x06C0]={
+ arabic="r",
category="lo",
description="ARABIC LETTER HEH WITH YEH ABOVE",
direction="al",
@@ -16354,6 +16549,7 @@ characters.data={
},
[0x06C1]={
adobename="hehaltonearabic",
+ arabic="d",
category="lo",
description="ARABIC LETTER HEH GOAL",
direction="al",
@@ -16361,6 +16557,7 @@ characters.data={
unicodeslot=0x06C1,
},
[0x06C2]={
+ arabic="d",
category="lo",
description="ARABIC LETTER HEH GOAL WITH HAMZA ABOVE",
direction="al",
@@ -16369,6 +16566,7 @@ characters.data={
unicodeslot=0x06C2,
},
[0x06C3]={
+ arabic="r",
category="lo",
description="ARABIC LETTER TEH MARBUTA GOAL",
direction="al",
@@ -16376,6 +16574,7 @@ characters.data={
unicodeslot=0x06C3,
},
[0x06C4]={
+ arabic="r",
category="lo",
description="ARABIC LETTER WAW WITH RING",
direction="al",
@@ -16384,6 +16583,7 @@ characters.data={
unicodeslot=0x06C4,
},
[0x06C5]={
+ arabic="r",
category="lo",
description="ARABIC LETTER KIRGHIZ OE",
direction="al",
@@ -16391,6 +16591,7 @@ characters.data={
unicodeslot=0x06C5,
},
[0x06C6]={
+ arabic="r",
category="lo",
description="ARABIC LETTER OE",
direction="al",
@@ -16398,6 +16599,7 @@ characters.data={
unicodeslot=0x06C6,
},
[0x06C7]={
+ arabic="r",
category="lo",
description="ARABIC LETTER U",
direction="al",
@@ -16405,6 +16607,7 @@ characters.data={
unicodeslot=0x06C7,
},
[0x06C8]={
+ arabic="r",
category="lo",
description="ARABIC LETTER YU",
direction="al",
@@ -16412,6 +16615,7 @@ characters.data={
unicodeslot=0x06C8,
},
[0x06C9]={
+ arabic="r",
category="lo",
description="ARABIC LETTER KIRGHIZ YU",
direction="al",
@@ -16419,6 +16623,7 @@ characters.data={
unicodeslot=0x06C9,
},
[0x06CA]={
+ arabic="r",
category="lo",
description="ARABIC LETTER WAW WITH TWO DOTS ABOVE",
direction="al",
@@ -16427,6 +16632,7 @@ characters.data={
unicodeslot=0x06CA,
},
[0x06CB]={
+ arabic="r",
category="lo",
description="ARABIC LETTER VE",
direction="al",
@@ -16434,6 +16640,7 @@ characters.data={
unicodeslot=0x06CB,
},
[0x06CC]={
+ arabic="d",
category="lo",
description="ARABIC LETTER FARSI YEH",
direction="al",
@@ -16441,6 +16648,7 @@ characters.data={
unicodeslot=0x06CC,
},
[0x06CD]={
+ arabic="r",
category="lo",
description="ARABIC LETTER YEH WITH TAIL",
direction="al",
@@ -16449,6 +16657,7 @@ characters.data={
unicodeslot=0x06CD,
},
[0x06CE]={
+ arabic="d",
category="lo",
description="ARABIC LETTER YEH WITH SMALL V",
direction="al",
@@ -16457,6 +16666,7 @@ characters.data={
unicodeslot=0x06CE,
},
[0x06CF]={
+ arabic="r",
category="lo",
description="ARABIC LETTER WAW WITH DOT ABOVE",
direction="al",
@@ -16465,6 +16675,7 @@ characters.data={
unicodeslot=0x06CF,
},
[0x06D0]={
+ arabic="d",
category="lo",
description="ARABIC LETTER E",
direction="al",
@@ -16473,6 +16684,7 @@ characters.data={
},
[0x06D1]={
adobename="yehthreedotsbelowarabic",
+ arabic="d",
category="lo",
description="ARABIC LETTER YEH WITH THREE DOTS BELOW",
direction="al",
@@ -16482,6 +16694,7 @@ characters.data={
},
[0x06D2]={
adobename="yehbarreearabic",
+ arabic="r",
category="lo",
description="ARABIC LETTER YEH BARREE",
direction="al",
@@ -16489,6 +16702,7 @@ characters.data={
unicodeslot=0x06D2,
},
[0x06D3]={
+ arabic="r",
category="lo",
description="ARABIC LETTER YEH BARREE WITH HAMZA ABOVE",
direction="al",
@@ -16505,6 +16719,7 @@ characters.data={
},
[0x06D5]={
adobename="afii57534",
+ arabic="r",
category="lo",
description="ARABIC LETTER AE",
direction="al",
@@ -16561,6 +16776,7 @@ characters.data={
unicodeslot=0x06DC,
},
[0x06DD]={
+ arabic="u",
category="cf",
description="ARABIC END OF AYAH",
direction="an",
@@ -16681,6 +16897,7 @@ characters.data={
unicodeslot=0x06ED,
},
[0x06EE]={
+ arabic="r",
category="lo",
description="ARABIC LETTER DAL WITH INVERTED V",
direction="al",
@@ -16689,6 +16906,7 @@ characters.data={
unicodeslot=0x06EE,
},
[0x06EF]={
+ arabic="r",
category="lo",
description="ARABIC LETTER REH WITH INVERTED V",
direction="al",
@@ -16777,6 +16995,7 @@ characters.data={
unicodeslot=0x06F9,
},
[0x06FA]={
+ arabic="d",
category="lo",
description="ARABIC LETTER SHEEN WITH DOT BELOW",
direction="al",
@@ -16785,6 +17004,7 @@ characters.data={
unicodeslot=0x06FA,
},
[0x06FB]={
+ arabic="d",
category="lo",
description="ARABIC LETTER DAD WITH DOT BELOW",
direction="al",
@@ -16793,6 +17013,7 @@ characters.data={
unicodeslot=0x06FB,
},
[0x06FC]={
+ arabic="d",
category="lo",
description="ARABIC LETTER GHAIN WITH DOT BELOW",
direction="al",
@@ -16815,6 +17036,7 @@ characters.data={
unicodeslot=0x06FE,
},
[0x06FF]={
+ arabic="d",
category="lo",
description="ARABIC LETTER HEH WITH INVERTED V",
direction="al",
@@ -16923,12 +17145,13 @@ characters.data={
[0x070F]={
category="cf",
description="SYRIAC ABBREVIATION MARK",
- direction="an",
+ direction="al",
linebreak="al",
unicodeslot=0x070F,
visible="yes",
},
[0x0710]={
+ arabic="r",
category="lo",
description="SYRIAC LETTER ALAPH",
direction="al",
@@ -16943,6 +17166,7 @@ characters.data={
unicodeslot=0x0711,
},
[0x0712]={
+ arabic="d",
category="lo",
description="SYRIAC LETTER BETH",
direction="al",
@@ -16950,6 +17174,7 @@ characters.data={
unicodeslot=0x0712,
},
[0x0713]={
+ arabic="d",
category="lo",
description="SYRIAC LETTER GAMAL",
direction="al",
@@ -16957,6 +17182,7 @@ characters.data={
unicodeslot=0x0713,
},
[0x0714]={
+ arabic="d",
category="lo",
description="SYRIAC LETTER GAMAL GARSHUNI",
direction="al",
@@ -16964,6 +17190,7 @@ characters.data={
unicodeslot=0x0714,
},
[0x0715]={
+ arabic="r",
category="lo",
description="SYRIAC LETTER DALATH",
direction="al",
@@ -16971,6 +17198,7 @@ characters.data={
unicodeslot=0x0715,
},
[0x0716]={
+ arabic="r",
category="lo",
description="SYRIAC LETTER DOTLESS DALATH RISH",
direction="al",
@@ -16978,6 +17206,7 @@ characters.data={
unicodeslot=0x0716,
},
[0x0717]={
+ arabic="r",
category="lo",
description="SYRIAC LETTER HE",
direction="al",
@@ -16985,6 +17214,7 @@ characters.data={
unicodeslot=0x0717,
},
[0x0718]={
+ arabic="r",
category="lo",
description="SYRIAC LETTER WAW",
direction="al",
@@ -16992,6 +17222,7 @@ characters.data={
unicodeslot=0x0718,
},
[0x0719]={
+ arabic="r",
category="lo",
description="SYRIAC LETTER ZAIN",
direction="al",
@@ -16999,6 +17230,7 @@ characters.data={
unicodeslot=0x0719,
},
[0x071A]={
+ arabic="d",
category="lo",
description="SYRIAC LETTER HETH",
direction="al",
@@ -17006,6 +17238,7 @@ characters.data={
unicodeslot=0x071A,
},
[0x071B]={
+ arabic="d",
category="lo",
description="SYRIAC LETTER TETH",
direction="al",
@@ -17013,6 +17246,7 @@ characters.data={
unicodeslot=0x071B,
},
[0x071C]={
+ arabic="d",
category="lo",
description="SYRIAC LETTER TETH GARSHUNI",
direction="al",
@@ -17020,6 +17254,7 @@ characters.data={
unicodeslot=0x071C,
},
[0x071D]={
+ arabic="d",
category="lo",
description="SYRIAC LETTER YUDH",
direction="al",
@@ -17027,6 +17262,7 @@ characters.data={
unicodeslot=0x071D,
},
[0x071E]={
+ arabic="r",
category="lo",
description="SYRIAC LETTER YUDH HE",
direction="al",
@@ -17034,6 +17270,7 @@ characters.data={
unicodeslot=0x071E,
},
[0x071F]={
+ arabic="d",
category="lo",
description="SYRIAC LETTER KAPH",
direction="al",
@@ -17041,6 +17278,7 @@ characters.data={
unicodeslot=0x071F,
},
[0x0720]={
+ arabic="d",
category="lo",
description="SYRIAC LETTER LAMADH",
direction="al",
@@ -17048,6 +17286,7 @@ characters.data={
unicodeslot=0x0720,
},
[0x0721]={
+ arabic="d",
category="lo",
description="SYRIAC LETTER MIM",
direction="al",
@@ -17055,6 +17294,7 @@ characters.data={
unicodeslot=0x0721,
},
[0x0722]={
+ arabic="d",
category="lo",
description="SYRIAC LETTER NUN",
direction="al",
@@ -17062,6 +17302,7 @@ characters.data={
unicodeslot=0x0722,
},
[0x0723]={
+ arabic="d",
category="lo",
description="SYRIAC LETTER SEMKATH",
direction="al",
@@ -17069,6 +17310,7 @@ characters.data={
unicodeslot=0x0723,
},
[0x0724]={
+ arabic="d",
category="lo",
description="SYRIAC LETTER FINAL SEMKATH",
direction="al",
@@ -17076,6 +17318,7 @@ characters.data={
unicodeslot=0x0724,
},
[0x0725]={
+ arabic="d",
category="lo",
description="SYRIAC LETTER E",
direction="al",
@@ -17083,6 +17326,7 @@ characters.data={
unicodeslot=0x0725,
},
[0x0726]={
+ arabic="d",
category="lo",
description="SYRIAC LETTER PE",
direction="al",
@@ -17090,6 +17334,7 @@ characters.data={
unicodeslot=0x0726,
},
[0x0727]={
+ arabic="d",
category="lo",
description="SYRIAC LETTER REVERSED PE",
direction="al",
@@ -17097,6 +17342,7 @@ characters.data={
unicodeslot=0x0727,
},
[0x0728]={
+ arabic="r",
category="lo",
description="SYRIAC LETTER SADHE",
direction="al",
@@ -17104,6 +17350,7 @@ characters.data={
unicodeslot=0x0728,
},
[0x0729]={
+ arabic="d",
category="lo",
description="SYRIAC LETTER QAPH",
direction="al",
@@ -17111,6 +17358,7 @@ characters.data={
unicodeslot=0x0729,
},
[0x072A]={
+ arabic="r",
category="lo",
description="SYRIAC LETTER RISH",
direction="al",
@@ -17118,6 +17366,7 @@ characters.data={
unicodeslot=0x072A,
},
[0x072B]={
+ arabic="d",
category="lo",
description="SYRIAC LETTER SHIN",
direction="al",
@@ -17125,6 +17374,7 @@ characters.data={
unicodeslot=0x072B,
},
[0x072C]={
+ arabic="r",
category="lo",
description="SYRIAC LETTER TAW",
direction="al",
@@ -17132,6 +17382,7 @@ characters.data={
unicodeslot=0x072C,
},
[0x072D]={
+ arabic="d",
category="lo",
description="SYRIAC LETTER PERSIAN BHETH",
direction="al",
@@ -17139,6 +17390,7 @@ characters.data={
unicodeslot=0x072D,
},
[0x072E]={
+ arabic="d",
category="lo",
description="SYRIAC LETTER PERSIAN GHAMAL",
direction="al",
@@ -17146,6 +17398,7 @@ characters.data={
unicodeslot=0x072E,
},
[0x072F]={
+ arabic="r",
category="lo",
description="SYRIAC LETTER PERSIAN DHALATH",
direction="al",
@@ -17342,6 +17595,7 @@ characters.data={
unicodeslot=0x074A,
},
[0x074D]={
+ arabic="r",
category="lo",
description="SYRIAC LETTER SOGDIAN ZHAIN",
direction="al",
@@ -17349,6 +17603,7 @@ characters.data={
unicodeslot=0x074D,
},
[0x074E]={
+ arabic="d",
category="lo",
description="SYRIAC LETTER SOGDIAN KHAPH",
direction="al",
@@ -17356,6 +17611,7 @@ characters.data={
unicodeslot=0x074E,
},
[0x074F]={
+ arabic="d",
category="lo",
description="SYRIAC LETTER SOGDIAN FE",
direction="al",
@@ -17363,6 +17619,7 @@ characters.data={
unicodeslot=0x074F,
},
[0x0750]={
+ arabic="d",
category="lo",
description="ARABIC LETTER BEH WITH THREE DOTS HORIZONTALLY BELOW",
direction="al",
@@ -17371,6 +17628,7 @@ characters.data={
unicodeslot=0x0750,
},
[0x0751]={
+ arabic="d",
category="lo",
description="ARABIC LETTER BEH WITH DOT BELOW AND THREE DOTS ABOVE",
direction="al",
@@ -17379,6 +17637,7 @@ characters.data={
unicodeslot=0x0751,
},
[0x0752]={
+ arabic="d",
category="lo",
description="ARABIC LETTER BEH WITH THREE DOTS POINTING UPWARDS BELOW",
direction="al",
@@ -17387,6 +17646,7 @@ characters.data={
unicodeslot=0x0752,
},
[0x0753]={
+ arabic="d",
category="lo",
description="ARABIC LETTER BEH WITH THREE DOTS POINTING UPWARDS BELOW AND TWO DOTS ABOVE",
direction="al",
@@ -17395,6 +17655,7 @@ characters.data={
unicodeslot=0x0753,
},
[0x0754]={
+ arabic="d",
category="lo",
description="ARABIC LETTER BEH WITH TWO DOTS BELOW AND DOT ABOVE",
direction="al",
@@ -17403,6 +17664,7 @@ characters.data={
unicodeslot=0x0754,
},
[0x0755]={
+ arabic="d",
category="lo",
description="ARABIC LETTER BEH WITH INVERTED SMALL V BELOW",
direction="al",
@@ -17411,6 +17673,7 @@ characters.data={
unicodeslot=0x0755,
},
[0x0756]={
+ arabic="d",
category="lo",
description="ARABIC LETTER BEH WITH SMALL V",
direction="al",
@@ -17419,6 +17682,7 @@ characters.data={
unicodeslot=0x0756,
},
[0x0757]={
+ arabic="d",
category="lo",
description="ARABIC LETTER HAH WITH TWO DOTS ABOVE",
direction="al",
@@ -17427,6 +17691,7 @@ characters.data={
unicodeslot=0x0757,
},
[0x0758]={
+ arabic="d",
category="lo",
description="ARABIC LETTER HAH WITH THREE DOTS POINTING UPWARDS BELOW",
direction="al",
@@ -17435,6 +17700,7 @@ characters.data={
unicodeslot=0x0758,
},
[0x0759]={
+ arabic="r",
category="lo",
description="ARABIC LETTER DAL WITH TWO DOTS VERTICALLY BELOW AND SMALL TAH",
direction="al",
@@ -17443,6 +17709,7 @@ characters.data={
unicodeslot=0x0759,
},
[0x075A]={
+ arabic="r",
category="lo",
description="ARABIC LETTER DAL WITH INVERTED SMALL V BELOW",
direction="al",
@@ -17451,6 +17718,7 @@ characters.data={
unicodeslot=0x075A,
},
[0x075B]={
+ arabic="r",
category="lo",
description="ARABIC LETTER REH WITH STROKE",
direction="al",
@@ -17459,6 +17727,7 @@ characters.data={
unicodeslot=0x075B,
},
[0x075C]={
+ arabic="d",
category="lo",
description="ARABIC LETTER SEEN WITH FOUR DOTS ABOVE",
direction="al",
@@ -17467,6 +17736,7 @@ characters.data={
unicodeslot=0x075C,
},
[0x075D]={
+ arabic="d",
category="lo",
description="ARABIC LETTER AIN WITH TWO DOTS ABOVE",
direction="al",
@@ -17475,6 +17745,7 @@ characters.data={
unicodeslot=0x075D,
},
[0x075E]={
+ arabic="d",
category="lo",
description="ARABIC LETTER AIN WITH THREE DOTS POINTING DOWNWARDS ABOVE",
direction="al",
@@ -17483,6 +17754,7 @@ characters.data={
unicodeslot=0x075E,
},
[0x075F]={
+ arabic="d",
category="lo",
description="ARABIC LETTER AIN WITH TWO DOTS VERTICALLY ABOVE",
direction="al",
@@ -17491,6 +17763,7 @@ characters.data={
unicodeslot=0x075F,
},
[0x0760]={
+ arabic="d",
category="lo",
description="ARABIC LETTER FEH WITH TWO DOTS BELOW",
direction="al",
@@ -17499,6 +17772,7 @@ characters.data={
unicodeslot=0x0760,
},
[0x0761]={
+ arabic="d",
category="lo",
description="ARABIC LETTER FEH WITH THREE DOTS POINTING UPWARDS BELOW",
direction="al",
@@ -17507,6 +17781,7 @@ characters.data={
unicodeslot=0x0761,
},
[0x0762]={
+ arabic="d",
category="lo",
description="ARABIC LETTER KEHEH WITH DOT ABOVE",
direction="al",
@@ -17515,6 +17790,7 @@ characters.data={
unicodeslot=0x0762,
},
[0x0763]={
+ arabic="d",
category="lo",
description="ARABIC LETTER KEHEH WITH THREE DOTS ABOVE",
direction="al",
@@ -17523,6 +17799,7 @@ characters.data={
unicodeslot=0x0763,
},
[0x0764]={
+ arabic="d",
category="lo",
description="ARABIC LETTER KEHEH WITH THREE DOTS POINTING UPWARDS BELOW",
direction="al",
@@ -17531,6 +17808,7 @@ characters.data={
unicodeslot=0x0764,
},
[0x0765]={
+ arabic="d",
category="lo",
description="ARABIC LETTER MEEM WITH DOT ABOVE",
direction="al",
@@ -17539,6 +17817,7 @@ characters.data={
unicodeslot=0x0765,
},
[0x0766]={
+ arabic="d",
category="lo",
description="ARABIC LETTER MEEM WITH DOT BELOW",
direction="al",
@@ -17547,6 +17826,7 @@ characters.data={
unicodeslot=0x0766,
},
[0x0767]={
+ arabic="d",
category="lo",
description="ARABIC LETTER NOON WITH TWO DOTS BELOW",
direction="al",
@@ -17555,6 +17835,7 @@ characters.data={
unicodeslot=0x0767,
},
[0x0768]={
+ arabic="d",
category="lo",
description="ARABIC LETTER NOON WITH SMALL TAH",
direction="al",
@@ -17563,6 +17844,7 @@ characters.data={
unicodeslot=0x0768,
},
[0x0769]={
+ arabic="d",
category="lo",
description="ARABIC LETTER NOON WITH SMALL V",
direction="al",
@@ -17571,6 +17853,7 @@ characters.data={
unicodeslot=0x0769,
},
[0x076A]={
+ arabic="d",
category="lo",
description="ARABIC LETTER LAM WITH BAR",
direction="al",
@@ -17579,6 +17862,7 @@ characters.data={
unicodeslot=0x076A,
},
[0x076B]={
+ arabic="r",
category="lo",
description="ARABIC LETTER REH WITH TWO DOTS VERTICALLY ABOVE",
direction="al",
@@ -17587,6 +17871,7 @@ characters.data={
unicodeslot=0x076B,
},
[0x076C]={
+ arabic="r",
category="lo",
description="ARABIC LETTER REH WITH HAMZA ABOVE",
direction="al",
@@ -17595,6 +17880,7 @@ characters.data={
unicodeslot=0x076C,
},
[0x076D]={
+ arabic="d",
category="lo",
description="ARABIC LETTER SEEN WITH TWO DOTS VERTICALLY ABOVE",
direction="al",
@@ -17603,6 +17889,7 @@ characters.data={
unicodeslot=0x076D,
},
[0x076E]={
+ arabic="d",
category="lo",
description="ARABIC LETTER HAH WITH SMALL ARABIC LETTER TAH BELOW",
direction="al",
@@ -17610,6 +17897,7 @@ characters.data={
unicodeslot=0x076E,
},
[0x076F]={
+ arabic="d",
category="lo",
description="ARABIC LETTER HAH WITH SMALL ARABIC LETTER TAH AND TWO DOTS",
direction="al",
@@ -17617,6 +17905,7 @@ characters.data={
unicodeslot=0x076F,
},
[0x0770]={
+ arabic="d",
category="lo",
description="ARABIC LETTER SEEN WITH SMALL ARABIC LETTER TAH AND TWO DOTS",
direction="al",
@@ -17624,6 +17913,7 @@ characters.data={
unicodeslot=0x0770,
},
[0x0771]={
+ arabic="r",
category="lo",
description="ARABIC LETTER REH WITH SMALL ARABIC LETTER TAH AND TWO DOTS",
direction="al",
@@ -17631,6 +17921,7 @@ characters.data={
unicodeslot=0x0771,
},
[0x0772]={
+ arabic="d",
category="lo",
description="ARABIC LETTER HAH WITH SMALL ARABIC LETTER TAH ABOVE",
direction="al",
@@ -17638,6 +17929,7 @@ characters.data={
unicodeslot=0x0772,
},
[0x0773]={
+ arabic="r",
category="lo",
description="ARABIC LETTER ALEF WITH EXTENDED ARABIC-INDIC DIGIT TWO ABOVE",
direction="al",
@@ -17645,6 +17937,7 @@ characters.data={
unicodeslot=0x0773,
},
[0x0774]={
+ arabic="r",
category="lo",
description="ARABIC LETTER ALEF WITH EXTENDED ARABIC-INDIC DIGIT THREE ABOVE",
direction="al",
@@ -17652,6 +17945,7 @@ characters.data={
unicodeslot=0x0774,
},
[0x0775]={
+ arabic="d",
category="lo",
description="ARABIC LETTER FARSI YEH WITH EXTENDED ARABIC-INDIC DIGIT TWO ABOVE",
direction="al",
@@ -17659,6 +17953,7 @@ characters.data={
unicodeslot=0x0775,
},
[0x0776]={
+ arabic="d",
category="lo",
description="ARABIC LETTER FARSI YEH WITH EXTENDED ARABIC-INDIC DIGIT THREE ABOVE",
direction="al",
@@ -17666,6 +17961,7 @@ characters.data={
unicodeslot=0x0776,
},
[0x0777]={
+ arabic="d",
category="lo",
description="ARABIC LETTER FARSI YEH WITH EXTENDED ARABIC-INDIC DIGIT FOUR BELOW",
direction="al",
@@ -17673,6 +17969,7 @@ characters.data={
unicodeslot=0x0777,
},
[0x0778]={
+ arabic="r",
category="lo",
description="ARABIC LETTER WAW WITH EXTENDED ARABIC-INDIC DIGIT TWO ABOVE",
direction="al",
@@ -17680,6 +17977,7 @@ characters.data={
unicodeslot=0x0778,
},
[0x0779]={
+ arabic="r",
category="lo",
description="ARABIC LETTER WAW WITH EXTENDED ARABIC-INDIC DIGIT THREE ABOVE",
direction="al",
@@ -17687,6 +17985,7 @@ characters.data={
unicodeslot=0x0779,
},
[0x077A]={
+ arabic="d",
category="lo",
description="ARABIC LETTER YEH BARREE WITH EXTENDED ARABIC-INDIC DIGIT TWO ABOVE",
direction="al",
@@ -17694,6 +17993,7 @@ characters.data={
unicodeslot=0x077A,
},
[0x077B]={
+ arabic="d",
category="lo",
description="ARABIC LETTER YEH BARREE WITH EXTENDED ARABIC-INDIC DIGIT THREE ABOVE",
direction="al",
@@ -17701,6 +18001,7 @@ characters.data={
unicodeslot=0x077B,
},
[0x077C]={
+ arabic="d",
category="lo",
description="ARABIC LETTER HAH WITH EXTENDED ARABIC-INDIC DIGIT FOUR BELOW",
direction="al",
@@ -17708,6 +18009,7 @@ characters.data={
unicodeslot=0x077C,
},
[0x077D]={
+ arabic="d",
category="lo",
description="ARABIC LETTER SEEN WITH EXTENDED ARABIC-INDIC DIGIT FOUR ABOVE",
direction="al",
@@ -17715,6 +18017,7 @@ characters.data={
unicodeslot=0x077D,
},
[0x077E]={
+ arabic="d",
category="lo",
description="ARABIC LETTER SEEN WITH INVERTED V",
direction="al",
@@ -17722,6 +18025,7 @@ characters.data={
unicodeslot=0x077E,
},
[0x077F]={
+ arabic="d",
category="lo",
description="ARABIC LETTER KAF WITH TWO DOTS ABOVE",
direction="al",
@@ -18149,6 +18453,7 @@ characters.data={
unicodeslot=0x07C9,
},
[0x07CA]={
+ arabic="d",
category="lo",
description="NKO LETTER A",
direction="r",
@@ -18156,6 +18461,7 @@ characters.data={
unicodeslot=0x07CA,
},
[0x07CB]={
+ arabic="d",
category="lo",
description="NKO LETTER EE",
direction="r",
@@ -18163,6 +18469,7 @@ characters.data={
unicodeslot=0x07CB,
},
[0x07CC]={
+ arabic="d",
category="lo",
description="NKO LETTER I",
direction="r",
@@ -18170,6 +18477,7 @@ characters.data={
unicodeslot=0x07CC,
},
[0x07CD]={
+ arabic="d",
category="lo",
description="NKO LETTER E",
direction="r",
@@ -18177,6 +18485,7 @@ characters.data={
unicodeslot=0x07CD,
},
[0x07CE]={
+ arabic="d",
category="lo",
description="NKO LETTER U",
direction="r",
@@ -18184,6 +18493,7 @@ characters.data={
unicodeslot=0x07CE,
},
[0x07CF]={
+ arabic="d",
category="lo",
description="NKO LETTER OO",
direction="r",
@@ -18191,6 +18501,7 @@ characters.data={
unicodeslot=0x07CF,
},
[0x07D0]={
+ arabic="d",
category="lo",
description="NKO LETTER O",
direction="r",
@@ -18198,6 +18509,7 @@ characters.data={
unicodeslot=0x07D0,
},
[0x07D1]={
+ arabic="d",
category="lo",
description="NKO LETTER DAGBASINNA",
direction="r",
@@ -18205,6 +18517,7 @@ characters.data={
unicodeslot=0x07D1,
},
[0x07D2]={
+ arabic="d",
category="lo",
description="NKO LETTER N",
direction="r",
@@ -18212,6 +18525,7 @@ characters.data={
unicodeslot=0x07D2,
},
[0x07D3]={
+ arabic="d",
category="lo",
description="NKO LETTER BA",
direction="r",
@@ -18219,6 +18533,7 @@ characters.data={
unicodeslot=0x07D3,
},
[0x07D4]={
+ arabic="d",
category="lo",
description="NKO LETTER PA",
direction="r",
@@ -18226,6 +18541,7 @@ characters.data={
unicodeslot=0x07D4,
},
[0x07D5]={
+ arabic="d",
category="lo",
description="NKO LETTER TA",
direction="r",
@@ -18233,6 +18549,7 @@ characters.data={
unicodeslot=0x07D5,
},
[0x07D6]={
+ arabic="d",
category="lo",
description="NKO LETTER JA",
direction="r",
@@ -18240,6 +18557,7 @@ characters.data={
unicodeslot=0x07D6,
},
[0x07D7]={
+ arabic="d",
category="lo",
description="NKO LETTER CHA",
direction="r",
@@ -18247,6 +18565,7 @@ characters.data={
unicodeslot=0x07D7,
},
[0x07D8]={
+ arabic="d",
category="lo",
description="NKO LETTER DA",
direction="r",
@@ -18254,6 +18573,7 @@ characters.data={
unicodeslot=0x07D8,
},
[0x07D9]={
+ arabic="d",
category="lo",
description="NKO LETTER RA",
direction="r",
@@ -18261,6 +18581,7 @@ characters.data={
unicodeslot=0x07D9,
},
[0x07DA]={
+ arabic="d",
category="lo",
description="NKO LETTER RRA",
direction="r",
@@ -18268,6 +18589,7 @@ characters.data={
unicodeslot=0x07DA,
},
[0x07DB]={
+ arabic="d",
category="lo",
description="NKO LETTER SA",
direction="r",
@@ -18275,6 +18597,7 @@ characters.data={
unicodeslot=0x07DB,
},
[0x07DC]={
+ arabic="d",
category="lo",
description="NKO LETTER GBA",
direction="r",
@@ -18282,6 +18605,7 @@ characters.data={
unicodeslot=0x07DC,
},
[0x07DD]={
+ arabic="d",
category="lo",
description="NKO LETTER FA",
direction="r",
@@ -18289,6 +18613,7 @@ characters.data={
unicodeslot=0x07DD,
},
[0x07DE]={
+ arabic="d",
category="lo",
description="NKO LETTER KA",
direction="r",
@@ -18296,6 +18621,7 @@ characters.data={
unicodeslot=0x07DE,
},
[0x07DF]={
+ arabic="d",
category="lo",
description="NKO LETTER LA",
direction="r",
@@ -18303,6 +18629,7 @@ characters.data={
unicodeslot=0x07DF,
},
[0x07E0]={
+ arabic="d",
category="lo",
description="NKO LETTER NA WOLOSO",
direction="r",
@@ -18310,6 +18637,7 @@ characters.data={
unicodeslot=0x07E0,
},
[0x07E1]={
+ arabic="d",
category="lo",
description="NKO LETTER MA",
direction="r",
@@ -18317,6 +18645,7 @@ characters.data={
unicodeslot=0x07E1,
},
[0x07E2]={
+ arabic="d",
category="lo",
description="NKO LETTER NYA",
direction="r",
@@ -18324,6 +18653,7 @@ characters.data={
unicodeslot=0x07E2,
},
[0x07E3]={
+ arabic="d",
category="lo",
description="NKO LETTER NA",
direction="r",
@@ -18331,6 +18661,7 @@ characters.data={
unicodeslot=0x07E3,
},
[0x07E4]={
+ arabic="d",
category="lo",
description="NKO LETTER HA",
direction="r",
@@ -18338,6 +18669,7 @@ characters.data={
unicodeslot=0x07E4,
},
[0x07E5]={
+ arabic="d",
category="lo",
description="NKO LETTER WA",
direction="r",
@@ -18345,6 +18677,7 @@ characters.data={
unicodeslot=0x07E5,
},
[0x07E6]={
+ arabic="d",
category="lo",
description="NKO LETTER YA",
direction="r",
@@ -18352,6 +18685,7 @@ characters.data={
unicodeslot=0x07E6,
},
[0x07E7]={
+ arabic="d",
category="lo",
description="NKO LETTER NYA WOLOSO",
direction="r",
@@ -18359,6 +18693,7 @@ characters.data={
unicodeslot=0x07E7,
},
[0x07E8]={
+ arabic="d",
category="lo",
description="NKO LETTER JONA JA",
direction="r",
@@ -18366,6 +18701,7 @@ characters.data={
unicodeslot=0x07E8,
},
[0x07E9]={
+ arabic="d",
category="lo",
description="NKO LETTER JONA CHA",
direction="r",
@@ -18373,6 +18709,7 @@ characters.data={
unicodeslot=0x07E9,
},
[0x07EA]={
+ arabic="d",
category="lo",
description="NKO LETTER JONA RA",
direction="r",
@@ -18485,6 +18822,7 @@ characters.data={
unicodeslot=0x07F9,
},
[0x07FA]={
+ arabic="c",
category="lm",
description="NKO LAJANYALAN",
direction="r",
@@ -18919,6 +19257,7 @@ characters.data={
unicodeslot=0x083E,
},
[0x0840]={
+ arabic="r",
category="lo",
description="MANDAIC LETTER HALQA",
direction="r",
@@ -18926,6 +19265,7 @@ characters.data={
unicodeslot=0x0840,
},
[0x0841]={
+ arabic="d",
category="lo",
description="MANDAIC LETTER AB",
direction="r",
@@ -18933,6 +19273,7 @@ characters.data={
unicodeslot=0x0841,
},
[0x0842]={
+ arabic="d",
category="lo",
description="MANDAIC LETTER AG",
direction="r",
@@ -18940,6 +19281,7 @@ characters.data={
unicodeslot=0x0842,
},
[0x0843]={
+ arabic="d",
category="lo",
description="MANDAIC LETTER AD",
direction="r",
@@ -18947,6 +19289,7 @@ characters.data={
unicodeslot=0x0843,
},
[0x0844]={
+ arabic="d",
category="lo",
description="MANDAIC LETTER AH",
direction="r",
@@ -18954,6 +19297,7 @@ characters.data={
unicodeslot=0x0844,
},
[0x0845]={
+ arabic="d",
category="lo",
description="MANDAIC LETTER USHENNA",
direction="r",
@@ -18961,6 +19305,7 @@ characters.data={
unicodeslot=0x0845,
},
[0x0846]={
+ arabic="r",
category="lo",
description="MANDAIC LETTER AZ",
direction="r",
@@ -18968,6 +19313,7 @@ characters.data={
unicodeslot=0x0846,
},
[0x0847]={
+ arabic="d",
category="lo",
description="MANDAIC LETTER IT",
direction="r",
@@ -18975,6 +19321,7 @@ characters.data={
unicodeslot=0x0847,
},
[0x0848]={
+ arabic="d",
category="lo",
description="MANDAIC LETTER ATT",
direction="r",
@@ -18982,6 +19329,7 @@ characters.data={
unicodeslot=0x0848,
},
[0x0849]={
+ arabic="r",
category="lo",
description="MANDAIC LETTER AKSA",
direction="r",
@@ -18989,6 +19337,7 @@ characters.data={
unicodeslot=0x0849,
},
[0x084A]={
+ arabic="d",
category="lo",
description="MANDAIC LETTER AK",
direction="r",
@@ -18996,6 +19345,7 @@ characters.data={
unicodeslot=0x084A,
},
[0x084B]={
+ arabic="d",
category="lo",
description="MANDAIC LETTER AL",
direction="r",
@@ -19003,6 +19353,7 @@ characters.data={
unicodeslot=0x084B,
},
[0x084C]={
+ arabic="d",
category="lo",
description="MANDAIC LETTER AM",
direction="r",
@@ -19010,6 +19361,7 @@ characters.data={
unicodeslot=0x084C,
},
[0x084D]={
+ arabic="d",
category="lo",
description="MANDAIC LETTER AN",
direction="r",
@@ -19017,6 +19369,7 @@ characters.data={
unicodeslot=0x084D,
},
[0x084E]={
+ arabic="d",
category="lo",
description="MANDAIC LETTER AS",
direction="r",
@@ -19024,6 +19377,7 @@ characters.data={
unicodeslot=0x084E,
},
[0x084F]={
+ arabic="r",
category="lo",
description="MANDAIC LETTER IN",
direction="r",
@@ -19031,6 +19385,7 @@ characters.data={
unicodeslot=0x084F,
},
[0x0850]={
+ arabic="d",
category="lo",
description="MANDAIC LETTER AP",
direction="r",
@@ -19038,6 +19393,7 @@ characters.data={
unicodeslot=0x0850,
},
[0x0851]={
+ arabic="d",
category="lo",
description="MANDAIC LETTER ASZ",
direction="r",
@@ -19045,6 +19401,7 @@ characters.data={
unicodeslot=0x0851,
},
[0x0852]={
+ arabic="d",
category="lo",
description="MANDAIC LETTER AQ",
direction="r",
@@ -19052,6 +19409,7 @@ characters.data={
unicodeslot=0x0852,
},
[0x0853]={
+ arabic="d",
category="lo",
description="MANDAIC LETTER AR",
direction="r",
@@ -19059,6 +19417,7 @@ characters.data={
unicodeslot=0x0853,
},
[0x0854]={
+ arabic="r",
category="lo",
description="MANDAIC LETTER ASH",
direction="r",
@@ -19066,6 +19425,7 @@ characters.data={
unicodeslot=0x0854,
},
[0x0855]={
+ arabic="d",
category="lo",
description="MANDAIC LETTER AT",
direction="r",
@@ -19073,6 +19433,7 @@ characters.data={
unicodeslot=0x0855,
},
[0x0856]={
+ arabic="u",
category="lo",
description="MANDAIC LETTER DUSHENNA",
direction="r",
@@ -19080,6 +19441,7 @@ characters.data={
unicodeslot=0x0856,
},
[0x0857]={
+ arabic="u",
category="lo",
description="MANDAIC LETTER KAD",
direction="r",
@@ -19087,6 +19449,7 @@ characters.data={
unicodeslot=0x0857,
},
[0x0858]={
+ arabic="u",
category="lo",
description="MANDAIC LETTER AIN",
direction="r",
@@ -19121,6 +19484,291 @@ characters.data={
linebreak="al",
unicodeslot=0x085E,
},
+ [0x08A0]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER BEH WITH SMALL V BELOW",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x08A0,
+ },
+ [0x08A2]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER JEEM WITH TWO DOTS ABOVE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x08A2,
+ },
+ [0x08A3]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER TAH WITH TWO DOTS ABOVE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x08A3,
+ },
+ [0x08A4]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER FEH WITH DOT BELOW AND THREE DOTS ABOVE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x08A4,
+ },
+ [0x08A5]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER QAF WITH DOT BELOW",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x08A5,
+ },
+ [0x08A6]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER LAM WITH DOUBLE BAR",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x08A6,
+ },
+ [0x08A7]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER MEEM WITH THREE DOTS ABOVE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x08A7,
+ },
+ [0x08A8]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER YEH WITH TWO DOTS BELOW AND HAMZA ABOVE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x08A8,
+ },
+ [0x08A9]={
+ arabic="d",
+ category="lo",
+ description="ARABIC LETTER YEH WITH TWO DOTS BELOW AND DOT ABOVE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x08A9,
+ },
+ [0x08AA]={
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER REH WITH LOOP",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x08AA,
+ },
+ [0x08AB]={
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER WAW WITH DOT WITHIN",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x08AB,
+ },
+ [0x08AC]={
+ arabic="r",
+ category="lo",
+ description="ARABIC LETTER ROHINGYA YEH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x08AC,
+ },
+ [0x08E4]={
+ category="mn",
+ description="ARABIC CURLY FATHA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x08E4,
+ },
+ [0x08E5]={
+ category="mn",
+ description="ARABIC CURLY DAMMA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x08E5,
+ },
+ [0x08E6]={
+ category="mn",
+ description="ARABIC CURLY KASRA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x08E6,
+ },
+ [0x08E7]={
+ category="mn",
+ description="ARABIC CURLY FATHATAN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x08E7,
+ },
+ [0x08E8]={
+ category="mn",
+ description="ARABIC CURLY DAMMATAN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x08E8,
+ },
+ [0x08E9]={
+ category="mn",
+ description="ARABIC CURLY KASRATAN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x08E9,
+ },
+ [0x08EA]={
+ category="mn",
+ description="ARABIC TONE ONE DOT ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x08EA,
+ },
+ [0x08EB]={
+ category="mn",
+ description="ARABIC TONE TWO DOTS ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x08EB,
+ },
+ [0x08EC]={
+ category="mn",
+ description="ARABIC TONE LOOP ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x08EC,
+ },
+ [0x08ED]={
+ category="mn",
+ description="ARABIC TONE ONE DOT BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x08ED,
+ },
+ [0x08EE]={
+ category="mn",
+ description="ARABIC TONE TWO DOTS BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x08EE,
+ },
+ [0x08EF]={
+ category="mn",
+ description="ARABIC TONE LOOP BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x08EF,
+ },
+ [0x08F0]={
+ category="mn",
+ description="ARABIC OPEN FATHATAN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x08F0,
+ },
+ [0x08F1]={
+ category="mn",
+ description="ARABIC OPEN DAMMATAN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x08F1,
+ },
+ [0x08F2]={
+ category="mn",
+ description="ARABIC OPEN KASRATAN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x08F2,
+ },
+ [0x08F3]={
+ category="mn",
+ description="ARABIC SMALL HIGH WAW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x08F3,
+ },
+ [0x08F4]={
+ category="mn",
+ description="ARABIC FATHA WITH RING",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x08F4,
+ },
+ [0x08F5]={
+ category="mn",
+ description="ARABIC FATHA WITH DOT ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x08F5,
+ },
+ [0x08F6]={
+ category="mn",
+ description="ARABIC KASRA WITH DOT BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x08F6,
+ },
+ [0x08F7]={
+ category="mn",
+ description="ARABIC LEFT ARROWHEAD ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x08F7,
+ },
+ [0x08F8]={
+ category="mn",
+ description="ARABIC RIGHT ARROWHEAD ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x08F8,
+ },
+ [0x08F9]={
+ category="mn",
+ description="ARABIC LEFT ARROWHEAD BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x08F9,
+ },
+ [0x08FA]={
+ category="mn",
+ description="ARABIC RIGHT ARROWHEAD BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x08FA,
+ },
+ [0x08FB]={
+ category="mn",
+ description="ARABIC DOUBLE RIGHT ARROWHEAD ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x08FB,
+ },
+ [0x08FC]={
+ category="mn",
+ description="ARABIC DOUBLE RIGHT ARROWHEAD ABOVE WITH DOT",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x08FC,
+ },
+ [0x08FD]={
+ category="mn",
+ description="ARABIC RIGHT ARROWHEAD ABOVE WITH DOT",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x08FD,
+ },
+ [0x08FE]={
+ category="mn",
+ description="ARABIC DAMMA WITH DOT",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x08FE,
+ },
[0x0900]={
category="mn",
description="DEVANAGARI SIGN INVERTED CANDRABINDU",
@@ -22149,6 +22797,13 @@ characters.data={
linebreak="nu",
unicodeslot=0x0AEF,
},
+ [0x0AF0]={
+ category="po",
+ description="GUJARATI ABBREVIATION SIGN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0AF0,
+ },
[0x0AF1]={
category="sc",
description="GUJARATI RUPEE SIGN",
@@ -26966,6 +27621,20 @@ characters.data={
specials={ "compat", 0x0EAB, 0x0EA1 },
unicodeslot=0x0EDD,
},
+ [0x0EDE]={
+ category="lo",
+ description="LAO LETTER KHMU GO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x0EDE,
+ },
+ [0x0EDF]={
+ category="lo",
+ description="LAO LETTER KHMU NYO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x0EDF,
+ },
[0x0F00]={
category="lo",
description="TIBETAN SYLLABLE OM",
@@ -29892,6 +30561,20 @@ characters.data={
linebreak="al",
unicodeslot=0x10C5,
},
+ [0x10C7]={
+ category="lu",
+ description="GEORGIAN CAPITAL LETTER YN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10C7,
+ },
+ [0x10CD]={
+ category="lu",
+ description="GEORGIAN CAPITAL LETTER AEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10CD,
+ },
[0x10D0]={
category="lo",
description="GEORGIAN LETTER AN",
@@ -30208,6 +30891,27 @@ characters.data={
specials={ "super", 0x10DC },
unicodeslot=0x10FC,
},
+ [0x10FD]={
+ category="lo",
+ description="GEORGIAN LETTER AEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10FD,
+ },
+ [0x10FE]={
+ category="lo",
+ description="GEORGIAN LETTER HARD SIGN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10FE,
+ },
+ [0x10FF]={
+ category="lo",
+ description="GEORGIAN LETTER LABIAL SIGN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10FF,
+ },
[0x1100]={
category="lo",
cjkwd="w",
@@ -31447,7 +32151,6 @@ characters.data={
},
[0x11A3]={
category="lo",
- cjkwd="w",
description="HANGUL JUNGSEONG A-EU",
direction="l",
linebreak="jv",
@@ -31455,7 +32158,6 @@ characters.data={
},
[0x11A4]={
category="lo",
- cjkwd="w",
description="HANGUL JUNGSEONG YA-U",
direction="l",
linebreak="jv",
@@ -31463,7 +32165,6 @@ characters.data={
},
[0x11A5]={
category="lo",
- cjkwd="w",
description="HANGUL JUNGSEONG YEO-YA",
direction="l",
linebreak="jv",
@@ -31471,7 +32172,6 @@ characters.data={
},
[0x11A6]={
category="lo",
- cjkwd="w",
description="HANGUL JUNGSEONG O-YA",
direction="l",
linebreak="jv",
@@ -31479,7 +32179,6 @@ characters.data={
},
[0x11A7]={
category="lo",
- cjkwd="w",
description="HANGUL JUNGSEONG O-YAE",
direction="l",
linebreak="jv",
@@ -32061,7 +32760,6 @@ characters.data={
},
[0x11FA]={
category="lo",
- cjkwd="w",
description="HANGUL JONGSEONG KIYEOK-NIEUN",
direction="l",
linebreak="jt",
@@ -32069,7 +32767,6 @@ characters.data={
},
[0x11FB]={
category="lo",
- cjkwd="w",
description="HANGUL JONGSEONG KIYEOK-PIEUP",
direction="l",
linebreak="jt",
@@ -32077,7 +32774,6 @@ characters.data={
},
[0x11FC]={
category="lo",
- cjkwd="w",
description="HANGUL JONGSEONG KIYEOK-CHIEUCH",
direction="l",
linebreak="jt",
@@ -32085,7 +32781,6 @@ characters.data={
},
[0x11FD]={
category="lo",
- cjkwd="w",
description="HANGUL JONGSEONG KIYEOK-KHIEUKH",
direction="l",
linebreak="jt",
@@ -32093,7 +32788,6 @@ characters.data={
},
[0x11FE]={
category="lo",
- cjkwd="w",
description="HANGUL JONGSEONG KIYEOK-HIEUH",
direction="l",
linebreak="jt",
@@ -32101,7 +32795,6 @@ characters.data={
},
[0x11FF]={
category="lo",
- cjkwd="w",
description="HANGUL JONGSEONG SSANGNIEUN",
direction="l",
linebreak="jt",
@@ -41576,14 +42269,14 @@ characters.data={
[0x17B4]={
category="cf",
description="KHMER VOWEL INHERENT AQ",
- direction="l",
+ direction="nsm",
linebreak="sa",
unicodeslot=0x17B4,
},
[0x17B5]={
category="cf",
description="KHMER VOWEL INHERENT AA",
- direction="l",
+ direction="nsm",
linebreak="sa",
unicodeslot=0x17B5,
},
@@ -47499,6 +48192,27 @@ characters.data={
linebreak="cm",
unicodeslot=0x1BAA,
},
+ [0x1BAB]={
+ category="mn",
+ description="SUNDANESE SIGN VIRAMA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1BAB,
+ },
+ [0x1BAC]={
+ category="mc",
+ description="SUNDANESE CONSONANT SIGN PASANGAN MA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1BAC,
+ },
+ [0x1BAD]={
+ category="mc",
+ description="SUNDANESE CONSONANT SIGN PASANGAN WA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1BAD,
+ },
[0x1BAE]={
category="lo",
description="SUNDANESE LETTER KHA",
@@ -47583,6 +48297,48 @@ characters.data={
linebreak="nu",
unicodeslot=0x1BB9,
},
+ [0x1BBA]={
+ category="lo",
+ description="SUNDANESE AVAGRAHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BBA,
+ },
+ [0x1BBB]={
+ category="lo",
+ description="SUNDANESE LETTER REU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BBB,
+ },
+ [0x1BBC]={
+ category="lo",
+ description="SUNDANESE LETTER LEU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BBC,
+ },
+ [0x1BBD]={
+ category="lo",
+ description="SUNDANESE LETTER BHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BBD,
+ },
+ [0x1BBE]={
+ category="lo",
+ description="SUNDANESE LETTER FINAL K",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BBE,
+ },
+ [0x1BBF]={
+ category="lo",
+ description="SUNDANESE LETTER FINAL M",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BBF,
+ },
[0x1BC0]={
category="lo",
description="BATAK LETTER A",
@@ -48829,6 +49585,62 @@ characters.data={
linebreak="ba",
unicodeslot=0x1C7F,
},
+ [0x1CC0]={
+ category="po",
+ description="SUNDANESE PUNCTUATION BINDU SURYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CC0,
+ },
+ [0x1CC1]={
+ category="po",
+ description="SUNDANESE PUNCTUATION BINDU PANGLONG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CC1,
+ },
+ [0x1CC2]={
+ category="po",
+ description="SUNDANESE PUNCTUATION BINDU PURNAMA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CC2,
+ },
+ [0x1CC3]={
+ category="po",
+ description="SUNDANESE PUNCTUATION BINDU CAKRA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CC3,
+ },
+ [0x1CC4]={
+ category="po",
+ description="SUNDANESE PUNCTUATION BINDU LEU SATANGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CC4,
+ },
+ [0x1CC5]={
+ category="po",
+ description="SUNDANESE PUNCTUATION BINDU KA SATANGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CC5,
+ },
+ [0x1CC6]={
+ category="po",
+ description="SUNDANESE PUNCTUATION BINDU DA SATANGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CC6,
+ },
+ [0x1CC7]={
+ category="po",
+ description="SUNDANESE PUNCTUATION BINDU BA SATANGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CC7,
+ },
[0x1CD0]={
category="mn",
description="VEDIC TONE KARSHANA",
@@ -49074,6 +49886,34 @@ characters.data={
linebreak="cm",
unicodeslot=0x1CF2,
},
+ [0x1CF3]={
+ category="mc",
+ description="VEDIC SIGN ROTATED ARDHAVISARGA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1CF3,
+ },
+ [0x1CF4]={
+ category="mn",
+ description="VEDIC TONE CANDRA ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1CF4,
+ },
+ [0x1CF5]={
+ category="lo",
+ description="VEDIC SIGN JIHVAMULIYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CF5,
+ },
+ [0x1CF6]={
+ category="lo",
+ description="VEDIC SIGN UPADHMANIYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CF6,
+ },
[0x1D00]={
category="ll",
description="LATIN LETTER SMALL CAPITAL A",
@@ -56332,6 +57172,7 @@ characters.data={
},
[0x200C]={
adobename="zerowidthnonjoiner",
+ arabic="u",
category="cf",
contextname="zwnj",
description="ZERO WIDTH NON-JOINER",
@@ -56341,6 +57182,7 @@ characters.data={
},
[0x200D]={
adobename="afii301",
+ arabic="c",
category="cf",
contextname="zwj",
description="ZERO WIDTH JOINER",
@@ -56624,7 +57466,7 @@ characters.data={
{
class="inner",
name="dots",
- }
+ },
},
specials={ "compat", 0x002E, 0x002E, 0x002E },
unicodeslot=0x2026,
@@ -56817,6 +57659,10 @@ characters.data={
linebreak="ns",
specials={ "compat", 0x0021, 0x0021 },
unicodeslot=0x203C,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x203D]={
category="po",
@@ -56832,6 +57678,16 @@ characters.data={
description="OVERLINE",
direction="on",
linebreak="al",
+ mathspec={
+ {
+ class="topaccent",
+ name="overbar",
+ },
+ {
+ class="botaccent",
+ name="underbar",
+ },
+ },
specials={ "compat", 0x0020, 0x0305 },
unicodeslot=0x203E,
},
@@ -56880,7 +57736,7 @@ characters.data={
linebreak="is",
mathspec={
{
- class="ord",
+ class="ordinary",
name="slash",
},
{
@@ -56929,6 +57785,10 @@ characters.data={
linebreak="ns",
specials={ "compat", 0x0021, 0x003F },
unicodeslot=0x2049,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x204A]={
category="po",
@@ -57244,6 +58104,8 @@ characters.data={
description="SUPERSCRIPT PLUS SIGN",
direction="es",
linebreak="al",
+ mathclass="binary",
+ mathname="positivesign",
specials={ "super", 0x002B },
unicodeslot=0x207A,
},
@@ -57252,6 +58114,8 @@ characters.data={
description="SUPERSCRIPT MINUS",
direction="es",
linebreak="al",
+ mathclass="binary",
+ mathname="negativesign",
specials={ "super", 0x2212 },
unicodeslot=0x207B,
},
@@ -57732,6 +58596,13 @@ characters.data={
linebreak="pr",
unicodeslot=0x20B9,
},
+ [0x20BA]={
+ category="sc",
+ description="TURKISH LIRA SIGN",
+ direction="et",
+ linebreak="pr",
+ unicodeslot=0x20BA,
+ },
[0x20D0]={
category="mn",
description="COMBINING LEFT HARPOON ABOVE",
@@ -57786,7 +58657,7 @@ characters.data={
description="COMBINING RIGHT ARROW ABOVE",
direction="nsm",
linebreak="cm",
- mathclass="accent",
+ mathclass="topaccent",
mathname="vec",
unicodeslot=0x20D7,
},
@@ -57816,7 +58687,7 @@ characters.data={
description="COMBINING THREE DOTS ABOVE",
direction="nsm",
linebreak="cm",
- mathclass="accent",
+ mathclass="topaccent",
mathname="dddot",
unicodeslot=0x20DB,
},
@@ -57930,7 +58801,7 @@ characters.data={
description="COMBINING WIDE BRIDGE ABOVE",
direction="nsm",
linebreak="cm",
- mathclass="accent",
+ mathclass="topaccent",
unicodeslot=0x20E9,
},
[0x20EA]={
@@ -58118,8 +58989,16 @@ characters.data={
description="PLANCK CONSTANT OVER TWO PI",
direction="l",
linebreak="al",
- mathclass="variable",
- mathname="hslash",
+ mathspec={
+ {
+ class="variable",
+ name="hslash",
+ },
+ {
+ class="ordinary",
+ name="hbar",
+ },
+ },
specials={ "font", 0x0127 },
unicodeslot=0x210F,
},
@@ -58445,7 +59324,7 @@ characters.data={
direction="l",
lccode=0x214E,
linebreak="al",
- mathclass="ord",
+ mathclass="ordinary",
mathname="Finv",
unicodeslot=0x2132,
},
@@ -58513,6 +59392,10 @@ characters.data={
linebreak="al",
specials={ "font", 0x0069 },
unicodeslot=0x2139,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x213A]={
category="so",
@@ -58574,7 +59457,7 @@ characters.data={
description="TURNED SANS-SERIF CAPITAL G",
direction="on",
linebreak="al",
- mathclass="ord",
+ mathclass="ordinary",
mathname="Game",
unicodeslot=0x2141,
},
@@ -58584,7 +59467,7 @@ characters.data={
description="TURNED SANS-SERIF CAPITAL L",
direction="on",
linebreak="al",
- mathclass="ord",
+ mathclass="ordinary",
unicodeslot=0x2142,
},
[0x2143]={
@@ -58593,7 +59476,7 @@ characters.data={
description="REVERSED SANS-SERIF CAPITAL L",
direction="on",
linebreak="al",
- mathclass="ord",
+ mathclass="ordinary",
unicodeslot=0x2143,
},
[0x2144]={
@@ -58602,7 +59485,7 @@ characters.data={
description="TURNED SANS-SERIF CAPITAL Y",
direction="on",
linebreak="al",
- mathclass="ord",
+ mathclass="ordinary",
unicodeslot=0x2144,
},
[0x2145]={
@@ -58660,7 +59543,7 @@ characters.data={
description="PROPERTY LINE",
direction="on",
linebreak="al",
- mathclass="ord",
+ mathclass="ordinary",
mathname="PropertyLine",
unicodeslot=0x214A,
},
@@ -58669,7 +59552,7 @@ characters.data={
description="TURNED AMPERSAND",
direction="on",
linebreak="al",
- mathclass="bin",
+ mathclass="binary",
mathname="upand",
unicodeslot=0x214B,
},
@@ -59301,6 +60184,7 @@ characters.data={
description="LEFTWARDS ARROW",
direction="on",
linebreak="ai",
+ mathextensible="l",
mathfiller="leftarrowfill",
mathspec={
{
@@ -59331,6 +60215,7 @@ characters.data={
direction="on",
linebreak="ai",
mathclass="relation",
+ mathextensible="u",
mathname="uparrow",
unicodeslot=0x2191,
},
@@ -59341,6 +60226,7 @@ characters.data={
description="RIGHTWARDS ARROW",
direction="on",
linebreak="ai",
+ mathextensible="r",
mathfiller="rightarrowfill",
mathspec={
{
@@ -59371,6 +60257,7 @@ characters.data={
direction="on",
linebreak="ai",
mathclass="relation",
+ mathextensible="d",
mathname="downarrow",
unicodeslot=0x2193,
},
@@ -59382,8 +60269,13 @@ characters.data={
direction="on",
linebreak="ai",
mathclass="relation",
+ mathextensible="h",
mathname="leftrightarrow",
unicodeslot=0x2194,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x2195]={
adobename="arrowupdn",
@@ -59393,8 +60285,13 @@ characters.data={
direction="on",
linebreak="ai",
mathclass="relation",
+ mathextensible="v",
mathname="updownarrow",
unicodeslot=0x2195,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x2196]={
adobename="arrowupleft",
@@ -59406,6 +60303,10 @@ characters.data={
mathclass="relation",
mathname="nwarrow",
unicodeslot=0x2196,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x2197]={
adobename="arrowupright",
@@ -59417,6 +60318,10 @@ characters.data={
mathclass="relation",
mathname="nearrow",
unicodeslot=0x2197,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x2198]={
adobename="arrowdownright",
@@ -59428,6 +60333,10 @@ characters.data={
mathclass="relation",
mathname="searrow",
unicodeslot=0x2198,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x2199]={
adobename="arrowdownleft",
@@ -59439,6 +60348,10 @@ characters.data={
mathclass="relation",
mathname="swarrow",
unicodeslot=0x2199,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x219A]={
category="sm",
@@ -59446,6 +60359,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="l",
mathname="nleftarrow",
specials={ "char", 0x2190, 0x0338 },
unicodeslot=0x219A,
@@ -59456,6 +60370,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="r",
mathname="nrightarrow",
specials={ "char", 0x2192, 0x0338 },
unicodeslot=0x219B,
@@ -59466,6 +60381,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="l",
mathname="leftwavearrow",
unicodeslot=0x219C,
},
@@ -59475,6 +60391,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="r",
mathname="rightwavearrow",
unicodeslot=0x219D,
},
@@ -59484,6 +60401,8 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="l",
+ mathfiller="twoheadleftarrowfill",
mathname="twoheadleftarrow",
unicodeslot=0x219E,
},
@@ -59493,6 +60412,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="u",
mathname="twoheaduparrow",
unicodeslot=0x219F,
},
@@ -59502,6 +60422,8 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="r",
+ mathfiller="twoheadrightarrowfill",
mathname="twoheadrightarrow",
unicodeslot=0x21A0,
},
@@ -59511,6 +60433,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="d",
mathname="twoheaddownarrow",
unicodeslot=0x21A1,
},
@@ -59520,6 +60443,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="l",
mathname="leftarrowtail",
unicodeslot=0x21A2,
},
@@ -59529,6 +60453,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="r",
mathname="rightarrowtail",
unicodeslot=0x21A3,
},
@@ -59538,6 +60463,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="l",
mathname="mapsfrom",
unicodeslot=0x21A4,
},
@@ -59547,6 +60473,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="u",
mathname="mapsup",
unicodeslot=0x21A5,
},
@@ -59556,6 +60483,8 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="r",
+ mathfiller="mapstofill",
mathname="mapsto",
unicodeslot=0x21A6,
},
@@ -59565,6 +60494,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="d",
mathname="mapsdown",
unicodeslot=0x21A7,
},
@@ -59574,7 +60504,8 @@ characters.data={
description="UP DOWN ARROW WITH BASE",
direction="on",
linebreak="al",
- mathclass="ord",
+ mathclass="ordinary",
+ mathextensible="v",
mathname="updownarrowbar",
unicodeslot=0x21A8,
},
@@ -59584,8 +60515,14 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="l",
+ mathfiller="hookleftarrowfill",
mathname="hookleftarrow",
unicodeslot=0x21A9,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x21AA]={
category="so",
@@ -59593,8 +60530,14 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="r",
+ mathfiller="hookrightarrowfill",
mathname="hookrightarrow",
unicodeslot=0x21AA,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x21AB]={
category="so",
@@ -59602,6 +60545,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="l",
mathname="looparrowleft",
unicodeslot=0x21AB,
},
@@ -59611,6 +60555,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="r",
mathname="looparrowright",
unicodeslot=0x21AC,
},
@@ -59620,6 +60565,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="h",
mathname="leftrightsquigarrow",
unicodeslot=0x21AD,
},
@@ -59629,6 +60575,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="h",
mathname="nleftrightarrow",
specials={ "char", 0x2194, 0x0338 },
unicodeslot=0x21AE,
@@ -59639,6 +60586,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="d",
mathname="downzigzagarrow",
unicodeslot=0x21AF,
},
@@ -59648,6 +60596,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="m",
mathname="Lsh",
unicodeslot=0x21B0,
},
@@ -59657,6 +60606,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="m",
mathname="Rsh",
unicodeslot=0x21B1,
},
@@ -59666,6 +60616,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="m",
mathname="Ldsh",
unicodeslot=0x21B2,
},
@@ -59675,6 +60626,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="m",
mathname="Rdsh",
unicodeslot=0x21B3,
},
@@ -59683,7 +60635,8 @@ characters.data={
description="RIGHTWARDS ARROW WITH CORNER DOWNWARDS",
direction="on",
linebreak="al",
- mathclass="ord",
+ mathclass="ordinary",
+ mathextensible="m",
mathname="linefeed",
unicodeslot=0x21B4,
},
@@ -59694,7 +60647,8 @@ characters.data={
description="DOWNWARDS ARROW WITH CORNER LEFTWARDS",
direction="on",
linebreak="al",
- mathclass="ord",
+ mathclass="ordinary",
+ mathextensible="m",
mathname="carriagereturn",
unicodeslot=0x21B5,
},
@@ -59733,6 +60687,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="h",
mathname="barleftarrowrightarrowbar",
unicodeslot=0x21B9,
},
@@ -59777,6 +60732,8 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="l",
+ mathfiller="leftharpoonupfill",
mathname="leftharpoonup",
unicodeslot=0x21BC,
},
@@ -59786,6 +60743,8 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="l",
+ mathfiller="leftharpoondownfill",
mathname="leftharpoondown",
unicodeslot=0x21BD,
},
@@ -59822,6 +60781,8 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="r",
+ mathfiller="rightharpoonupfill",
mathname="rightharpoonup",
unicodeslot=0x21C0,
},
@@ -59831,6 +60792,8 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="r",
+ mathfiller="rightharpoondownfill",
mathname="rightharpoondown",
unicodeslot=0x21C1,
},
@@ -59859,6 +60822,8 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="h",
+ mathfiller="rightoverleftarrowfill",
mathname="rightleftarrows",
unicodeslot=0x21C4,
},
@@ -59869,6 +60834,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="m",
mathname="updownarrows",
unicodeslot=0x21C5,
},
@@ -59879,6 +60845,8 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="h",
+ mathfiller="lefgtoverrightarrowfill",
mathname="leftrightarrows",
unicodeslot=0x21C6,
},
@@ -59888,6 +60856,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="l",
mathname="leftleftarrows",
unicodeslot=0x21C7,
},
@@ -59897,6 +60866,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="u",
mathname="upuparrows",
unicodeslot=0x21C8,
},
@@ -59906,6 +60876,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="r",
mathname="rightrightarrows",
unicodeslot=0x21C9,
},
@@ -59915,6 +60886,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="d",
mathname="downdownarrows",
unicodeslot=0x21CA,
},
@@ -59924,6 +60896,8 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="h",
+ mathfiller="leftrightharpoonsfill",
mathname="leftrightharpoons",
unicodeslot=0x21CB,
},
@@ -59933,6 +60907,8 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="h",
+ mathfiller="rightleftharpoonsfill",
mathname="rightleftharpoons",
unicodeslot=0x21CC,
},
@@ -59943,6 +60919,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="l",
mathname="nLeftarrow",
specials={ "char", 0x21D0, 0x0338 },
unicodeslot=0x21CD,
@@ -59953,6 +60930,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="h",
mathname="nLeftrightarrow",
specials={ "char", 0x21D4, 0x0338 },
unicodeslot=0x21CE,
@@ -59964,6 +60942,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="r",
mathname="nRightarrow",
specials={ "char", 0x21D2, 0x0338 },
unicodeslot=0x21CF,
@@ -59975,6 +60954,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="l",
mathname="Leftarrow",
unicodeslot=0x21D0,
},
@@ -59985,6 +60965,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="u",
mathname="Uparrow",
unicodeslot=0x21D1,
},
@@ -59995,8 +60976,17 @@ characters.data={
description="RIGHTWARDS DOUBLE ARROW",
direction="on",
linebreak="ai",
- mathclass="relation",
- mathname="Rightarrow",
+ mathextensible="r",
+ mathspec={
+ {
+ class="relation",
+ name="Rightarrow",
+ },
+ {
+ class="relation",
+ name="imply",
+ },
+ },
unicodeslot=0x21D2,
},
[0x21D3]={
@@ -60006,6 +60996,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="d",
mathname="Downarrow",
unicodeslot=0x21D3,
},
@@ -60017,6 +61008,7 @@ characters.data={
direction="on",
linebreak="ai",
mathclass="relation",
+ mathextensible="h",
mathname="Leftrightarrow",
unicodeslot=0x21D4,
},
@@ -60026,6 +61018,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="v",
mathname="Updownarrow",
unicodeslot=0x21D5,
},
@@ -60071,6 +61064,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="l",
mathname="Lleftarrow",
unicodeslot=0x21DA,
},
@@ -60080,6 +61074,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="r",
mathname="Rrightarrow",
unicodeslot=0x21DB,
},
@@ -60089,6 +61084,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="l",
mathname="leftsquigarrow",
unicodeslot=0x21DC,
},
@@ -60116,6 +61112,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="u",
mathname="nHuparrow",
unicodeslot=0x21DE,
},
@@ -60126,6 +61123,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="d",
mathname="nHdownarrow",
unicodeslot=0x21DF,
},
@@ -60136,6 +61134,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="l",
mathname="leftdasharrow",
unicodeslot=0x21E0,
},
@@ -60146,6 +61145,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="u",
mathname="updasharrow",
unicodeslot=0x21E1,
},
@@ -60174,6 +61174,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="d",
mathname="downdasharrow",
unicodeslot=0x21E3,
},
@@ -60184,6 +61185,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="l",
mathname="barleftarrow",
unicodeslot=0x21E4,
},
@@ -60194,6 +61196,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="r",
mathname="rightarrowbar",
unicodeslot=0x21E5,
},
@@ -60203,7 +61206,8 @@ characters.data={
description="LEFTWARDS WHITE ARROW",
direction="on",
linebreak="al",
- mathclass="ord",
+ mathclass="ordinary",
+ mathextensible="l",
mathname="leftwhitearrow",
unicodeslot=0x21E6,
},
@@ -60214,7 +61218,8 @@ characters.data={
description="UPWARDS WHITE ARROW",
direction="on",
linebreak="al",
- mathclass="ord",
+ mathclass="ordinary",
+ mathextensible="u",
mathname="upwhitearrow",
unicodeslot=0x21E7,
},
@@ -60224,7 +61229,8 @@ characters.data={
description="RIGHTWARDS WHITE ARROW",
direction="on",
linebreak="al",
- mathclass="ord",
+ mathclass="ordinary",
+ mathextensible="r",
mathname="rightwhitearrow",
unicodeslot=0x21E8,
},
@@ -60234,7 +61240,8 @@ characters.data={
description="DOWNWARDS WHITE ARROW",
direction="on",
linebreak="al",
- mathclass="ord",
+ mathclass="ordinary",
+ mathextensible="d",
mathname="downwhitearrow",
unicodeslot=0x21E9,
},
@@ -60251,7 +61258,8 @@ characters.data={
description="UPWARDS WHITE ARROW ON PEDESTAL",
direction="on",
linebreak="al",
- mathclass="ord",
+ mathclass="ordinary",
+ mathextensible="u",
mathname="whitearrowupfrombar",
unicodeslot=0x21EB,
},
@@ -60317,6 +61325,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="r",
mathname="circleonrightarrow",
unicodeslot=0x21F4,
},
@@ -60326,6 +61335,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="m",
mathname="downuparrows",
unicodeslot=0x21F5,
},
@@ -60335,6 +61345,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="r",
mathname="rightthreearrows",
unicodeslot=0x21F6,
},
@@ -60344,6 +61355,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="l",
mathname="nvleftarrow",
unicodeslot=0x21F7,
},
@@ -60353,6 +61365,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="r",
mathname="nvrightarrow",
unicodeslot=0x21F8,
},
@@ -60362,6 +61375,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="h",
mathname="nvleftrightarrow",
unicodeslot=0x21F9,
},
@@ -60371,6 +61385,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="l",
mathname="nVleftarrow",
unicodeslot=0x21FA,
},
@@ -60380,6 +61395,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="r",
mathname="nVrightarrow",
unicodeslot=0x21FB,
},
@@ -60389,6 +61405,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="h",
mathname="nVleftrightarrow",
unicodeslot=0x21FC,
},
@@ -60398,6 +61415,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="l",
mathname="leftarrowtriangle",
unicodeslot=0x21FD,
},
@@ -60407,6 +61425,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="r",
mathname="rightarrowtriangle",
unicodeslot=0x21FE,
},
@@ -60416,6 +61435,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="h",
mathname="leftrightarrowtriangle",
unicodeslot=0x21FF,
},
@@ -60426,7 +61446,7 @@ characters.data={
description="FOR ALL",
direction="on",
linebreak="ai",
- mathclass="ord",
+ mathclass="ordinary",
mathname="forall",
unicodeslot=0x2200,
},
@@ -60435,7 +61455,7 @@ characters.data={
description="COMPLEMENT",
direction="on",
linebreak="al",
- mathclass="ord",
+ mathclass="ordinary",
mathname="complement",
unicodeslot=0x2201,
},
@@ -60457,7 +61477,7 @@ characters.data={
description="THERE EXISTS",
direction="on",
linebreak="ai",
- mathclass="ord",
+ mathclass="ordinary",
mathname="exists",
unicodeslot=0x2203,
},
@@ -60466,7 +61486,7 @@ characters.data={
description="THERE DOES NOT EXIST",
direction="on",
linebreak="al",
- mathclass="ord",
+ mathclass="ordinary",
mathname="nexists",
specials={ "char", 0x2203, 0x0338 },
unicodeslot=0x2204,
@@ -60627,11 +61647,9 @@ characters.data={
[0x2212]={
adobename="minus",
category="sm",
---comment="the mathclass is needed for mathsymbol remapping",
description="MINUS SIGN",
direction="es",
linebreak="pr",
---mathclass="binary",
mathspec={
{
class="binary",
@@ -60667,7 +61685,7 @@ characters.data={
adobename="divisionslash",
category="sm",
cjkwd="a",
- comment="mathclass=ord,mathname=diagup",
+ comment="mathclass=ordinary,mathname=diagup",
description="DIVISION SLASH",
direction="on",
linebreak="ai",
@@ -60676,7 +61694,7 @@ characters.data={
},
[0x2216]={
category="sm",
- comment="mathclass=ord,mathname=diagdown",
+ comment="mathclass=ordinary,mathname=diagdown",
description="SET MINUS",
direction="on",
linebreak="al",
@@ -60771,7 +61789,7 @@ characters.data={
description="RIGHT ANGLE",
direction="on",
linebreak="ai",
- mathclass="ord",
+ mathclass="ordinary",
mathname="rightangle",
unicodeslot=0x221F,
},
@@ -60782,7 +61800,7 @@ characters.data={
description="ANGLE",
direction="on",
linebreak="ai",
- mathclass="ord",
+ mathclass="ordinary",
mathname="angle",
unicodeslot=0x2220,
},
@@ -60791,7 +61809,7 @@ characters.data={
description="MEASURED ANGLE",
direction="on",
linebreak="al",
- mathclass="ord",
+ mathclass="ordinary",
mathname="measuredangle",
unicodeslot=0x2221,
},
@@ -60800,7 +61818,7 @@ characters.data={
description="SPHERICAL ANGLE",
direction="on",
linebreak="al",
- mathclass="ord",
+ mathclass="ordinary",
mathname="sphericalangle",
unicodeslot=0x2222,
},
@@ -60887,11 +61905,11 @@ characters.data={
linebreak="ai",
mathspec={
{
- class="bin",
+ class="binary",
name="vee",
},
{
- class="bin",
+ class="binary",
name="lor",
},
},
@@ -60932,15 +61950,16 @@ characters.data={
description="INTEGRAL",
direction="on",
linebreak="ai",
+ mathclass="limop",
mathspec={
- {
- class="nothing",
- name="intop",
- },
{
class="limop",
name="int",
},
+ {
+ class="nothing",
+ name="intop",
+ },
},
unicodeslot=0x222B,
},
@@ -60951,15 +61970,16 @@ characters.data={
description="DOUBLE INTEGRAL",
direction="on",
linebreak="ai",
+ mathclass="limop",
mathspec={
- {
- class="nothing",
- name="iintop",
- },
{
class="limop",
name="iint",
},
+ {
+ class="nothing",
+ name="iintop",
+ },
},
specials={ "compat", 0x222B, 0x222B },
unicodeslot=0x222C,
@@ -60969,15 +61989,16 @@ characters.data={
description="TRIPLE INTEGRAL",
direction="on",
linebreak="al",
+ mathclass="limop",
mathspec={
- {
- class="nothing",
- name="iiintop",
- },
{
class="limop",
name="iiint",
},
+ {
+ class="nothing",
+ name="iiintop",
+ },
},
specials={ "compat", 0x222B, 0x222B, 0x222B },
unicodeslot=0x222D,
@@ -61507,6 +62528,7 @@ characters.data={
direction="on",
linebreak="ai",
mathclass="relation",
+ mathextensible="h",
mathname="equiv",
unicodeslot=0x2261,
},
@@ -61517,6 +62539,8 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="h",
+ mathfiller="triplerelfill",
mathname="nequiv",
specials={ "char", 0x2261, 0x0338 },
unicodeslot=0x2262,
@@ -61526,6 +62550,8 @@ characters.data={
description="STRICTLY EQUIVALENT TO",
direction="on",
linebreak="al",
+ mathclass="relation",
+ mathextensible="h",
unicodeslot=0x2263,
},
[0x2264]={
@@ -62402,7 +63428,7 @@ characters.data={
description="NORMAL SUBGROUP OF",
direction="on",
linebreak="al",
- mathclass="bin",
+ mathclass="binary",
mirror=0x22B3,
unicodeslot=0x22B2,
},
@@ -62412,7 +63438,7 @@ characters.data={
description="CONTAINS AS NORMAL SUBGROUP",
direction="on",
linebreak="al",
- mathclass="bin",
+ mathclass="binary",
mirror=0x22B2,
unicodeslot=0x22B3,
},
@@ -63174,7 +64200,7 @@ characters.data={
description="DIAMETER SIGN",
direction="on",
linebreak="al",
- mathclass="ord",
+ mathclass="ordinary",
mathname="varnothing",
unicodeslot=0x2300,
},
@@ -63235,7 +64261,7 @@ characters.data={
description="LEFT CEILING",
direction="on",
linebreak="al",
- mathspec = {
+ mathspec={
{
class="open",
name="lceil",
@@ -63243,7 +64269,7 @@ characters.data={
{
class="open",
name="lceiling",
- }
+ },
},
mirror=0x2309,
unicodeslot=0x2308,
@@ -63253,7 +64279,7 @@ characters.data={
description="RIGHT CEILING",
direction="on",
linebreak="al",
- mathspec = {
+ mathspec={
{
class="close",
name="rceil",
@@ -63261,7 +64287,7 @@ characters.data={
{
class="close",
name="rceiling",
- }
+ },
},
mirror=0x2308,
unicodeslot=0x2309,
@@ -63392,15 +64418,23 @@ characters.data={
category="so",
description="WATCH",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x231A,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x231B]={
category="so",
description="HOURGLASS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x231B,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x231C]={
category="so",
@@ -64821,7 +65855,7 @@ characters.data={
description="TOP TORTOISE SHELL BRACKET",
direction="on",
linebreak="al",
- mathclass="accent",
+ mathclass="topaccent",
unicodeslot=0x23E0,
},
[0x23E1]={
@@ -64829,7 +65863,7 @@ characters.data={
description="BOTTOM TORTOISE SHELL BRACKET",
direction="on",
linebreak="al",
- mathclass="accent",
+ mathclass="botaccent",
unicodeslot=0x23E1,
},
[0x23E2]={
@@ -64934,28 +65968,28 @@ characters.data={
category="so",
description="ALARM CLOCK",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x23F0,
},
[0x23F1]={
category="so",
description="STOPWATCH",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x23F1,
},
[0x23F2]={
category="so",
description="TIMER CLOCK",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x23F2,
},
[0x23F3]={
category="so",
description="HOURGLASS WITH FLOWING SAND",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x23F3,
},
[0x2400]={
@@ -66311,6 +67345,10 @@ characters.data={
linebreak="ai",
specials={ "circle", 0x004D },
unicodeslot=0x24C2,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x24C3]={
adobename="Ncircle",
@@ -66364,7 +67402,7 @@ characters.data={
direction="l",
lccode=0x24E1,
linebreak="ai",
- mathclass="ord",
+ mathclass="ordinary",
mathname="circledR",
specials={ "circle", 0x0052 },
unicodeslot=0x24C7,
@@ -66377,7 +67415,7 @@ characters.data={
direction="l",
lccode=0x24E2,
linebreak="ai",
- mathclass="ord",
+ mathclass="ordinary",
mathname="circledS",
specials={ "circle", 0x0053 },
unicodeslot=0x24C8,
@@ -68228,7 +69266,7 @@ characters.data={
description="BLACK SQUARE",
direction="on",
linebreak="ai",
- mathclass="ord",
+ mathclass="ordinary",
mathname="blacksquare",
unicodeslot=0x25A0,
},
@@ -68241,11 +69279,11 @@ characters.data={
linebreak="ai",
mathspec={
{
- class="ord",
+ class="ordinary",
name="square",
},
{
- class="ord",
+ class="ordinary",
name="Box",
},
},
@@ -68256,7 +69294,7 @@ characters.data={
description="WHITE SQUARE WITH ROUNDED CORNERS",
direction="on",
linebreak="al",
- mathclass="ord",
+ mathclass="ordinary",
unicodeslot=0x25A2,
},
[0x25A3]={
@@ -68329,6 +69367,10 @@ characters.data={
direction="on",
linebreak="al",
unicodeslot=0x25AA,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x25AB]={
adobename="whitesmallsquare",
@@ -68337,6 +69379,10 @@ characters.data={
direction="on",
linebreak="al",
unicodeslot=0x25AB,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x25AC]={
adobename="filledrect",
@@ -68388,6 +69434,8 @@ characters.data={
description="BLACK UP-POINTING TRIANGLE",
direction="on",
linebreak="ai",
+ mathclass="binary",
+ mathname="blacktriangle",
unicodeslot=0x25B2,
},
[0x25B3]={
@@ -68399,7 +69447,7 @@ characters.data={
linebreak="ai",
mathspec={
{
- class="ord",
+ class="ordinary",
name="triangle",
},
{
@@ -68432,9 +69480,13 @@ characters.data={
description="BLACK RIGHT-POINTING TRIANGLE",
direction="on",
linebreak="ai",
- mathclass="bin",
+ mathclass="binary",
mathname="blacktriangleright",
unicodeslot=0x25B6,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x25B7]={
adobename="whiterightpointingtriangle",
@@ -68443,7 +69495,7 @@ characters.data={
description="WHITE RIGHT-POINTING TRIANGLE",
direction="on",
linebreak="ai",
- mathclass="bin",
+ mathclass="binary",
mathname="triangleright",
unicodeslot=0x25B7,
},
@@ -68452,8 +69504,6 @@ characters.data={
description="BLACK RIGHT-POINTING SMALL TRIANGLE",
direction="on",
linebreak="al",
- mathclass="bin",
- mathname="blacktriangleleft",
unicodeslot=0x25B8,
},
[0x25B9]={
@@ -68486,6 +69536,8 @@ characters.data={
description="BLACK DOWN-POINTING TRIANGLE",
direction="on",
linebreak="ai",
+ mathclass="binary",
+ mathname="blacktriangledown",
unicodeslot=0x25BC,
},
[0x25BD]={
@@ -68495,8 +69547,16 @@ characters.data={
description="WHITE DOWN-POINTING TRIANGLE",
direction="on",
linebreak="ai",
- mathclass="binary",
- mathname="bigtriangledown",
+ mathspec={
+ {
+ class="binary",
+ name="triangledown",
+ },
+ {
+ class="binary",
+ name="bigtriangledown",
+ },
+ },
unicodeslot=0x25BD,
},
[0x25BE]={
@@ -68521,7 +69581,13 @@ characters.data={
description="BLACK LEFT-POINTING TRIANGLE",
direction="on",
linebreak="ai",
+ mathclass="binary",
+ mathname="blacktriangleleft",
unicodeslot=0x25C0,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x25C1]={
adobename="whiteleftpointingtriangle",
@@ -68530,7 +69596,7 @@ characters.data={
description="WHITE LEFT-POINTING TRIANGLE",
direction="on",
linebreak="ai",
- mathclass="bin",
+ mathclass="binary",
mathname="triangleleft",
unicodeslot=0x25C1,
},
@@ -68605,7 +69671,7 @@ characters.data={
description="LOZENGE",
direction="on",
linebreak="al",
- mathclass="ord",
+ mathclass="ordinary",
mathname="lozenge",
unicodeslot=0x25CA,
},
@@ -68977,6 +70043,10 @@ characters.data={
direction="on",
linebreak="al",
unicodeslot=0x25FB,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x25FC]={
category="sm",
@@ -68984,6 +70054,10 @@ characters.data={
direction="on",
linebreak="al",
unicodeslot=0x25FC,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x25FD]={
category="sm",
@@ -68991,6 +70065,10 @@ characters.data={
direction="on",
linebreak="al",
unicodeslot=0x25FD,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x25FE]={
category="sm",
@@ -68998,6 +70076,10 @@ characters.data={
direction="on",
linebreak="al",
unicodeslot=0x25FE,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x25FF]={
category="sm",
@@ -69010,28 +70092,36 @@ characters.data={
category="so",
description="BLACK SUN WITH RAYS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x2600,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x2601]={
category="so",
description="CLOUD",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x2601,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x2602]={
category="so",
description="UMBRELLA",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x2602,
},
[0x2603]={
category="so",
description="SNOWMAN",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x2603,
},
[0x2604]={
@@ -69048,7 +70138,7 @@ characters.data={
description="BLACK STAR",
direction="on",
linebreak="ai",
- mathclass="ord",
+ mathclass="ordinary",
mathname="bigstar",
unicodeslot=0x2605,
},
@@ -69119,6 +70209,10 @@ characters.data={
direction="on",
linebreak="ai",
unicodeslot=0x260E,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x260F]={
adobename="whitetelephone",
@@ -69142,6 +70236,10 @@ characters.data={
direction="on",
linebreak="al",
unicodeslot=0x2611,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x2612]={
category="so",
@@ -69162,16 +70260,24 @@ characters.data={
cjkwd="a",
description="UMBRELLA WITH RAIN DROPS",
direction="on",
- linebreak="ai",
+ linebreak="id",
unicodeslot=0x2614,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x2615]={
category="so",
cjkwd="a",
description="HOT BEVERAGE",
direction="on",
- linebreak="ai",
+ linebreak="id",
unicodeslot=0x2615,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x2616]={
category="so",
@@ -69191,7 +70297,7 @@ characters.data={
category="so",
description="SHAMROCK",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x2618,
},
[0x2619]={
@@ -69205,14 +70311,14 @@ characters.data={
category="so",
description="BLACK LEFT POINTING INDEX",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x261A,
},
[0x261B]={
category="so",
description="BLACK RIGHT POINTING INDEX",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x261B,
},
[0x261C]={
@@ -69221,7 +70327,7 @@ characters.data={
cjkwd="a",
description="WHITE LEFT POINTING INDEX",
direction="on",
- linebreak="ai",
+ linebreak="id",
unicodeslot=0x261C,
},
[0x261D]={
@@ -69229,8 +70335,12 @@ characters.data={
category="so",
description="WHITE UP POINTING INDEX",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x261D,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x261E]={
adobename="pointingindexrightwhite",
@@ -69238,7 +70348,7 @@ characters.data={
cjkwd="a",
description="WHITE RIGHT POINTING INDEX",
direction="on",
- linebreak="ai",
+ linebreak="id",
unicodeslot=0x261E,
},
[0x261F]={
@@ -69246,7 +70356,7 @@ characters.data={
category="so",
description="WHITE DOWN POINTING INDEX",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x261F,
},
[0x2620]={
@@ -69429,7 +70539,7 @@ characters.data={
category="so",
description="WHITE FROWNING FACE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x2639,
},
[0x263A]={
@@ -69437,15 +70547,19 @@ characters.data={
category="so",
description="WHITE SMILING FACE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x263A,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x263B]={
adobename="invsmileface",
category="so",
description="BLACK SMILING FACE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x263B,
},
[0x263C]={
@@ -69544,6 +70658,10 @@ characters.data={
direction="on",
linebreak="al",
unicodeslot=0x2648,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x2649]={
category="so",
@@ -69551,6 +70669,10 @@ characters.data={
direction="on",
linebreak="al",
unicodeslot=0x2649,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x264A]={
category="so",
@@ -69558,6 +70680,10 @@ characters.data={
direction="on",
linebreak="al",
unicodeslot=0x264A,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x264B]={
category="so",
@@ -69565,6 +70691,10 @@ characters.data={
direction="on",
linebreak="al",
unicodeslot=0x264B,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x264C]={
category="so",
@@ -69572,6 +70702,10 @@ characters.data={
direction="on",
linebreak="al",
unicodeslot=0x264C,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x264D]={
category="so",
@@ -69579,6 +70713,10 @@ characters.data={
direction="on",
linebreak="al",
unicodeslot=0x264D,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x264E]={
category="so",
@@ -69586,6 +70724,10 @@ characters.data={
direction="on",
linebreak="al",
unicodeslot=0x264E,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x264F]={
category="so",
@@ -69593,6 +70735,10 @@ characters.data={
direction="on",
linebreak="al",
unicodeslot=0x264F,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x2650]={
category="so",
@@ -69600,6 +70746,10 @@ characters.data={
direction="on",
linebreak="al",
unicodeslot=0x2650,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x2651]={
category="so",
@@ -69607,6 +70757,10 @@ characters.data={
direction="on",
linebreak="al",
unicodeslot=0x2651,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x2652]={
category="so",
@@ -69614,6 +70768,10 @@ characters.data={
direction="on",
linebreak="al",
unicodeslot=0x2652,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x2653]={
category="so",
@@ -69621,6 +70779,10 @@ characters.data={
direction="on",
linebreak="al",
unicodeslot=0x2653,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x2654]={
category="so",
@@ -69716,6 +70878,10 @@ characters.data={
mathclass="default",
mathname="spadesuit",
unicodeslot=0x2660,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x2661]={
adobename="heartsuitwhite",
@@ -69748,6 +70914,10 @@ characters.data={
mathclass="default",
mathname="clubsuit",
unicodeslot=0x2663,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x2664]={
adobename="spadesuitwhite",
@@ -69766,6 +70936,10 @@ characters.data={
direction="on",
linebreak="ai",
unicodeslot=0x2665,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x2666]={
adobename="diamond",
@@ -69773,9 +70947,13 @@ characters.data={
description="BLACK DIAMOND SUIT",
direction="on",
linebreak="al",
- mathclass="ord",
+ mathclass="ordinary",
mathname="blacklozenge",
unicodeslot=0x2666,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x2667]={
adobename="clubsuitwhite",
@@ -69792,8 +70970,12 @@ characters.data={
cjkwd="a",
description="HOT SPRINGS",
direction="on",
- linebreak="ai",
+ linebreak="id",
unicodeslot=0x2668,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x2669]={
adobename="quarternote",
@@ -69944,6 +71126,10 @@ characters.data={
direction="on",
linebreak="al",
unicodeslot=0x267B,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x267C]={
category="so",
@@ -69970,8 +71156,12 @@ characters.data={
category="so",
description="WHEELCHAIR SYMBOL",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x267F,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x2680]={
category="so",
@@ -70112,6 +71302,10 @@ characters.data={
direction="on",
linebreak="al",
unicodeslot=0x2693,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x2694]={
category="so",
@@ -70205,6 +71399,10 @@ characters.data={
direction="on",
linebreak="al",
unicodeslot=0x26A0,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x26A1]={
category="so",
@@ -70212,6 +71410,10 @@ characters.data={
direction="on",
linebreak="al",
unicodeslot=0x26A1,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x26A2]={
category="so",
@@ -70275,6 +71477,10 @@ characters.data={
direction="on",
linebreak="al",
unicodeslot=0x26AA,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x26AB]={
category="so",
@@ -70282,6 +71488,10 @@ characters.data={
direction="on",
linebreak="al",
unicodeslot=0x26AB,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x26AC]={
category="so",
@@ -70406,51 +71616,59 @@ characters.data={
category="so",
description="SOCCER BALL",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x26BD,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x26BE]={
category="so",
cjkwd="a",
description="BASEBALL",
direction="on",
- linebreak="ai",
+ linebreak="id",
unicodeslot=0x26BE,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x26BF]={
category="so",
cjkwd="a",
description="SQUARED KEY",
direction="on",
- linebreak="ai",
+ linebreak="id",
unicodeslot=0x26BF,
},
[0x26C0]={
category="so",
description="WHITE DRAUGHTS MAN",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x26C0,
},
[0x26C1]={
category="so",
description="WHITE DRAUGHTS KING",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x26C1,
},
[0x26C2]={
category="so",
description="BLACK DRAUGHTS MAN",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x26C2,
},
[0x26C3]={
category="so",
description="BLACK DRAUGHTS KING",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x26C3,
},
[0x26C4]={
@@ -70458,23 +71676,31 @@ characters.data={
cjkwd="a",
description="SNOWMAN WITHOUT SNOW",
direction="on",
- linebreak="ai",
+ linebreak="id",
unicodeslot=0x26C4,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x26C5]={
category="so",
cjkwd="a",
description="SUN BEHIND CLOUD",
direction="on",
- linebreak="ai",
+ linebreak="id",
unicodeslot=0x26C5,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x26C6]={
category="so",
cjkwd="a",
description="RAIN",
direction="on",
- linebreak="ai",
+ linebreak="id",
unicodeslot=0x26C6,
},
[0x26C7]={
@@ -70482,7 +71708,7 @@ characters.data={
cjkwd="a",
description="BLACK SNOWMAN",
direction="on",
- linebreak="ai",
+ linebreak="id",
unicodeslot=0x26C7,
},
[0x26C8]={
@@ -70490,7 +71716,7 @@ characters.data={
cjkwd="a",
description="THUNDER CLOUD AND RAIN",
direction="on",
- linebreak="ai",
+ linebreak="id",
unicodeslot=0x26C8,
},
[0x26C9]={
@@ -70530,7 +71756,7 @@ characters.data={
cjkwd="a",
description="DISABLED CAR",
direction="on",
- linebreak="ai",
+ linebreak="id",
unicodeslot=0x26CD,
},
[0x26CE]={
@@ -70545,7 +71771,7 @@ characters.data={
cjkwd="a",
description="PICK",
direction="on",
- linebreak="ai",
+ linebreak="id",
unicodeslot=0x26CF,
},
[0x26D0]={
@@ -70553,7 +71779,7 @@ characters.data={
cjkwd="a",
description="CAR SLIDING",
direction="on",
- linebreak="ai",
+ linebreak="id",
unicodeslot=0x26D0,
},
[0x26D1]={
@@ -70561,7 +71787,7 @@ characters.data={
cjkwd="a",
description="HELMET WITH WHITE CROSS",
direction="on",
- linebreak="ai",
+ linebreak="id",
unicodeslot=0x26D1,
},
[0x26D2]={
@@ -70577,7 +71803,7 @@ characters.data={
cjkwd="a",
description="CHAINS",
direction="on",
- linebreak="ai",
+ linebreak="id",
unicodeslot=0x26D3,
},
[0x26D4]={
@@ -70585,8 +71811,12 @@ characters.data={
cjkwd="a",
description="NO ENTRY",
direction="on",
- linebreak="ai",
+ linebreak="id",
unicodeslot=0x26D4,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x26D5]={
category="so",
@@ -70617,7 +71847,7 @@ characters.data={
cjkwd="a",
description="BLACK LEFT LANE MERGE",
direction="on",
- linebreak="ai",
+ linebreak="id",
unicodeslot=0x26D8,
},
[0x26D9]={
@@ -70625,7 +71855,7 @@ characters.data={
cjkwd="a",
description="WHITE LEFT LANE MERGE",
direction="on",
- linebreak="ai",
+ linebreak="id",
unicodeslot=0x26D9,
},
[0x26DA]={
@@ -70649,7 +71879,7 @@ characters.data={
cjkwd="a",
description="LEFT CLOSED ENTRY",
direction="on",
- linebreak="ai",
+ linebreak="id",
unicodeslot=0x26DC,
},
[0x26DD]={
@@ -70673,7 +71903,7 @@ characters.data={
cjkwd="a",
description="BLACK TRUCK",
direction="on",
- linebreak="ai",
+ linebreak="id",
unicodeslot=0x26DF,
},
[0x26E0]={
@@ -70681,7 +71911,7 @@ characters.data={
cjkwd="a",
description="RESTRICTED LEFT ENTRY-1",
direction="on",
- linebreak="ai",
+ linebreak="id",
unicodeslot=0x26E0,
},
[0x26E1]={
@@ -70689,7 +71919,7 @@ characters.data={
cjkwd="a",
description="RESTRICTED LEFT ENTRY-2",
direction="on",
- linebreak="ai",
+ linebreak="id",
unicodeslot=0x26E1,
},
[0x26E2]={
@@ -70756,8 +71986,12 @@ characters.data={
cjkwd="a",
description="CHURCH",
direction="on",
- linebreak="ai",
+ linebreak="id",
unicodeslot=0x26EA,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x26EB]={
category="so",
@@ -70812,7 +72046,7 @@ characters.data={
cjkwd="a",
description="UMBRELLA ON GROUND",
direction="on",
- linebreak="ai",
+ linebreak="id",
unicodeslot=0x26F1,
},
[0x26F2]={
@@ -70820,23 +72054,31 @@ characters.data={
cjkwd="a",
description="FOUNTAIN",
direction="on",
- linebreak="ai",
+ linebreak="id",
unicodeslot=0x26F2,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x26F3]={
category="so",
cjkwd="a",
description="FLAG IN HOLE",
direction="on",
- linebreak="ai",
+ linebreak="id",
unicodeslot=0x26F3,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x26F4]={
category="so",
cjkwd="a",
description="FERRY",
direction="on",
- linebreak="ai",
+ linebreak="id",
unicodeslot=0x26F4,
},
[0x26F5]={
@@ -70844,8 +72086,12 @@ characters.data={
cjkwd="a",
description="SAILBOAT",
direction="on",
- linebreak="ai",
+ linebreak="id",
unicodeslot=0x26F5,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x26F6]={
category="so",
@@ -70860,7 +72106,7 @@ characters.data={
cjkwd="a",
description="SKIER",
direction="on",
- linebreak="ai",
+ linebreak="id",
unicodeslot=0x26F7,
},
[0x26F8]={
@@ -70868,7 +72114,7 @@ characters.data={
cjkwd="a",
description="ICE SKATE",
direction="on",
- linebreak="ai",
+ linebreak="id",
unicodeslot=0x26F8,
},
[0x26F9]={
@@ -70876,7 +72122,7 @@ characters.data={
cjkwd="a",
description="PERSON WITH BALL",
direction="on",
- linebreak="ai",
+ linebreak="id",
unicodeslot=0x26F9,
},
[0x26FA]={
@@ -70884,8 +72130,12 @@ characters.data={
cjkwd="a",
description="TENT",
direction="on",
- linebreak="ai",
+ linebreak="id",
unicodeslot=0x26FA,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x26FB]={
category="so",
@@ -70908,15 +72158,19 @@ characters.data={
cjkwd="a",
description="FUEL PUMP",
direction="on",
- linebreak="ai",
+ linebreak="id",
unicodeslot=0x26FD,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x26FE]={
category="so",
cjkwd="a",
description="CUP ON BLACK SQUARE",
direction="on",
- linebreak="ai",
+ linebreak="id",
unicodeslot=0x26FE,
},
[0x26FF]={
@@ -70924,35 +72178,39 @@ characters.data={
cjkwd="a",
description="WHITE FLAG WITH HORIZONTAL MIDDLE BLACK STRIPE",
direction="on",
- linebreak="ai",
+ linebreak="id",
unicodeslot=0x26FF,
},
[0x2701]={
category="so",
description="UPPER BLADE SCISSORS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x2701,
},
[0x2702]={
category="so",
description="BLACK SCISSORS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x2702,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x2703]={
category="so",
description="LOWER BLADE SCISSORS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x2703,
},
[0x2704]={
category="so",
description="WHITE SCISSORS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x2704,
},
[0x2705]={
@@ -70980,42 +72238,54 @@ characters.data={
category="so",
description="AIRPLANE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x2708,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x2709]={
category="so",
description="ENVELOPE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x2709,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x270A]={
category="so",
description="RAISED FIST",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x270A,
},
[0x270B]={
category="so",
description="RAISED HAND",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x270B,
},
[0x270C]={
category="so",
description="VICTORY HAND",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x270C,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x270D]={
category="so",
description="WRITING HAND",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x270D,
},
[0x270E]={
@@ -71031,6 +72301,10 @@ characters.data={
direction="on",
linebreak="al",
unicodeslot=0x270F,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x2710]={
category="so",
@@ -71052,6 +72326,10 @@ characters.data={
direction="on",
linebreak="al",
unicodeslot=0x2712,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x2713]={
adobename="checkmark",
@@ -71069,6 +72347,10 @@ characters.data={
direction="on",
linebreak="al",
unicodeslot=0x2714,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x2715]={
category="so",
@@ -71083,6 +72365,10 @@ characters.data={
direction="on",
linebreak="al",
unicodeslot=0x2716,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x2717]={
category="so",
@@ -71288,6 +72574,10 @@ characters.data={
direction="on",
linebreak="al",
unicodeslot=0x2733,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x2734]={
category="so",
@@ -71295,6 +72585,10 @@ characters.data={
direction="on",
linebreak="al",
unicodeslot=0x2734,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x2735]={
category="so",
@@ -71408,6 +72702,10 @@ characters.data={
direction="on",
linebreak="al",
unicodeslot=0x2744,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x2745]={
category="so",
@@ -71429,6 +72727,10 @@ characters.data={
direction="on",
linebreak="al",
unicodeslot=0x2747,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x2748]={
category="so",
@@ -71542,6 +72844,10 @@ characters.data={
direction="on",
linebreak="ai",
unicodeslot=0x2757,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x2758]={
category="so",
@@ -71633,6 +72939,10 @@ characters.data={
direction="on",
linebreak="al",
unicodeslot=0x2764,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x2765]={
category="so",
@@ -72094,6 +73404,10 @@ characters.data={
direction="on",
linebreak="al",
unicodeslot=0x27A1,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x27A2]={
category="so",
@@ -72388,6 +73702,15 @@ characters.data={
linebreak="al",
unicodeslot=0x27CA,
},
+ [0x27CB]={
+ category="sm",
+ comment="check math properties",
+ description="MATHEMATICAL RISING DIAGONAL",
+ direction="on",
+ linebreak="al",
+ mirror=0x27CD,
+ unicodeslot=0x27CB,
+ },
[0x27CC]={
category="sm",
description="LONG DIVISION",
@@ -72395,6 +73718,15 @@ characters.data={
linebreak="al",
unicodeslot=0x27CC,
},
+ [0x27CD]={
+ category="sm",
+ comment="check math properties",
+ description="MATHEMATICAL FALLING DIAGONAL",
+ direction="on",
+ linebreak="al",
+ mirror=0x27CB,
+ unicodeslot=0x27CD,
+ },
[0x27CE]={
category="sm",
description="SQUARED LOGICAL AND",
@@ -72680,6 +74012,7 @@ characters.data={
description="UPWARDS QUADRUPLE ARROW",
direction="on",
linebreak="al",
+ mathextensible="u",
unicodeslot=0x27F0,
},
[0x27F1]={
@@ -72687,6 +74020,7 @@ characters.data={
description="DOWNWARDS QUADRUPLE ARROW",
direction="on",
linebreak="al",
+ mathextensible="v",
unicodeslot=0x27F1,
},
[0x27F2]={
@@ -72708,6 +74042,7 @@ characters.data={
description="RIGHT ARROW WITH CIRCLED PLUS",
direction="on",
linebreak="al",
+ mathextensible="r",
unicodeslot=0x27F4,
},
[0x27F5]={
@@ -72716,6 +74051,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="l",
mathname="longleftarrow",
unicodeslot=0x27F5,
},
@@ -72725,6 +74061,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="r",
mathname="longrightarrow",
unicodeslot=0x27F6,
},
@@ -72734,6 +74071,8 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="h",
+ mathfiller="leftrightarrowfill",
mathname="longleftrightarrow",
unicodeslot=0x27F7,
},
@@ -72743,6 +74082,8 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="l",
+ mathfiller="Leftarrowfill",
mathname="Longleftarrow",
unicodeslot=0x27F8,
},
@@ -72752,6 +74093,8 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="r",
+ mathfiller="Rightarrowfill",
mathname="Longrightarrow",
unicodeslot=0x27F9,
},
@@ -72761,6 +74104,8 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="h",
+ mathfiller="Leftrightarrowfill",
mathname="Longleftrightarrow",
unicodeslot=0x27FA,
},
@@ -72770,6 +74115,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="l",
mathname="longmapsfrom",
unicodeslot=0x27FB,
},
@@ -72779,6 +74125,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="r",
mathname="longmapsto",
unicodeslot=0x27FC,
},
@@ -72788,6 +74135,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="l",
mathname="Longmapsfrom",
unicodeslot=0x27FD,
},
@@ -72797,6 +74145,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="r",
mathname="Longmapsto",
unicodeslot=0x27FE,
},
@@ -72806,6 +74155,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="r",
mathname="longrightsquigarrow",
unicodeslot=0x27FF,
},
@@ -74606,6 +75956,7 @@ characters.data={
description="RIGHTWARDS TWO-HEADED ARROW WITH VERTICAL STROKE",
direction="on",
linebreak="al",
+ mathextensible="r",
unicodeslot=0x2900,
},
[0x2901]={
@@ -74613,6 +75964,7 @@ characters.data={
description="RIGHTWARDS TWO-HEADED ARROW WITH DOUBLE VERTICAL STROKE",
direction="on",
linebreak="al",
+ mathextensible="r",
unicodeslot=0x2901,
},
[0x2902]={
@@ -74620,6 +75972,7 @@ characters.data={
description="LEFTWARDS DOUBLE ARROW WITH VERTICAL STROKE",
direction="on",
linebreak="al",
+ mathextensible="l",
unicodeslot=0x2902,
},
[0x2903]={
@@ -74627,6 +75980,7 @@ characters.data={
description="RIGHTWARDS DOUBLE ARROW WITH VERTICAL STROKE",
direction="on",
linebreak="al",
+ mathextensible="r",
unicodeslot=0x2903,
},
[0x2904]={
@@ -74634,6 +75988,7 @@ characters.data={
description="LEFT RIGHT DOUBLE ARROW WITH VERTICAL STROKE",
direction="on",
linebreak="al",
+ mathextensible="h",
unicodeslot=0x2904,
},
[0x2905]={
@@ -74641,6 +75996,7 @@ characters.data={
description="RIGHTWARDS TWO-HEADED ARROW FROM BAR",
direction="on",
linebreak="al",
+ mathextensible="r",
unicodeslot=0x2905,
},
[0x2906]={
@@ -74649,6 +76005,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="l",
mathname="Mapsfrom",
unicodeslot=0x2906,
},
@@ -74658,6 +76015,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="r",
mathname="Mapsto",
unicodeslot=0x2907,
},
@@ -74666,6 +76024,7 @@ characters.data={
description="DOWNWARDS ARROW WITH HORIZONTAL STROKE",
direction="on",
linebreak="al",
+ mathextensible="d",
unicodeslot=0x2908,
},
[0x2909]={
@@ -74673,6 +76032,7 @@ characters.data={
description="UPWARDS ARROW WITH HORIZONTAL STROKE",
direction="on",
linebreak="al",
+ mathextensible="u",
unicodeslot=0x2909,
},
[0x290A]={
@@ -74681,6 +76041,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="u",
mathname="Uuparrow",
unicodeslot=0x290A,
},
@@ -74690,6 +76051,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="d",
mathname="Ddownarrow",
unicodeslot=0x290B,
},
@@ -74699,6 +76061,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="l",
mathname="dashedleftarrow",
unicodeslot=0x290C,
},
@@ -74708,6 +76071,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="r",
mathname="dashedrightarrow",
unicodeslot=0x290D,
},
@@ -74716,6 +76080,7 @@ characters.data={
description="LEFTWARDS TRIPLE DASH ARROW",
direction="on",
linebreak="al",
+ mathextensible="l",
unicodeslot=0x290E,
},
[0x290F]={
@@ -74723,6 +76088,7 @@ characters.data={
description="RIGHTWARDS TRIPLE DASH ARROW",
direction="on",
linebreak="al",
+ mathextensible="r",
unicodeslot=0x290F,
},
[0x2910]={
@@ -74730,6 +76096,7 @@ characters.data={
description="RIGHTWARDS TWO-HEADED TRIPLE DASH ARROW",
direction="on",
linebreak="al",
+ mathextensible="r",
unicodeslot=0x2910,
},
[0x2911]={
@@ -74738,6 +76105,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="r",
mathname="dottedrightarrow",
unicodeslot=0x2911,
},
@@ -74746,6 +76114,7 @@ characters.data={
description="UPWARDS ARROW TO BAR",
direction="on",
linebreak="al",
+ mathextensible="u",
unicodeslot=0x2912,
},
[0x2913]={
@@ -74753,6 +76122,7 @@ characters.data={
description="DOWNWARDS ARROW TO BAR",
direction="on",
linebreak="al",
+ mathextensible="d",
unicodeslot=0x2913,
},
[0x2914]={
@@ -74760,6 +76130,7 @@ characters.data={
description="RIGHTWARDS ARROW WITH TAIL WITH VERTICAL STROKE",
direction="on",
linebreak="al",
+ mathextensible="r",
unicodeslot=0x2914,
},
[0x2915]={
@@ -74767,6 +76138,7 @@ characters.data={
description="RIGHTWARDS ARROW WITH TAIL WITH DOUBLE VERTICAL STROKE",
direction="on",
linebreak="al",
+ mathextensible="r",
unicodeslot=0x2915,
},
[0x2916]={
@@ -74775,6 +76147,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="r",
mathname="twoheadrightarrowtail",
unicodeslot=0x2916,
},
@@ -74784,6 +76157,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="relation",
+ mathextensible="r",
unicodeslot=0x2917,
},
[0x2918]={
@@ -74791,6 +76165,7 @@ characters.data={
description="RIGHTWARDS TWO-HEADED ARROW WITH TAIL WITH DOUBLE VERTICAL STROKE",
direction="on",
linebreak="al",
+ mathextensible="r",
unicodeslot=0x2918,
},
[0x2919]={
@@ -74798,6 +76173,7 @@ characters.data={
description="LEFTWARDS ARROW-TAIL",
direction="on",
linebreak="al",
+ mathextensible="l",
unicodeslot=0x2919,
},
[0x291A]={
@@ -74805,6 +76181,7 @@ characters.data={
description="RIGHTWARDS ARROW-TAIL",
direction="on",
linebreak="al",
+ mathextensible="r",
unicodeslot=0x291A,
},
[0x291B]={
@@ -74812,6 +76189,7 @@ characters.data={
description="LEFTWARDS DOUBLE ARROW-TAIL",
direction="on",
linebreak="al",
+ mathextensible="l",
unicodeslot=0x291B,
},
[0x291C]={
@@ -74819,6 +76197,7 @@ characters.data={
description="RIGHTWARDS DOUBLE ARROW-TAIL",
direction="on",
linebreak="al",
+ mathextensible="r",
unicodeslot=0x291C,
},
[0x291D]={
@@ -74826,6 +76205,7 @@ characters.data={
description="LEFTWARDS ARROW TO BLACK DIAMOND",
direction="on",
linebreak="al",
+ mathextensible="l",
unicodeslot=0x291D,
},
[0x291E]={
@@ -74833,6 +76213,7 @@ characters.data={
description="RIGHTWARDS ARROW TO BLACK DIAMOND",
direction="on",
linebreak="al",
+ mathextensible="r",
unicodeslot=0x291E,
},
[0x291F]={
@@ -74840,6 +76221,7 @@ characters.data={
description="LEFTWARDS ARROW FROM BAR TO BLACK DIAMOND",
direction="on",
linebreak="al",
+ mathextensible="l",
unicodeslot=0x291F,
},
[0x2920]={
@@ -74847,6 +76229,7 @@ characters.data={
description="RIGHTWARDS ARROW FROM BAR TO BLACK DIAMOND",
direction="on",
linebreak="al",
+ mathextensible="r",
unicodeslot=0x2920,
},
[0x2921]={
@@ -74992,6 +76375,7 @@ characters.data={
description="WAVE ARROW POINTING DIRECTLY RIGHT",
direction="on",
linebreak="al",
+ mathextensible="r",
unicodeslot=0x2933,
},
[0x2934]={
@@ -74999,20 +76383,31 @@ characters.data={
description="ARROW POINTING RIGHTWARDS THEN CURVING UPWARDS",
direction="on",
linebreak="al",
+ mathextensible="m",
unicodeslot=0x2934,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x2935]={
category="sm",
description="ARROW POINTING RIGHTWARDS THEN CURVING DOWNWARDS",
direction="on",
linebreak="al",
+ mathextensible="m",
unicodeslot=0x2935,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x2936]={
category="sm",
description="ARROW POINTING DOWNWARDS THEN CURVING LEFTWARDS",
direction="on",
linebreak="al",
+ mathextensible="m",
unicodeslot=0x2936,
},
[0x2937]={
@@ -75020,6 +76415,7 @@ characters.data={
description="ARROW POINTING DOWNWARDS THEN CURVING RIGHTWARDS",
direction="on",
linebreak="al",
+ mathextensible="m",
unicodeslot=0x2937,
},
[0x2938]={
@@ -75027,6 +76423,7 @@ characters.data={
description="RIGHT-SIDE ARC CLOCKWISE ARROW",
direction="on",
linebreak="al",
+ mathextensible="r",
unicodeslot=0x2938,
},
[0x2939]={
@@ -75034,6 +76431,7 @@ characters.data={
description="LEFT-SIDE ARC ANTICLOCKWISE ARROW",
direction="on",
linebreak="al",
+ mathextensible="l",
unicodeslot=0x2939,
},
[0x293A]={
@@ -75069,6 +76467,7 @@ characters.data={
description="LOWER RIGHT SEMICIRCULAR CLOCKWISE ARROW",
direction="on",
linebreak="al",
+ mathextensible="r",
unicodeslot=0x293E,
},
[0x293F]={
@@ -75076,6 +76475,7 @@ characters.data={
description="LOWER LEFT SEMICIRCULAR ANTICLOCKWISE ARROW",
direction="on",
linebreak="al",
+ mathextensible="l",
unicodeslot=0x293F,
},
[0x2940]={
@@ -75118,6 +76518,7 @@ characters.data={
description="RIGHTWARDS ARROW WITH PLUS BELOW",
direction="on",
linebreak="al",
+ mathextensible="r",
unicodeslot=0x2945,
},
[0x2946]={
@@ -75125,6 +76526,7 @@ characters.data={
description="LEFTWARDS ARROW WITH PLUS BELOW",
direction="on",
linebreak="al",
+ mathextensible="l",
unicodeslot=0x2946,
},
[0x2947]={
@@ -75146,6 +76548,7 @@ characters.data={
description="UPWARDS TWO-HEADED ARROW FROM SMALL CIRCLE",
direction="on",
linebreak="al",
+ mathextensible="u",
unicodeslot=0x2949,
},
[0x294A]={
@@ -75419,6 +76822,7 @@ characters.data={
description="RIGHT DOUBLE ARROW WITH ROUNDED HEAD",
direction="on",
linebreak="al",
+ mathextensible="r",
unicodeslot=0x2970,
},
[0x2971]={
@@ -76312,6 +77716,7 @@ characters.data={
description="BLACK DIAMOND WITH DOWN ARROW",
direction="on",
linebreak="al",
+ mathextensible="d",
unicodeslot=0x29EA,
},
[0x29EB]={
@@ -76326,6 +77731,7 @@ characters.data={
description="WHITE CIRCLE WITH DOWN ARROW",
direction="on",
linebreak="al",
+ mathextensible="d",
unicodeslot=0x29EC,
},
[0x29ED]={
@@ -76333,6 +77739,7 @@ characters.data={
description="BLACK CIRCLE WITH DOWN ARROW",
direction="on",
linebreak="al",
+ mathextensible="d",
unicodeslot=0x29ED,
},
[0x29EE]={
@@ -76649,6 +78056,7 @@ characters.data={
description="INTEGRAL WITH LEFTWARDS ARROW WITH HOOK",
direction="on",
linebreak="al",
+ mathextensible="l",
unicodeslot=0x2A17,
},
[0x2A18]={
@@ -78482,6 +79890,10 @@ characters.data={
direction="on",
linebreak="al",
unicodeslot=0x2B05,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x2B06]={
category="so",
@@ -78489,6 +79901,10 @@ characters.data={
direction="on",
linebreak="al",
unicodeslot=0x2B06,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x2B07]={
category="so",
@@ -78496,6 +79912,10 @@ characters.data={
direction="on",
linebreak="al",
unicodeslot=0x2B07,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x2B08]={
category="so",
@@ -78636,6 +80056,10 @@ characters.data={
direction="on",
linebreak="al",
unicodeslot=0x2B1B,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x2B1C]={
category="so",
@@ -78643,6 +80067,10 @@ characters.data={
direction="on",
linebreak="al",
unicodeslot=0x2B1C,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x2B1D]={
category="so",
@@ -78782,6 +80210,7 @@ characters.data={
description="LEFT ARROW WITH SMALL CIRCLE",
direction="on",
linebreak="al",
+ mathextensible="l",
unicodeslot=0x2B30,
},
[0x2B31]={
@@ -78789,6 +80218,7 @@ characters.data={
description="THREE LEFTWARDS ARROWS",
direction="on",
linebreak="al",
+ mathextensible="l",
unicodeslot=0x2B31,
},
[0x2B32]={
@@ -78796,6 +80226,7 @@ characters.data={
description="LEFT ARROW WITH CIRCLED PLUS",
direction="on",
linebreak="al",
+ mathextensible="l",
unicodeslot=0x2B32,
},
[0x2B33]={
@@ -78803,6 +80234,7 @@ characters.data={
description="LONG LEFTWARDS SQUIGGLE ARROW",
direction="on",
linebreak="al",
+ mathextensible="l",
unicodeslot=0x2B33,
},
[0x2B34]={
@@ -78810,6 +80242,7 @@ characters.data={
description="LEFTWARDS TWO-HEADED ARROW WITH VERTICAL STROKE",
direction="on",
linebreak="al",
+ mathextensible="l",
unicodeslot=0x2B34,
},
[0x2B35]={
@@ -78817,6 +80250,7 @@ characters.data={
description="LEFTWARDS TWO-HEADED ARROW WITH DOUBLE VERTICAL STROKE",
direction="on",
linebreak="al",
+ mathextensible="l",
unicodeslot=0x2B35,
},
[0x2B36]={
@@ -78824,6 +80258,7 @@ characters.data={
description="LEFTWARDS TWO-HEADED ARROW FROM BAR",
direction="on",
linebreak="al",
+ mathextensible="l",
unicodeslot=0x2B36,
},
[0x2B37]={
@@ -78831,6 +80266,7 @@ characters.data={
description="LEFTWARDS TWO-HEADED TRIPLE DASH ARROW",
direction="on",
linebreak="al",
+ mathextensible="l",
unicodeslot=0x2B37,
},
[0x2B38]={
@@ -78838,6 +80274,7 @@ characters.data={
description="LEFTWARDS ARROW WITH DOTTED STEM",
direction="on",
linebreak="al",
+ mathextensible="l",
unicodeslot=0x2B38,
},
[0x2B39]={
@@ -78845,6 +80282,7 @@ characters.data={
description="LEFTWARDS ARROW WITH TAIL WITH VERTICAL STROKE",
direction="on",
linebreak="al",
+ mathextensible="l",
unicodeslot=0x2B39,
},
[0x2B3A]={
@@ -78852,6 +80290,7 @@ characters.data={
description="LEFTWARDS ARROW WITH TAIL WITH DOUBLE VERTICAL STROKE",
direction="on",
linebreak="al",
+ mathextensible="l",
unicodeslot=0x2B3A,
},
[0x2B3B]={
@@ -78859,6 +80298,7 @@ characters.data={
description="LEFTWARDS TWO-HEADED ARROW WITH TAIL",
direction="on",
linebreak="al",
+ mathextensible="l",
unicodeslot=0x2B3B,
},
[0x2B3C]={
@@ -78866,6 +80306,7 @@ characters.data={
description="LEFTWARDS TWO-HEADED ARROW WITH TAIL WITH VERTICAL STROKE",
direction="on",
linebreak="al",
+ mathextensible="l",
unicodeslot=0x2B3C,
},
[0x2B3D]={
@@ -78873,6 +80314,7 @@ characters.data={
description="LEFTWARDS TWO-HEADED ARROW WITH TAIL WITH DOUBLE VERTICAL STROKE",
direction="on",
linebreak="al",
+ mathextensible="l",
unicodeslot=0x2B3D,
},
[0x2B3E]={
@@ -78887,6 +80329,7 @@ characters.data={
description="WAVE ARROW POINTING DIRECTLY LEFT",
direction="on",
linebreak="al",
+ mathextensible="l",
unicodeslot=0x2B3F,
},
[0x2B40]={
@@ -78986,6 +80429,10 @@ characters.data={
direction="on",
linebreak="al",
unicodeslot=0x2B50,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x2B51]={
category="so",
@@ -79022,6 +80469,10 @@ characters.data={
direction="on",
linebreak="ai",
unicodeslot=0x2B55,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x2B56]={
category="so",
@@ -80960,6 +82411,20 @@ characters.data={
linebreak="cm",
unicodeslot=0x2CF1,
},
+ [0x2CF2]={
+ category="lu",
+ description="COPTIC CAPITAL LETTER BOHAIRIC KHEI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2CF2,
+ },
+ [0x2CF3]={
+ category="ll",
+ description="COPTIC SMALL LETTER BOHAIRIC KHEI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2CF3,
+ },
[0x2CF9]={
category="po",
description="COPTIC OLD NUBIAN FULL STOP",
@@ -81313,6 +82778,20 @@ characters.data={
uccode=0x10C5,
unicodeslot=0x2D25,
},
+ [0x2D27]={
+ category="ll",
+ description="GEORGIAN SMALL LETTER YN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D27,
+ },
+ [0x2D2D]={
+ category="ll",
+ description="GEORGIAN SMALL LETTER AEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D2D,
+ },
[0x2D30]={
category="lo",
description="TIFINAGH LETTER YA",
@@ -81616,7 +83095,6 @@ characters.data={
},
[0x2D5B]={
category="lo",
- cjkwd="w",
description="TIFINAGH LETTER YASH",
direction="l",
linebreak="al",
@@ -81624,7 +83102,6 @@ characters.data={
},
[0x2D5C]={
category="lo",
- cjkwd="w",
description="TIFINAGH LETTER YAT",
direction="l",
linebreak="al",
@@ -81669,14 +83146,14 @@ characters.data={
category="lo",
description="TIFINAGH LETTER YAY",
direction="l",
- linebreak="id",
+ linebreak="al",
unicodeslot=0x2D62,
},
[0x2D63]={
category="lo",
description="TIFINAGH LETTER YAZ",
direction="l",
- linebreak="id",
+ linebreak="al",
unicodeslot=0x2D63,
},
[0x2D64]={
@@ -81693,6 +83170,20 @@ characters.data={
linebreak="al",
unicodeslot=0x2D65,
},
+ [0x2D66]={
+ category="lo",
+ description="TIFINAGH LETTER YE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D66,
+ },
+ [0x2D67]={
+ category="lo",
+ description="TIFINAGH LETTER YO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2D67,
+ },
[0x2D6F]={
category="lm",
description="TIFINAGH MODIFIER LETTER LABIALIZATION MARK",
@@ -81908,14 +83399,14 @@ characters.data={
category="lo",
description="ETHIOPIC SYLLABLE SSEE",
direction="l",
- linebreak="id",
+ linebreak="al",
unicodeslot=0x2DA4,
},
[0x2DA5]={
category="lo",
description="ETHIOPIC SYLLABLE SSE",
direction="l",
- linebreak="id",
+ linebreak="al",
unicodeslot=0x2DA5,
},
[0x2DA6]={
@@ -82004,6 +83495,7 @@ characters.data={
},
[0x2DB4]={
category="lo",
+ cjkwd="w",
description="ETHIOPIC SYLLABLE ZZEE",
direction="l",
linebreak="al",
@@ -82011,6 +83503,7 @@ characters.data={
},
[0x2DB5]={
category="lo",
+ cjkwd="w",
description="ETHIOPIC SYLLABLE ZZE",
direction="l",
linebreak="al",
@@ -82048,14 +83541,14 @@ characters.data={
category="lo",
description="ETHIOPIC SYLLABLE CCHAA",
direction="l",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x2DBB,
},
[0x2DBC]={
category="lo",
description="ETHIOPIC SYLLABLE CCHEE",
direction="l",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x2DBC,
},
[0x2DBD]={
@@ -82424,6 +83917,7 @@ characters.data={
},
[0x2DF6]={
category="mn",
+ cjkwd="w",
description="COMBINING CYRILLIC LETTER A",
direction="nsm",
linebreak="cm",
@@ -82431,6 +83925,7 @@ characters.data={
},
[0x2DF7]={
category="mn",
+ cjkwd="w",
description="COMBINING CYRILLIC LETTER IE",
direction="nsm",
linebreak="cm",
@@ -82475,14 +83970,14 @@ characters.data={
category="mn",
description="COMBINING CYRILLIC LETTER LITTLE YUS",
direction="nsm",
- linebreak="cm",
+ linebreak="id",
unicodeslot=0x2DFD,
},
[0x2DFE]={
category="mn",
description="COMBINING CYRILLIC LETTER BIG YUS",
direction="nsm",
- linebreak="cm",
+ linebreak="id",
unicodeslot=0x2DFE,
},
[0x2DFF]={
@@ -82862,6 +84357,76 @@ characters.data={
linebreak="ba",
unicodeslot=0x2E31,
},
+ [0x2E32]={
+ category="po",
+ description="TURNED COMMA",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2E32,
+ },
+ [0x2E33]={
+ category="po",
+ description="RAISED DOT",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x2E33,
+ },
+ [0x2E34]={
+ category="po",
+ description="RAISED COMMA",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x2E34,
+ },
+ [0x2E35]={
+ category="po",
+ description="TURNED SEMICOLON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2E35,
+ },
+ [0x2E36]={
+ category="po",
+ description="DAGGER WITH LEFT GUARD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2E36,
+ },
+ [0x2E37]={
+ category="po",
+ description="DAGGER WITH RIGHT GUARD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2E37,
+ },
+ [0x2E38]={
+ category="po",
+ description="TURNED DAGGER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2E38,
+ },
+ [0x2E39]={
+ category="po",
+ description="TOP HALF SECTION SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2E39,
+ },
+ [0x2E3A]={
+ category="pd",
+ description="TWO-EM DASH",
+ direction="on",
+ linebreak="b2",
+ unicodeslot=0x2E3A,
+ },
+ [0x2E3B]={
+ category="pd",
+ description="THREE-EM DASH",
+ direction="on",
+ linebreak="b2",
+ unicodeslot=0x2E3B,
+ },
[0x2E80]={
category="so",
cjkwd="w",
@@ -86237,7 +87802,7 @@ characters.data={
category="mn",
cjkwd="w",
description="HANGUL SINGLE DOT TONE MARK",
- direction="nsm",
+ direction="l",
linebreak="cm",
unicodeslot=0x302E,
},
@@ -86245,7 +87810,7 @@ characters.data={
category="mn",
cjkwd="w",
description="HANGUL DOUBLE DOT TONE MARK",
- direction="nsm",
+ direction="l",
linebreak="cm",
unicodeslot=0x302F,
},
@@ -86365,6 +87930,10 @@ characters.data={
direction="on",
linebreak="id",
unicodeslot=0x303D,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x303E]={
category="so",
@@ -86388,7 +87957,7 @@ characters.data={
cjkwd="w",
description="HIRAGANA LETTER SMALL A",
direction="l",
- linebreak="ns",
+ linebreak="cj",
unicodeslot=0x3041,
},
[0x3042]={
@@ -86406,7 +87975,7 @@ characters.data={
cjkwd="w",
description="HIRAGANA LETTER SMALL I",
direction="l",
- linebreak="ns",
+ linebreak="cj",
unicodeslot=0x3043,
},
[0x3044]={
@@ -86424,7 +87993,7 @@ characters.data={
cjkwd="w",
description="HIRAGANA LETTER SMALL U",
direction="l",
- linebreak="ns",
+ linebreak="cj",
unicodeslot=0x3045,
},
[0x3046]={
@@ -86442,7 +88011,7 @@ characters.data={
cjkwd="w",
description="HIRAGANA LETTER SMALL E",
direction="l",
- linebreak="ns",
+ linebreak="cj",
unicodeslot=0x3047,
},
[0x3048]={
@@ -86460,7 +88029,7 @@ characters.data={
cjkwd="w",
description="HIRAGANA LETTER SMALL O",
direction="l",
- linebreak="ns",
+ linebreak="cj",
unicodeslot=0x3049,
},
[0x304A]={
@@ -86706,7 +88275,7 @@ characters.data={
cjkwd="w",
description="HIRAGANA LETTER SMALL TU",
direction="l",
- linebreak="ns",
+ linebreak="cj",
unicodeslot=0x3063,
},
[0x3064]={
@@ -87007,7 +88576,7 @@ characters.data={
cjkwd="w",
description="HIRAGANA LETTER SMALL YA",
direction="l",
- linebreak="ns",
+ linebreak="cj",
unicodeslot=0x3083,
},
[0x3084]={
@@ -87025,7 +88594,7 @@ characters.data={
cjkwd="w",
description="HIRAGANA LETTER SMALL YU",
direction="l",
- linebreak="ns",
+ linebreak="cj",
unicodeslot=0x3085,
},
[0x3086]={
@@ -87043,7 +88612,7 @@ characters.data={
cjkwd="w",
description="HIRAGANA LETTER SMALL YO",
direction="l",
- linebreak="ns",
+ linebreak="cj",
unicodeslot=0x3087,
},
[0x3088]={
@@ -87106,7 +88675,7 @@ characters.data={
cjkwd="w",
description="HIRAGANA LETTER SMALL WA",
direction="l",
- linebreak="ns",
+ linebreak="cj",
unicodeslot=0x308E,
},
[0x308F]={
@@ -87169,7 +88738,7 @@ characters.data={
cjkwd="w",
description="HIRAGANA LETTER SMALL KA",
direction="l",
- linebreak="ns",
+ linebreak="cj",
unicodeslot=0x3095,
},
[0x3096]={
@@ -87177,7 +88746,7 @@ characters.data={
cjkwd="w",
description="HIRAGANA LETTER SMALL KE",
direction="l",
- linebreak="ns",
+ linebreak="cj",
unicodeslot=0x3096,
},
[0x3099]={
@@ -87258,7 +88827,7 @@ characters.data={
cjkwd="w",
description="KATAKANA LETTER SMALL A",
direction="l",
- linebreak="ns",
+ linebreak="cj",
unicodeslot=0x30A1,
},
[0x30A2]={
@@ -87276,7 +88845,7 @@ characters.data={
cjkwd="w",
description="KATAKANA LETTER SMALL I",
direction="l",
- linebreak="ns",
+ linebreak="cj",
unicodeslot=0x30A3,
},
[0x30A4]={
@@ -87294,7 +88863,7 @@ characters.data={
cjkwd="w",
description="KATAKANA LETTER SMALL U",
direction="l",
- linebreak="ns",
+ linebreak="cj",
unicodeslot=0x30A5,
},
[0x30A6]={
@@ -87312,7 +88881,7 @@ characters.data={
cjkwd="w",
description="KATAKANA LETTER SMALL E",
direction="l",
- linebreak="ns",
+ linebreak="cj",
unicodeslot=0x30A7,
},
[0x30A8]={
@@ -87330,7 +88899,7 @@ characters.data={
cjkwd="w",
description="KATAKANA LETTER SMALL O",
direction="l",
- linebreak="ns",
+ linebreak="cj",
unicodeslot=0x30A9,
},
[0x30AA]={
@@ -87576,7 +89145,7 @@ characters.data={
cjkwd="w",
description="KATAKANA LETTER SMALL TU",
direction="l",
- linebreak="ns",
+ linebreak="cj",
unicodeslot=0x30C3,
},
[0x30C4]={
@@ -87877,7 +89446,7 @@ characters.data={
cjkwd="w",
description="KATAKANA LETTER SMALL YA",
direction="l",
- linebreak="ns",
+ linebreak="cj",
unicodeslot=0x30E3,
},
[0x30E4]={
@@ -87895,7 +89464,7 @@ characters.data={
cjkwd="w",
description="KATAKANA LETTER SMALL YU",
direction="l",
- linebreak="ns",
+ linebreak="cj",
unicodeslot=0x30E5,
},
[0x30E6]={
@@ -87913,7 +89482,7 @@ characters.data={
cjkwd="w",
description="KATAKANA LETTER SMALL YO",
direction="l",
- linebreak="ns",
+ linebreak="cj",
unicodeslot=0x30E7,
},
[0x30E8]={
@@ -87976,7 +89545,7 @@ characters.data={
cjkwd="w",
description="KATAKANA LETTER SMALL WA",
direction="l",
- linebreak="ns",
+ linebreak="cj",
unicodeslot=0x30EE,
},
[0x30EF]={
@@ -88040,7 +89609,7 @@ characters.data={
cjkwd="w",
description="KATAKANA LETTER SMALL KA",
direction="l",
- linebreak="ns",
+ linebreak="cj",
unicodeslot=0x30F5,
},
[0x30F6]={
@@ -88049,7 +89618,7 @@ characters.data={
cjkwd="w",
description="KATAKANA LETTER SMALL KE",
direction="l",
- linebreak="ns",
+ linebreak="cj",
unicodeslot=0x30F6,
},
[0x30F7]={
@@ -88107,7 +89676,7 @@ characters.data={
cjkwd="w",
description="KATAKANA-HIRAGANA PROLONGED SOUND MARK",
direction="l",
- linebreak="ns",
+ linebreak="cj",
unicodeslot=0x30FC,
},
[0x30FD]={
@@ -90094,7 +91663,7 @@ characters.data={
cjkwd="w",
description="KATAKANA LETTER SMALL KU",
direction="l",
- linebreak="ns",
+ linebreak="cj",
unicodeslot=0x31F0,
},
[0x31F1]={
@@ -90102,7 +91671,7 @@ characters.data={
cjkwd="w",
description="KATAKANA LETTER SMALL SI",
direction="l",
- linebreak="ns",
+ linebreak="cj",
unicodeslot=0x31F1,
},
[0x31F2]={
@@ -90110,7 +91679,7 @@ characters.data={
cjkwd="w",
description="KATAKANA LETTER SMALL SU",
direction="l",
- linebreak="ns",
+ linebreak="cj",
unicodeslot=0x31F2,
},
[0x31F3]={
@@ -90118,7 +91687,7 @@ characters.data={
cjkwd="w",
description="KATAKANA LETTER SMALL TO",
direction="l",
- linebreak="ns",
+ linebreak="cj",
unicodeslot=0x31F3,
},
[0x31F4]={
@@ -90126,7 +91695,7 @@ characters.data={
cjkwd="w",
description="KATAKANA LETTER SMALL NU",
direction="l",
- linebreak="ns",
+ linebreak="cj",
unicodeslot=0x31F4,
},
[0x31F5]={
@@ -90134,7 +91703,7 @@ characters.data={
cjkwd="w",
description="KATAKANA LETTER SMALL HA",
direction="l",
- linebreak="ns",
+ linebreak="cj",
unicodeslot=0x31F5,
},
[0x31F6]={
@@ -90142,7 +91711,7 @@ characters.data={
cjkwd="w",
description="KATAKANA LETTER SMALL HI",
direction="l",
- linebreak="ns",
+ linebreak="cj",
unicodeslot=0x31F6,
},
[0x31F7]={
@@ -90150,7 +91719,7 @@ characters.data={
cjkwd="w",
description="KATAKANA LETTER SMALL HU",
direction="l",
- linebreak="ns",
+ linebreak="cj",
unicodeslot=0x31F7,
},
[0x31F8]={
@@ -90158,7 +91727,7 @@ characters.data={
cjkwd="w",
description="KATAKANA LETTER SMALL HE",
direction="l",
- linebreak="ns",
+ linebreak="cj",
unicodeslot=0x31F8,
},
[0x31F9]={
@@ -90166,7 +91735,7 @@ characters.data={
cjkwd="w",
description="KATAKANA LETTER SMALL HO",
direction="l",
- linebreak="ns",
+ linebreak="cj",
unicodeslot=0x31F9,
},
[0x31FA]={
@@ -90174,7 +91743,7 @@ characters.data={
cjkwd="w",
description="KATAKANA LETTER SMALL MU",
direction="l",
- linebreak="ns",
+ linebreak="cj",
unicodeslot=0x31FA,
},
[0x31FB]={
@@ -90182,7 +91751,7 @@ characters.data={
cjkwd="w",
description="KATAKANA LETTER SMALL RA",
direction="l",
- linebreak="ns",
+ linebreak="cj",
unicodeslot=0x31FB,
},
[0x31FC]={
@@ -90190,7 +91759,7 @@ characters.data={
cjkwd="w",
description="KATAKANA LETTER SMALL RI",
direction="l",
- linebreak="ns",
+ linebreak="cj",
unicodeslot=0x31FC,
},
[0x31FD]={
@@ -90198,7 +91767,7 @@ characters.data={
cjkwd="w",
description="KATAKANA LETTER SMALL RU",
direction="l",
- linebreak="ns",
+ linebreak="cj",
unicodeslot=0x31FD,
},
[0x31FE]={
@@ -90206,7 +91775,7 @@ characters.data={
cjkwd="w",
description="KATAKANA LETTER SMALL RE",
direction="l",
- linebreak="ns",
+ linebreak="cj",
unicodeslot=0x31FE,
},
[0x31FF]={
@@ -90214,7 +91783,7 @@ characters.data={
cjkwd="w",
description="KATAKANA LETTER SMALL RO",
direction="l",
- linebreak="ns",
+ linebreak="cj",
unicodeslot=0x31FF,
},
[0x3200]={
@@ -91668,6 +93237,10 @@ characters.data={
linebreak="id",
specials={ "circle", 0x795D },
unicodeslot=0x3297,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x3298]={
adobename="ideographiclaborcircle",
@@ -91688,6 +93261,10 @@ characters.data={
linebreak="id",
specials={ "circle", 0x79D8 },
unicodeslot=0x3299,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x329A]={
category="so",
@@ -108042,6 +109619,62 @@ characters.data={
linebreak="al",
unicodeslot=0xA673,
},
+ [0xA674]={
+ category="mn",
+ description="COMBINING CYRILLIC LETTER UKRAINIAN IE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA674,
+ },
+ [0xA675]={
+ category="mn",
+ description="COMBINING CYRILLIC LETTER I",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA675,
+ },
+ [0xA676]={
+ category="mn",
+ description="COMBINING CYRILLIC LETTER YI",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA676,
+ },
+ [0xA677]={
+ category="mn",
+ description="COMBINING CYRILLIC LETTER U",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA677,
+ },
+ [0xA678]={
+ category="mn",
+ description="COMBINING CYRILLIC LETTER HARD SIGN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA678,
+ },
+ [0xA679]={
+ category="mn",
+ description="COMBINING CYRILLIC LETTER YERU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA679,
+ },
+ [0xA67A]={
+ category="mn",
+ description="COMBINING CYRILLIC LETTER SOFT SIGN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA67A,
+ },
+ [0xA67B]={
+ category="mn",
+ description="COMBINING CYRILLIC LETTER OMEGA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA67B,
+ },
[0xA67C]={
category="mn",
description="COMBINING CYRILLIC KAVYKA",
@@ -108238,6 +109871,13 @@ characters.data={
linebreak="al",
unicodeslot=0xA697,
},
+ [0xA69F]={
+ category="mn",
+ description="COMBINING CYRILLIC LETTER IOTIFIED E",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA69F,
+ },
[0xA6A0]={
category="lo",
description="BAMUM LETTER A",
@@ -109870,6 +111510,20 @@ characters.data={
linebreak="al",
unicodeslot=0xA791,
},
+ [0xA792]={
+ category="lu",
+ description="LATIN CAPITAL LETTER C WITH BAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA792,
+ },
+ [0xA793]={
+ category="ll",
+ description="LATIN SMALL LETTER C WITH BAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA793,
+ },
[0xA7A0]={
category="lu",
description="LATIN CAPITAL LETTER G WITH OBLIQUE STROKE",
@@ -109940,6 +111594,29 @@ characters.data={
linebreak="al",
unicodeslot=0xA7A9,
},
+ [0xA7AA]={
+ category="lu",
+ description="LATIN CAPITAL LETTER H WITH HOOK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA7AA,
+ },
+ [0xA7F8]={
+ category="lm",
+ description="MODIFIER LETTER CAPITAL H WITH STROKE",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x0126 },
+ unicodeslot=0xA7F8,
+ },
+ [0xA7F9]={
+ category="lm",
+ description="MODIFIER LETTER SMALL LIGATURE OE",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x0153 },
+ unicodeslot=0xA7F9,
+ },
[0xA7FA]={
category="ll",
description="LATIN LETTER SMALL CAPITAL TURNED M",
@@ -114278,6 +115955,167 @@ characters.data={
linebreak="sa",
unicodeslot=0xAADF,
},
+ [0xAAE0]={
+ category="lo",
+ description="MEETEI MAYEK LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAAE0,
+ },
+ [0xAAE1]={
+ category="lo",
+ description="MEETEI MAYEK LETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAAE1,
+ },
+ [0xAAE2]={
+ category="lo",
+ description="MEETEI MAYEK LETTER CHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAAE2,
+ },
+ [0xAAE3]={
+ category="lo",
+ description="MEETEI MAYEK LETTER NYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAAE3,
+ },
+ [0xAAE4]={
+ category="lo",
+ description="MEETEI MAYEK LETTER TTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAAE4,
+ },
+ [0xAAE5]={
+ category="lo",
+ description="MEETEI MAYEK LETTER TTHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAAE5,
+ },
+ [0xAAE6]={
+ category="lo",
+ description="MEETEI MAYEK LETTER DDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAAE6,
+ },
+ [0xAAE7]={
+ category="lo",
+ description="MEETEI MAYEK LETTER DDHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAAE7,
+ },
+ [0xAAE8]={
+ category="lo",
+ description="MEETEI MAYEK LETTER NNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAAE8,
+ },
+ [0xAAE9]={
+ category="lo",
+ description="MEETEI MAYEK LETTER SHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAAE9,
+ },
+ [0xAAEA]={
+ category="lo",
+ description="MEETEI MAYEK LETTER SSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAAEA,
+ },
+ [0xAAEB]={
+ category="mc",
+ description="MEETEI MAYEK VOWEL SIGN II",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xAAEB,
+ },
+ [0xAAEC]={
+ category="mn",
+ description="MEETEI MAYEK VOWEL SIGN UU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xAAEC,
+ },
+ [0xAAED]={
+ category="mn",
+ description="MEETEI MAYEK VOWEL SIGN AAI",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xAAED,
+ },
+ [0xAAEE]={
+ category="mc",
+ description="MEETEI MAYEK VOWEL SIGN AU",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xAAEE,
+ },
+ [0xAAEF]={
+ category="mc",
+ description="MEETEI MAYEK VOWEL SIGN AAU",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xAAEF,
+ },
+ [0xAAF0]={
+ category="po",
+ description="MEETEI MAYEK CHEIKHAN",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0xAAF0,
+ },
+ [0xAAF1]={
+ category="po",
+ description="MEETEI MAYEK AHANG KHUDAM",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0xAAF1,
+ },
+ [0xAAF2]={
+ category="lo",
+ description="MEETEI MAYEK ANJI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAAF2,
+ },
+ [0xAAF3]={
+ category="lm",
+ description="MEETEI MAYEK SYLLABLE REPETITION MARK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAAF3,
+ },
+ [0xAAF4]={
+ category="lm",
+ description="MEETEI MAYEK WORD REPETITION MARK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAAF4,
+ },
+ [0xAAF5]={
+ category="mc",
+ description="MEETEI MAYEK VOWEL SIGN VISARGA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xAAF5,
+ },
+ [0xAAF6]={
+ category="mn",
+ description="MEETEI MAYEK VIRAMA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xAAF6,
+ },
[0xAB01]={
category="lo",
description="ETHIOPIC SYLLABLE TTHU",
@@ -114896,7 +116734,6 @@ characters.data={
},
[0xD7B0]={
category="lo",
- cjkwd="w",
description="HANGUL JUNGSEONG O-YEO",
direction="l",
linebreak="jv",
@@ -114904,7 +116741,6 @@ characters.data={
},
[0xD7B1]={
category="lo",
- cjkwd="w",
description="HANGUL JUNGSEONG O-O-I",
direction="l",
linebreak="jv",
@@ -114912,7 +116748,6 @@ characters.data={
},
[0xD7B2]={
category="lo",
- cjkwd="w",
description="HANGUL JUNGSEONG YO-A",
direction="l",
linebreak="jv",
@@ -114920,7 +116755,6 @@ characters.data={
},
[0xD7B3]={
category="lo",
- cjkwd="w",
description="HANGUL JUNGSEONG YO-AE",
direction="l",
linebreak="jv",
@@ -114928,7 +116762,6 @@ characters.data={
},
[0xD7B4]={
category="lo",
- cjkwd="w",
description="HANGUL JUNGSEONG YO-EO",
direction="l",
linebreak="jv",
@@ -114936,7 +116769,6 @@ characters.data={
},
[0xD7B5]={
category="lo",
- cjkwd="w",
description="HANGUL JUNGSEONG U-YEO",
direction="l",
linebreak="jv",
@@ -114944,7 +116776,6 @@ characters.data={
},
[0xD7B6]={
category="lo",
- cjkwd="w",
description="HANGUL JUNGSEONG U-I-I",
direction="l",
linebreak="jv",
@@ -114952,7 +116783,6 @@ characters.data={
},
[0xD7B7]={
category="lo",
- cjkwd="w",
description="HANGUL JUNGSEONG YU-AE",
direction="l",
linebreak="jv",
@@ -114960,7 +116790,6 @@ characters.data={
},
[0xD7B8]={
category="lo",
- cjkwd="w",
description="HANGUL JUNGSEONG YU-O",
direction="l",
linebreak="jv",
@@ -114968,7 +116797,6 @@ characters.data={
},
[0xD7B9]={
category="lo",
- cjkwd="w",
description="HANGUL JUNGSEONG EU-A",
direction="l",
linebreak="jv",
@@ -114976,7 +116804,6 @@ characters.data={
},
[0xD7BA]={
category="lo",
- cjkwd="w",
description="HANGUL JUNGSEONG EU-EO",
direction="l",
linebreak="jv",
@@ -114984,7 +116811,6 @@ characters.data={
},
[0xD7BB]={
category="lo",
- cjkwd="w",
description="HANGUL JUNGSEONG EU-E",
direction="l",
linebreak="jv",
@@ -114992,7 +116818,6 @@ characters.data={
},
[0xD7BC]={
category="lo",
- cjkwd="w",
description="HANGUL JUNGSEONG EU-O",
direction="l",
linebreak="jv",
@@ -115000,7 +116825,6 @@ characters.data={
},
[0xD7BD]={
category="lo",
- cjkwd="w",
description="HANGUL JUNGSEONG I-YA-O",
direction="l",
linebreak="jv",
@@ -115008,7 +116832,6 @@ characters.data={
},
[0xD7BE]={
category="lo",
- cjkwd="w",
description="HANGUL JUNGSEONG I-YAE",
direction="l",
linebreak="jv",
@@ -115016,7 +116839,6 @@ characters.data={
},
[0xD7BF]={
category="lo",
- cjkwd="w",
description="HANGUL JUNGSEONG I-YEO",
direction="l",
linebreak="jv",
@@ -115024,7 +116846,6 @@ characters.data={
},
[0xD7C0]={
category="lo",
- cjkwd="w",
description="HANGUL JUNGSEONG I-YE",
direction="l",
linebreak="jv",
@@ -115032,7 +116853,6 @@ characters.data={
},
[0xD7C1]={
category="lo",
- cjkwd="w",
description="HANGUL JUNGSEONG I-O-I",
direction="l",
linebreak="jv",
@@ -115040,7 +116860,6 @@ characters.data={
},
[0xD7C2]={
category="lo",
- cjkwd="w",
description="HANGUL JUNGSEONG I-YO",
direction="l",
linebreak="jv",
@@ -115048,7 +116867,6 @@ characters.data={
},
[0xD7C3]={
category="lo",
- cjkwd="w",
description="HANGUL JUNGSEONG I-YU",
direction="l",
linebreak="jv",
@@ -115056,7 +116874,6 @@ characters.data={
},
[0xD7C4]={
category="lo",
- cjkwd="w",
description="HANGUL JUNGSEONG I-I",
direction="l",
linebreak="jv",
@@ -115064,7 +116881,6 @@ characters.data={
},
[0xD7C5]={
category="lo",
- cjkwd="w",
description="HANGUL JUNGSEONG ARAEA-A",
direction="l",
linebreak="jv",
@@ -115072,7 +116888,6 @@ characters.data={
},
[0xD7C6]={
category="lo",
- cjkwd="w",
description="HANGUL JUNGSEONG ARAEA-E",
direction="l",
linebreak="jv",
@@ -115080,7 +116895,6 @@ characters.data={
},
[0xD7CB]={
category="lo",
- cjkwd="w",
description="HANGUL JONGSEONG NIEUN-RIEUL",
direction="l",
linebreak="jt",
@@ -115088,7 +116902,6 @@ characters.data={
},
[0xD7CC]={
category="lo",
- cjkwd="w",
description="HANGUL JONGSEONG NIEUN-CHIEUCH",
direction="l",
linebreak="jt",
@@ -115096,7 +116909,6 @@ characters.data={
},
[0xD7CD]={
category="lo",
- cjkwd="w",
description="HANGUL JONGSEONG SSANGTIKEUT",
direction="l",
linebreak="jt",
@@ -115104,7 +116916,6 @@ characters.data={
},
[0xD7CE]={
category="lo",
- cjkwd="w",
description="HANGUL JONGSEONG SSANGTIKEUT-PIEUP",
direction="l",
linebreak="jt",
@@ -115112,7 +116923,6 @@ characters.data={
},
[0xD7CF]={
category="lo",
- cjkwd="w",
description="HANGUL JONGSEONG TIKEUT-PIEUP",
direction="l",
linebreak="jt",
@@ -115120,7 +116930,6 @@ characters.data={
},
[0xD7D0]={
category="lo",
- cjkwd="w",
description="HANGUL JONGSEONG TIKEUT-SIOS",
direction="l",
linebreak="jt",
@@ -115128,7 +116937,6 @@ characters.data={
},
[0xD7D1]={
category="lo",
- cjkwd="w",
description="HANGUL JONGSEONG TIKEUT-SIOS-KIYEOK",
direction="l",
linebreak="jt",
@@ -115136,7 +116944,6 @@ characters.data={
},
[0xD7D2]={
category="lo",
- cjkwd="w",
description="HANGUL JONGSEONG TIKEUT-CIEUC",
direction="l",
linebreak="jt",
@@ -115144,7 +116951,6 @@ characters.data={
},
[0xD7D3]={
category="lo",
- cjkwd="w",
description="HANGUL JONGSEONG TIKEUT-CHIEUCH",
direction="l",
linebreak="jt",
@@ -115152,7 +116958,6 @@ characters.data={
},
[0xD7D4]={
category="lo",
- cjkwd="w",
description="HANGUL JONGSEONG TIKEUT-THIEUTH",
direction="l",
linebreak="jt",
@@ -115160,7 +116965,6 @@ characters.data={
},
[0xD7D5]={
category="lo",
- cjkwd="w",
description="HANGUL JONGSEONG RIEUL-SSANGKIYEOK",
direction="l",
linebreak="jt",
@@ -115168,7 +116972,6 @@ characters.data={
},
[0xD7D6]={
category="lo",
- cjkwd="w",
description="HANGUL JONGSEONG RIEUL-KIYEOK-HIEUH",
direction="l",
linebreak="jt",
@@ -115176,7 +116979,6 @@ characters.data={
},
[0xD7D7]={
category="lo",
- cjkwd="w",
description="HANGUL JONGSEONG SSANGRIEUL-KHIEUKH",
direction="l",
linebreak="jt",
@@ -115184,7 +116986,6 @@ characters.data={
},
[0xD7D8]={
category="lo",
- cjkwd="w",
description="HANGUL JONGSEONG RIEUL-MIEUM-HIEUH",
direction="l",
linebreak="jt",
@@ -115192,7 +116993,6 @@ characters.data={
},
[0xD7D9]={
category="lo",
- cjkwd="w",
description="HANGUL JONGSEONG RIEUL-PIEUP-TIKEUT",
direction="l",
linebreak="jt",
@@ -115200,7 +117000,6 @@ characters.data={
},
[0xD7DA]={
category="lo",
- cjkwd="w",
description="HANGUL JONGSEONG RIEUL-PIEUP-PHIEUPH",
direction="l",
linebreak="jt",
@@ -115208,7 +117007,6 @@ characters.data={
},
[0xD7DB]={
category="lo",
- cjkwd="w",
description="HANGUL JONGSEONG RIEUL-YESIEUNG",
direction="l",
linebreak="jt",
@@ -115216,7 +117014,6 @@ characters.data={
},
[0xD7DC]={
category="lo",
- cjkwd="w",
description="HANGUL JONGSEONG RIEUL-YEORINHIEUH-HIEUH",
direction="l",
linebreak="jt",
@@ -115224,7 +117021,6 @@ characters.data={
},
[0xD7DD]={
category="lo",
- cjkwd="w",
description="HANGUL JONGSEONG KAPYEOUNRIEUL",
direction="l",
linebreak="jt",
@@ -115232,7 +117028,6 @@ characters.data={
},
[0xD7DE]={
category="lo",
- cjkwd="w",
description="HANGUL JONGSEONG MIEUM-NIEUN",
direction="l",
linebreak="jt",
@@ -115240,7 +117035,6 @@ characters.data={
},
[0xD7DF]={
category="lo",
- cjkwd="w",
description="HANGUL JONGSEONG MIEUM-SSANGNIEUN",
direction="l",
linebreak="jt",
@@ -115248,7 +117042,6 @@ characters.data={
},
[0xD7E0]={
category="lo",
- cjkwd="w",
description="HANGUL JONGSEONG SSANGMIEUM",
direction="l",
linebreak="jt",
@@ -115256,7 +117049,6 @@ characters.data={
},
[0xD7E1]={
category="lo",
- cjkwd="w",
description="HANGUL JONGSEONG MIEUM-PIEUP-SIOS",
direction="l",
linebreak="jt",
@@ -115264,7 +117056,6 @@ characters.data={
},
[0xD7E2]={
category="lo",
- cjkwd="w",
description="HANGUL JONGSEONG MIEUM-CIEUC",
direction="l",
linebreak="jt",
@@ -115272,7 +117063,6 @@ characters.data={
},
[0xD7E3]={
category="lo",
- cjkwd="w",
description="HANGUL JONGSEONG PIEUP-TIKEUT",
direction="l",
linebreak="jt",
@@ -115280,7 +117070,6 @@ characters.data={
},
[0xD7E4]={
category="lo",
- cjkwd="w",
description="HANGUL JONGSEONG PIEUP-RIEUL-PHIEUPH",
direction="l",
linebreak="jt",
@@ -115288,7 +117077,6 @@ characters.data={
},
[0xD7E5]={
category="lo",
- cjkwd="w",
description="HANGUL JONGSEONG PIEUP-MIEUM",
direction="l",
linebreak="jt",
@@ -115296,7 +117084,6 @@ characters.data={
},
[0xD7E6]={
category="lo",
- cjkwd="w",
description="HANGUL JONGSEONG SSANGPIEUP",
direction="l",
linebreak="jt",
@@ -115304,7 +117091,6 @@ characters.data={
},
[0xD7E7]={
category="lo",
- cjkwd="w",
description="HANGUL JONGSEONG PIEUP-SIOS-TIKEUT",
direction="l",
linebreak="jt",
@@ -115312,7 +117098,6 @@ characters.data={
},
[0xD7E8]={
category="lo",
- cjkwd="w",
description="HANGUL JONGSEONG PIEUP-CIEUC",
direction="l",
linebreak="jt",
@@ -115320,7 +117105,6 @@ characters.data={
},
[0xD7E9]={
category="lo",
- cjkwd="w",
description="HANGUL JONGSEONG PIEUP-CHIEUCH",
direction="l",
linebreak="jt",
@@ -115328,7 +117112,6 @@ characters.data={
},
[0xD7EA]={
category="lo",
- cjkwd="w",
description="HANGUL JONGSEONG SIOS-MIEUM",
direction="l",
linebreak="jt",
@@ -115336,7 +117119,6 @@ characters.data={
},
[0xD7EB]={
category="lo",
- cjkwd="w",
description="HANGUL JONGSEONG SIOS-KAPYEOUNPIEUP",
direction="l",
linebreak="jt",
@@ -115344,7 +117126,6 @@ characters.data={
},
[0xD7EC]={
category="lo",
- cjkwd="w",
description="HANGUL JONGSEONG SSANGSIOS-KIYEOK",
direction="l",
linebreak="jt",
@@ -115352,7 +117133,6 @@ characters.data={
},
[0xD7ED]={
category="lo",
- cjkwd="w",
description="HANGUL JONGSEONG SSANGSIOS-TIKEUT",
direction="l",
linebreak="jt",
@@ -115360,7 +117140,6 @@ characters.data={
},
[0xD7EE]={
category="lo",
- cjkwd="w",
description="HANGUL JONGSEONG SIOS-PANSIOS",
direction="l",
linebreak="jt",
@@ -115368,7 +117147,6 @@ characters.data={
},
[0xD7EF]={
category="lo",
- cjkwd="w",
description="HANGUL JONGSEONG SIOS-CIEUC",
direction="l",
linebreak="jt",
@@ -115376,7 +117154,6 @@ characters.data={
},
[0xD7F0]={
category="lo",
- cjkwd="w",
description="HANGUL JONGSEONG SIOS-CHIEUCH",
direction="l",
linebreak="jt",
@@ -115384,7 +117161,6 @@ characters.data={
},
[0xD7F1]={
category="lo",
- cjkwd="w",
description="HANGUL JONGSEONG SIOS-THIEUTH",
direction="l",
linebreak="jt",
@@ -115392,7 +117168,6 @@ characters.data={
},
[0xD7F2]={
category="lo",
- cjkwd="w",
description="HANGUL JONGSEONG SIOS-HIEUH",
direction="l",
linebreak="jt",
@@ -115400,7 +117175,6 @@ characters.data={
},
[0xD7F3]={
category="lo",
- cjkwd="w",
description="HANGUL JONGSEONG PANSIOS-PIEUP",
direction="l",
linebreak="jt",
@@ -115408,7 +117182,6 @@ characters.data={
},
[0xD7F4]={
category="lo",
- cjkwd="w",
description="HANGUL JONGSEONG PANSIOS-KAPYEOUNPIEUP",
direction="l",
linebreak="jt",
@@ -115416,7 +117189,6 @@ characters.data={
},
[0xD7F5]={
category="lo",
- cjkwd="w",
description="HANGUL JONGSEONG YESIEUNG-MIEUM",
direction="l",
linebreak="jt",
@@ -115424,7 +117196,6 @@ characters.data={
},
[0xD7F6]={
category="lo",
- cjkwd="w",
description="HANGUL JONGSEONG YESIEUNG-HIEUH",
direction="l",
linebreak="jt",
@@ -115432,7 +117203,6 @@ characters.data={
},
[0xD7F7]={
category="lo",
- cjkwd="w",
description="HANGUL JONGSEONG CIEUC-PIEUP",
direction="l",
linebreak="jt",
@@ -115440,7 +117210,6 @@ characters.data={
},
[0xD7F8]={
category="lo",
- cjkwd="w",
description="HANGUL JONGSEONG CIEUC-SSANGPIEUP",
direction="l",
linebreak="jt",
@@ -115448,7 +117217,6 @@ characters.data={
},
[0xD7F9]={
category="lo",
- cjkwd="w",
description="HANGUL JONGSEONG SSANGCIEUC",
direction="l",
linebreak="jt",
@@ -115456,7 +117224,6 @@ characters.data={
},
[0xD7FA]={
category="lo",
- cjkwd="w",
description="HANGUL JONGSEONG PHIEUPH-SIOS",
direction="l",
linebreak="jt",
@@ -115464,7 +117231,6 @@ characters.data={
},
[0xD7FB]={
category="lo",
- cjkwd="w",
description="HANGUL JONGSEONG PHIEUPH-THIEUTH",
direction="l",
linebreak="jt",
@@ -118233,6 +119999,24 @@ characters.data={
specials={ "char", 0x9DB4 },
unicodeslot=0xFA2D,
},
+ [0xFA2E]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA2E",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x90DE },
+ unicodeslot=0xFA2E,
+ },
+ [0xFA2F]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA2F",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x96B7 },
+ unicodeslot=0xFA2F,
+ },
[0xFA30]={
category="lo",
cjkwd="w",
@@ -119861,7 +121645,7 @@ characters.data={
category="lo",
description="HEBREW LETTER YOD WITH HIRIQ",
direction="r",
- linebreak="al",
+ linebreak="hl",
shcode=0x05D9,
specials={ "char", 0x05D9, 0x05B4 },
unicodeslot=0xFB1D,
@@ -119878,7 +121662,7 @@ characters.data={
category="lo",
description="HEBREW LIGATURE YIDDISH YOD YOD PATAH",
direction="r",
- linebreak="al",
+ linebreak="hl",
specials={ "char", 0x05F2, 0x05B7 },
unicodeslot=0xFB1F,
},
@@ -119887,7 +121671,7 @@ characters.data={
category="lo",
description="HEBREW LETTER ALTERNATIVE AYIN",
direction="r",
- linebreak="al",
+ linebreak="hl",
specials={ "font", 0x05E2 },
unicodeslot=0xFB20,
},
@@ -119895,7 +121679,7 @@ characters.data={
category="lo",
description="HEBREW LETTER WIDE ALEF",
direction="r",
- linebreak="al",
+ linebreak="hl",
specials={ "font", 0x05D0 },
unicodeslot=0xFB21,
},
@@ -119903,7 +121687,7 @@ characters.data={
category="lo",
description="HEBREW LETTER WIDE DALET",
direction="r",
- linebreak="al",
+ linebreak="hl",
specials={ "font", 0x05D3 },
unicodeslot=0xFB22,
},
@@ -119911,7 +121695,7 @@ characters.data={
category="lo",
description="HEBREW LETTER WIDE HE",
direction="r",
- linebreak="al",
+ linebreak="hl",
specials={ "font", 0x05D4 },
unicodeslot=0xFB23,
},
@@ -119919,7 +121703,7 @@ characters.data={
category="lo",
description="HEBREW LETTER WIDE KAF",
direction="r",
- linebreak="al",
+ linebreak="hl",
specials={ "font", 0x05DB },
unicodeslot=0xFB24,
},
@@ -119927,7 +121711,7 @@ characters.data={
category="lo",
description="HEBREW LETTER WIDE LAMED",
direction="r",
- linebreak="al",
+ linebreak="hl",
specials={ "font", 0x05DC },
unicodeslot=0xFB25,
},
@@ -119935,7 +121719,7 @@ characters.data={
category="lo",
description="HEBREW LETTER WIDE FINAL MEM",
direction="r",
- linebreak="al",
+ linebreak="hl",
specials={ "font", 0x05DD },
unicodeslot=0xFB26,
},
@@ -119943,7 +121727,7 @@ characters.data={
category="lo",
description="HEBREW LETTER WIDE RESH",
direction="r",
- linebreak="al",
+ linebreak="hl",
specials={ "font", 0x05E8 },
unicodeslot=0xFB27,
},
@@ -119951,7 +121735,7 @@ characters.data={
category="lo",
description="HEBREW LETTER WIDE TAV",
direction="r",
- linebreak="al",
+ linebreak="hl",
specials={ "font", 0x05EA },
unicodeslot=0xFB28,
},
@@ -119968,7 +121752,7 @@ characters.data={
category="lo",
description="HEBREW LETTER SHIN WITH SHIN DOT",
direction="r",
- linebreak="al",
+ linebreak="hl",
shcode=0x05E9,
specials={ "char", 0x05E9, 0x05C1 },
unicodeslot=0xFB2A,
@@ -119978,7 +121762,7 @@ characters.data={
category="lo",
description="HEBREW LETTER SHIN WITH SIN DOT",
direction="r",
- linebreak="al",
+ linebreak="hl",
shcode=0x05E9,
specials={ "char", 0x05E9, 0x05C2 },
unicodeslot=0xFB2B,
@@ -119988,7 +121772,7 @@ characters.data={
category="lo",
description="HEBREW LETTER SHIN WITH DAGESH AND SHIN DOT",
direction="r",
- linebreak="al",
+ linebreak="hl",
shcode=0x05E9,
specials={ "char", 0xFB49, 0x05C1 },
unicodeslot=0xFB2C,
@@ -119998,7 +121782,7 @@ characters.data={
category="lo",
description="HEBREW LETTER SHIN WITH DAGESH AND SIN DOT",
direction="r",
- linebreak="al",
+ linebreak="hl",
shcode=0x05E9,
specials={ "char", 0xFB49, 0x05C2 },
unicodeslot=0xFB2D,
@@ -120008,7 +121792,7 @@ characters.data={
category="lo",
description="HEBREW LETTER ALEF WITH PATAH",
direction="r",
- linebreak="al",
+ linebreak="hl",
shcode=0x05D0,
specials={ "char", 0x05D0, 0x05B7 },
unicodeslot=0xFB2E,
@@ -120018,7 +121802,7 @@ characters.data={
category="lo",
description="HEBREW LETTER ALEF WITH QAMATS",
direction="r",
- linebreak="al",
+ linebreak="hl",
shcode=0x05D0,
specials={ "char", 0x05D0, 0x05B8 },
unicodeslot=0xFB2F,
@@ -120028,7 +121812,7 @@ characters.data={
category="lo",
description="HEBREW LETTER ALEF WITH MAPIQ",
direction="r",
- linebreak="al",
+ linebreak="hl",
shcode=0x05D0,
specials={ "char", 0x05D0, 0x05BC },
unicodeslot=0xFB30,
@@ -120038,7 +121822,7 @@ characters.data={
category="lo",
description="HEBREW LETTER BET WITH DAGESH",
direction="r",
- linebreak="al",
+ linebreak="hl",
shcode=0x05D1,
specials={ "char", 0x05D1, 0x05BC },
unicodeslot=0xFB31,
@@ -120048,7 +121832,7 @@ characters.data={
category="lo",
description="HEBREW LETTER GIMEL WITH DAGESH",
direction="r",
- linebreak="al",
+ linebreak="hl",
shcode=0x05D2,
specials={ "char", 0x05D2, 0x05BC },
unicodeslot=0xFB32,
@@ -120058,7 +121842,7 @@ characters.data={
category="lo",
description="HEBREW LETTER DALET WITH DAGESH",
direction="r",
- linebreak="al",
+ linebreak="hl",
shcode=0x05D3,
specials={ "char", 0x05D3, 0x05BC },
unicodeslot=0xFB33,
@@ -120068,7 +121852,7 @@ characters.data={
category="lo",
description="HEBREW LETTER HE WITH MAPIQ",
direction="r",
- linebreak="al",
+ linebreak="hl",
shcode=0x05D4,
specials={ "char", 0x05D4, 0x05BC },
unicodeslot=0xFB34,
@@ -120078,7 +121862,7 @@ characters.data={
category="lo",
description="HEBREW LETTER VAV WITH DAGESH",
direction="r",
- linebreak="al",
+ linebreak="hl",
shcode=0x05D5,
specials={ "char", 0x05D5, 0x05BC },
unicodeslot=0xFB35,
@@ -120088,7 +121872,7 @@ characters.data={
category="lo",
description="HEBREW LETTER ZAYIN WITH DAGESH",
direction="r",
- linebreak="al",
+ linebreak="hl",
shcode=0x05D6,
specials={ "char", 0x05D6, 0x05BC },
unicodeslot=0xFB36,
@@ -120098,7 +121882,7 @@ characters.data={
category="lo",
description="HEBREW LETTER TET WITH DAGESH",
direction="r",
- linebreak="al",
+ linebreak="hl",
shcode=0x05D8,
specials={ "char", 0x05D8, 0x05BC },
unicodeslot=0xFB38,
@@ -120108,7 +121892,7 @@ characters.data={
category="lo",
description="HEBREW LETTER YOD WITH DAGESH",
direction="r",
- linebreak="al",
+ linebreak="hl",
shcode=0x05D9,
specials={ "char", 0x05D9, 0x05BC },
unicodeslot=0xFB39,
@@ -120118,7 +121902,7 @@ characters.data={
category="lo",
description="HEBREW LETTER FINAL KAF WITH DAGESH",
direction="r",
- linebreak="al",
+ linebreak="hl",
specials={ "char", 0x05DA, 0x05BC },
unicodeslot=0xFB3A,
},
@@ -120127,7 +121911,7 @@ characters.data={
category="lo",
description="HEBREW LETTER KAF WITH DAGESH",
direction="r",
- linebreak="al",
+ linebreak="hl",
shcode=0x05DB,
specials={ "char", 0x05DB, 0x05BC },
unicodeslot=0xFB3B,
@@ -120137,7 +121921,7 @@ characters.data={
category="lo",
description="HEBREW LETTER LAMED WITH DAGESH",
direction="r",
- linebreak="al",
+ linebreak="hl",
shcode=0x05DC,
specials={ "char", 0x05DC, 0x05BC },
unicodeslot=0xFB3C,
@@ -120147,7 +121931,7 @@ characters.data={
category="lo",
description="HEBREW LETTER MEM WITH DAGESH",
direction="r",
- linebreak="al",
+ linebreak="hl",
shcode=0x05DE,
specials={ "char", 0x05DE, 0x05BC },
unicodeslot=0xFB3E,
@@ -120157,7 +121941,7 @@ characters.data={
category="lo",
description="HEBREW LETTER NUN WITH DAGESH",
direction="r",
- linebreak="al",
+ linebreak="hl",
shcode=0x05E0,
specials={ "char", 0x05E0, 0x05BC },
unicodeslot=0xFB40,
@@ -120167,7 +121951,7 @@ characters.data={
category="lo",
description="HEBREW LETTER SAMEKH WITH DAGESH",
direction="r",
- linebreak="al",
+ linebreak="hl",
shcode=0x05E1,
specials={ "char", 0x05E1, 0x05BC },
unicodeslot=0xFB41,
@@ -120177,7 +121961,7 @@ characters.data={
category="lo",
description="HEBREW LETTER FINAL PE WITH DAGESH",
direction="r",
- linebreak="al",
+ linebreak="hl",
specials={ "char", 0x05E3, 0x05BC },
unicodeslot=0xFB43,
},
@@ -120186,7 +121970,7 @@ characters.data={
category="lo",
description="HEBREW LETTER PE WITH DAGESH",
direction="r",
- linebreak="al",
+ linebreak="hl",
shcode=0x05E4,
specials={ "char", 0x05E4, 0x05BC },
unicodeslot=0xFB44,
@@ -120196,7 +121980,7 @@ characters.data={
category="lo",
description="HEBREW LETTER TSADI WITH DAGESH",
direction="r",
- linebreak="al",
+ linebreak="hl",
shcode=0x05E6,
specials={ "char", 0x05E6, 0x05BC },
unicodeslot=0xFB46,
@@ -120206,7 +121990,7 @@ characters.data={
category="lo",
description="HEBREW LETTER QOF WITH DAGESH",
direction="r",
- linebreak="al",
+ linebreak="hl",
shcode=0x05E7,
specials={ "char", 0x05E7, 0x05BC },
unicodeslot=0xFB47,
@@ -120216,7 +122000,7 @@ characters.data={
category="lo",
description="HEBREW LETTER RESH WITH DAGESH",
direction="r",
- linebreak="al",
+ linebreak="hl",
shcode=0x05E8,
specials={ "char", 0x05E8, 0x05BC },
unicodeslot=0xFB48,
@@ -120226,7 +122010,7 @@ characters.data={
category="lo",
description="HEBREW LETTER SHIN WITH DAGESH",
direction="r",
- linebreak="al",
+ linebreak="hl",
shcode=0x05E9,
specials={ "char", 0x05E9, 0x05BC },
unicodeslot=0xFB49,
@@ -120236,7 +122020,7 @@ characters.data={
category="lo",
description="HEBREW LETTER TAV WITH DAGESH",
direction="r",
- linebreak="al",
+ linebreak="hl",
shcode=0x05EA,
specials={ "char", 0x05EA, 0x05BC },
unicodeslot=0xFB4A,
@@ -120246,7 +122030,7 @@ characters.data={
category="lo",
description="HEBREW LETTER VAV WITH HOLAM",
direction="r",
- linebreak="al",
+ linebreak="hl",
shcode=0x05D5,
specials={ "char", 0x05D5, 0x05B9 },
unicodeslot=0xFB4B,
@@ -120256,7 +122040,7 @@ characters.data={
category="lo",
description="HEBREW LETTER BET WITH RAFE",
direction="r",
- linebreak="al",
+ linebreak="hl",
shcode=0x05D1,
specials={ "char", 0x05D1, 0x05BF },
unicodeslot=0xFB4C,
@@ -120266,7 +122050,7 @@ characters.data={
category="lo",
description="HEBREW LETTER KAF WITH RAFE",
direction="r",
- linebreak="al",
+ linebreak="hl",
shcode=0x05DB,
specials={ "char", 0x05DB, 0x05BF },
unicodeslot=0xFB4D,
@@ -120276,7 +122060,7 @@ characters.data={
category="lo",
description="HEBREW LETTER PE WITH RAFE",
direction="r",
- linebreak="al",
+ linebreak="hl",
shcode=0x05E4,
specials={ "char", 0x05E4, 0x05BF },
unicodeslot=0xFB4E,
@@ -120286,7 +122070,7 @@ characters.data={
category="lo",
description="HEBREW LIGATURE ALEF LAMED",
direction="r",
- linebreak="al",
+ linebreak="hl",
specials={ "compat", 0x05D0, 0x05DC },
unicodeslot=0xFB4F,
},
@@ -128386,7 +130170,7 @@ characters.data={
cjkwd="h",
description="HALFWIDTH KATAKANA LETTER SMALL A",
direction="l",
- linebreak="ns",
+ linebreak="cj",
specials={ "narrow", 0x30A1 },
unicodeslot=0xFF67,
},
@@ -128396,7 +130180,7 @@ characters.data={
cjkwd="h",
description="HALFWIDTH KATAKANA LETTER SMALL I",
direction="l",
- linebreak="ns",
+ linebreak="cj",
specials={ "narrow", 0x30A3 },
unicodeslot=0xFF68,
},
@@ -128406,7 +130190,7 @@ characters.data={
cjkwd="h",
description="HALFWIDTH KATAKANA LETTER SMALL U",
direction="l",
- linebreak="ns",
+ linebreak="cj",
specials={ "narrow", 0x30A5 },
unicodeslot=0xFF69,
},
@@ -128416,7 +130200,7 @@ characters.data={
cjkwd="h",
description="HALFWIDTH KATAKANA LETTER SMALL E",
direction="l",
- linebreak="ns",
+ linebreak="cj",
specials={ "narrow", 0x30A7 },
unicodeslot=0xFF6A,
},
@@ -128426,7 +130210,7 @@ characters.data={
cjkwd="h",
description="HALFWIDTH KATAKANA LETTER SMALL O",
direction="l",
- linebreak="ns",
+ linebreak="cj",
specials={ "narrow", 0x30A9 },
unicodeslot=0xFF6B,
},
@@ -128436,7 +130220,7 @@ characters.data={
cjkwd="h",
description="HALFWIDTH KATAKANA LETTER SMALL YA",
direction="l",
- linebreak="ns",
+ linebreak="cj",
specials={ "narrow", 0x30E3 },
unicodeslot=0xFF6C,
},
@@ -128446,7 +130230,7 @@ characters.data={
cjkwd="h",
description="HALFWIDTH KATAKANA LETTER SMALL YU",
direction="l",
- linebreak="ns",
+ linebreak="cj",
specials={ "narrow", 0x30E5 },
unicodeslot=0xFF6D,
},
@@ -128456,7 +130240,7 @@ characters.data={
cjkwd="h",
description="HALFWIDTH KATAKANA LETTER SMALL YO",
direction="l",
- linebreak="ns",
+ linebreak="cj",
specials={ "narrow", 0x30E7 },
unicodeslot=0xFF6E,
},
@@ -128466,7 +130250,7 @@ characters.data={
cjkwd="h",
description="HALFWIDTH KATAKANA LETTER SMALL TU",
direction="l",
- linebreak="ns",
+ linebreak="cj",
specials={ "narrow", 0x30C3 },
unicodeslot=0xFF6F,
},
@@ -128476,7 +130260,7 @@ characters.data={
cjkwd="h",
description="HALFWIDTH KATAKANA-HIRAGANA PROLONGED SOUND MARK",
direction="l",
- linebreak="ns",
+ linebreak="cj",
specials={ "narrow", 0x30FC },
unicodeslot=0xFF70,
},
@@ -136192,6 +137976,412 @@ characters.data={
linebreak="al",
unicodeslot=0x1093F,
},
+ [0x10980]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER A",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10980,
+ },
+ [0x10981]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER E",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10981,
+ },
+ [0x10982]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER I",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10982,
+ },
+ [0x10983]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER O",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10983,
+ },
+ [0x10984]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER YA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10984,
+ },
+ [0x10985]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER WA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10985,
+ },
+ [0x10986]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER BA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10986,
+ },
+ [0x10987]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER BA-2",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10987,
+ },
+ [0x10988]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER PA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10988,
+ },
+ [0x10989]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER MA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10989,
+ },
+ [0x1098A]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER NA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1098A,
+ },
+ [0x1098B]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER NA-2",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1098B,
+ },
+ [0x1098C]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER NE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1098C,
+ },
+ [0x1098D]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER NE-2",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1098D,
+ },
+ [0x1098E]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER RA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1098E,
+ },
+ [0x1098F]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER RA-2",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1098F,
+ },
+ [0x10990]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER LA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10990,
+ },
+ [0x10991]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER KHA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10991,
+ },
+ [0x10992]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER HHA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10992,
+ },
+ [0x10993]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER SA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10993,
+ },
+ [0x10994]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER SA-2",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10994,
+ },
+ [0x10995]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER SE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10995,
+ },
+ [0x10996]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER KA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10996,
+ },
+ [0x10997]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER QA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10997,
+ },
+ [0x10998]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER TA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10998,
+ },
+ [0x10999]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER TA-2",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10999,
+ },
+ [0x1099A]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER TE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1099A,
+ },
+ [0x1099B]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER TE-2",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1099B,
+ },
+ [0x1099C]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER TO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1099C,
+ },
+ [0x1099D]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC LETTER DA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1099D,
+ },
+ [0x1099E]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC SYMBOL VIDJ",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1099E,
+ },
+ [0x1099F]={
+ category="lo",
+ description="MEROITIC HIEROGLYPHIC SYMBOL VIDJ-2",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1099F,
+ },
+ [0x109A0]={
+ category="lo",
+ description="MEROITIC CURSIVE LETTER A",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109A0,
+ },
+ [0x109A1]={
+ category="lo",
+ description="MEROITIC CURSIVE LETTER E",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109A1,
+ },
+ [0x109A2]={
+ category="lo",
+ description="MEROITIC CURSIVE LETTER I",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109A2,
+ },
+ [0x109A3]={
+ category="lo",
+ description="MEROITIC CURSIVE LETTER O",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109A3,
+ },
+ [0x109A4]={
+ category="lo",
+ description="MEROITIC CURSIVE LETTER YA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109A4,
+ },
+ [0x109A5]={
+ category="lo",
+ description="MEROITIC CURSIVE LETTER WA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109A5,
+ },
+ [0x109A6]={
+ category="lo",
+ description="MEROITIC CURSIVE LETTER BA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109A6,
+ },
+ [0x109A7]={
+ category="lo",
+ description="MEROITIC CURSIVE LETTER PA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109A7,
+ },
+ [0x109A8]={
+ category="lo",
+ description="MEROITIC CURSIVE LETTER MA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109A8,
+ },
+ [0x109A9]={
+ category="lo",
+ description="MEROITIC CURSIVE LETTER NA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109A9,
+ },
+ [0x109AA]={
+ category="lo",
+ description="MEROITIC CURSIVE LETTER NE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109AA,
+ },
+ [0x109AB]={
+ category="lo",
+ description="MEROITIC CURSIVE LETTER RA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109AB,
+ },
+ [0x109AC]={
+ category="lo",
+ description="MEROITIC CURSIVE LETTER LA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109AC,
+ },
+ [0x109AD]={
+ category="lo",
+ description="MEROITIC CURSIVE LETTER KHA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109AD,
+ },
+ [0x109AE]={
+ category="lo",
+ description="MEROITIC CURSIVE LETTER HHA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109AE,
+ },
+ [0x109AF]={
+ category="lo",
+ description="MEROITIC CURSIVE LETTER SA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109AF,
+ },
+ [0x109B0]={
+ category="lo",
+ description="MEROITIC CURSIVE LETTER ARCHAIC SA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109B0,
+ },
+ [0x109B1]={
+ category="lo",
+ description="MEROITIC CURSIVE LETTER SE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109B1,
+ },
+ [0x109B2]={
+ category="lo",
+ description="MEROITIC CURSIVE LETTER KA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109B2,
+ },
+ [0x109B3]={
+ category="lo",
+ description="MEROITIC CURSIVE LETTER QA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109B3,
+ },
+ [0x109B4]={
+ category="lo",
+ description="MEROITIC CURSIVE LETTER TA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109B4,
+ },
+ [0x109B5]={
+ category="lo",
+ description="MEROITIC CURSIVE LETTER TE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109B5,
+ },
+ [0x109B6]={
+ category="lo",
+ description="MEROITIC CURSIVE LETTER TO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109B6,
+ },
+ [0x109B7]={
+ category="lo",
+ description="MEROITIC CURSIVE LETTER DA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109B7,
+ },
+ [0x109BE]={
+ category="lo",
+ description="MEROITIC CURSIVE LOGOGRAM RMT",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109BE,
+ },
+ [0x109BF]={
+ category="lo",
+ description="MEROITIC CURSIVE LOGOGRAM IMN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x109BF,
+ },
[0x10A00]={
category="lo",
description="KHAROSHTHI LETTER A",
@@ -139646,6 +141836,1765 @@ characters.data={
linebreak="ba",
unicodeslot=0x110C1,
},
+ [0x110D0]={
+ category="lo",
+ description="SORA SOMPENG LETTER SAH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110D0,
+ },
+ [0x110D1]={
+ category="lo",
+ description="SORA SOMPENG LETTER TAH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110D1,
+ },
+ [0x110D2]={
+ category="lo",
+ description="SORA SOMPENG LETTER BAH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110D2,
+ },
+ [0x110D3]={
+ category="lo",
+ description="SORA SOMPENG LETTER CAH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110D3,
+ },
+ [0x110D4]={
+ category="lo",
+ description="SORA SOMPENG LETTER DAH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110D4,
+ },
+ [0x110D5]={
+ category="lo",
+ description="SORA SOMPENG LETTER GAH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110D5,
+ },
+ [0x110D6]={
+ category="lo",
+ description="SORA SOMPENG LETTER MAH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110D6,
+ },
+ [0x110D7]={
+ category="lo",
+ description="SORA SOMPENG LETTER NGAH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110D7,
+ },
+ [0x110D8]={
+ category="lo",
+ description="SORA SOMPENG LETTER LAH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110D8,
+ },
+ [0x110D9]={
+ category="lo",
+ description="SORA SOMPENG LETTER NAH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110D9,
+ },
+ [0x110DA]={
+ category="lo",
+ description="SORA SOMPENG LETTER VAH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110DA,
+ },
+ [0x110DB]={
+ category="lo",
+ description="SORA SOMPENG LETTER PAH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110DB,
+ },
+ [0x110DC]={
+ category="lo",
+ description="SORA SOMPENG LETTER YAH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110DC,
+ },
+ [0x110DD]={
+ category="lo",
+ description="SORA SOMPENG LETTER RAH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110DD,
+ },
+ [0x110DE]={
+ category="lo",
+ description="SORA SOMPENG LETTER HAH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110DE,
+ },
+ [0x110DF]={
+ category="lo",
+ description="SORA SOMPENG LETTER KAH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110DF,
+ },
+ [0x110E0]={
+ category="lo",
+ description="SORA SOMPENG LETTER JAH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110E0,
+ },
+ [0x110E1]={
+ category="lo",
+ description="SORA SOMPENG LETTER NYAH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110E1,
+ },
+ [0x110E2]={
+ category="lo",
+ description="SORA SOMPENG LETTER AH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110E2,
+ },
+ [0x110E3]={
+ category="lo",
+ description="SORA SOMPENG LETTER EEH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110E3,
+ },
+ [0x110E4]={
+ category="lo",
+ description="SORA SOMPENG LETTER IH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110E4,
+ },
+ [0x110E5]={
+ category="lo",
+ description="SORA SOMPENG LETTER UH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110E5,
+ },
+ [0x110E6]={
+ category="lo",
+ description="SORA SOMPENG LETTER OH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110E6,
+ },
+ [0x110E7]={
+ category="lo",
+ description="SORA SOMPENG LETTER EH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110E7,
+ },
+ [0x110E8]={
+ category="lo",
+ description="SORA SOMPENG LETTER MAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110E8,
+ },
+ [0x110F0]={
+ category="nd",
+ description="SORA SOMPENG DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x110F0,
+ },
+ [0x110F1]={
+ category="nd",
+ description="SORA SOMPENG DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x110F1,
+ },
+ [0x110F2]={
+ category="nd",
+ description="SORA SOMPENG DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x110F2,
+ },
+ [0x110F3]={
+ category="nd",
+ description="SORA SOMPENG DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x110F3,
+ },
+ [0x110F4]={
+ category="nd",
+ description="SORA SOMPENG DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x110F4,
+ },
+ [0x110F5]={
+ category="nd",
+ description="SORA SOMPENG DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x110F5,
+ },
+ [0x110F6]={
+ category="nd",
+ description="SORA SOMPENG DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x110F6,
+ },
+ [0x110F7]={
+ category="nd",
+ description="SORA SOMPENG DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x110F7,
+ },
+ [0x110F8]={
+ category="nd",
+ description="SORA SOMPENG DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x110F8,
+ },
+ [0x110F9]={
+ category="nd",
+ description="SORA SOMPENG DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x110F9,
+ },
+ [0x11100]={
+ category="mn",
+ description="CHAKMA SIGN CANDRABINDU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11100,
+ },
+ [0x11101]={
+ category="mn",
+ description="CHAKMA SIGN ANUSVARA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11101,
+ },
+ [0x11102]={
+ category="mn",
+ description="CHAKMA SIGN VISARGA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11102,
+ },
+ [0x11103]={
+ category="lo",
+ description="CHAKMA LETTER AA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11103,
+ },
+ [0x11104]={
+ category="lo",
+ description="CHAKMA LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11104,
+ },
+ [0x11105]={
+ category="lo",
+ description="CHAKMA LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11105,
+ },
+ [0x11106]={
+ category="lo",
+ description="CHAKMA LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11106,
+ },
+ [0x11107]={
+ category="lo",
+ description="CHAKMA LETTER KAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11107,
+ },
+ [0x11108]={
+ category="lo",
+ description="CHAKMA LETTER KHAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11108,
+ },
+ [0x11109]={
+ category="lo",
+ description="CHAKMA LETTER GAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11109,
+ },
+ [0x1110A]={
+ category="lo",
+ description="CHAKMA LETTER GHAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1110A,
+ },
+ [0x1110B]={
+ category="lo",
+ description="CHAKMA LETTER NGAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1110B,
+ },
+ [0x1110C]={
+ category="lo",
+ description="CHAKMA LETTER CAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1110C,
+ },
+ [0x1110D]={
+ category="lo",
+ description="CHAKMA LETTER CHAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1110D,
+ },
+ [0x1110E]={
+ category="lo",
+ description="CHAKMA LETTER JAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1110E,
+ },
+ [0x1110F]={
+ category="lo",
+ description="CHAKMA LETTER JHAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1110F,
+ },
+ [0x11110]={
+ category="lo",
+ description="CHAKMA LETTER NYAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11110,
+ },
+ [0x11111]={
+ category="lo",
+ description="CHAKMA LETTER TTAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11111,
+ },
+ [0x11112]={
+ category="lo",
+ description="CHAKMA LETTER TTHAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11112,
+ },
+ [0x11113]={
+ category="lo",
+ description="CHAKMA LETTER DDAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11113,
+ },
+ [0x11114]={
+ category="lo",
+ description="CHAKMA LETTER DDHAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11114,
+ },
+ [0x11115]={
+ category="lo",
+ description="CHAKMA LETTER NNAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11115,
+ },
+ [0x11116]={
+ category="lo",
+ description="CHAKMA LETTER TAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11116,
+ },
+ [0x11117]={
+ category="lo",
+ description="CHAKMA LETTER THAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11117,
+ },
+ [0x11118]={
+ category="lo",
+ description="CHAKMA LETTER DAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11118,
+ },
+ [0x11119]={
+ category="lo",
+ description="CHAKMA LETTER DHAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11119,
+ },
+ [0x1111A]={
+ category="lo",
+ description="CHAKMA LETTER NAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1111A,
+ },
+ [0x1111B]={
+ category="lo",
+ description="CHAKMA LETTER PAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1111B,
+ },
+ [0x1111C]={
+ category="lo",
+ description="CHAKMA LETTER PHAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1111C,
+ },
+ [0x1111D]={
+ category="lo",
+ description="CHAKMA LETTER BAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1111D,
+ },
+ [0x1111E]={
+ category="lo",
+ description="CHAKMA LETTER BHAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1111E,
+ },
+ [0x1111F]={
+ category="lo",
+ description="CHAKMA LETTER MAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1111F,
+ },
+ [0x11120]={
+ category="lo",
+ description="CHAKMA LETTER YYAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11120,
+ },
+ [0x11121]={
+ category="lo",
+ description="CHAKMA LETTER YAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11121,
+ },
+ [0x11122]={
+ category="lo",
+ description="CHAKMA LETTER RAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11122,
+ },
+ [0x11123]={
+ category="lo",
+ description="CHAKMA LETTER LAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11123,
+ },
+ [0x11124]={
+ category="lo",
+ description="CHAKMA LETTER WAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11124,
+ },
+ [0x11125]={
+ category="lo",
+ description="CHAKMA LETTER SAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11125,
+ },
+ [0x11126]={
+ category="lo",
+ description="CHAKMA LETTER HAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11126,
+ },
+ [0x11127]={
+ category="mn",
+ description="CHAKMA VOWEL SIGN A",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11127,
+ },
+ [0x11128]={
+ category="mn",
+ description="CHAKMA VOWEL SIGN I",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11128,
+ },
+ [0x11129]={
+ category="mn",
+ description="CHAKMA VOWEL SIGN II",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11129,
+ },
+ [0x1112A]={
+ category="mn",
+ description="CHAKMA VOWEL SIGN U",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1112A,
+ },
+ [0x1112B]={
+ category="mn",
+ description="CHAKMA VOWEL SIGN UU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1112B,
+ },
+ [0x1112C]={
+ category="mc",
+ description="CHAKMA VOWEL SIGN E",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1112C,
+ },
+ [0x1112D]={
+ category="mn",
+ description="CHAKMA VOWEL SIGN AI",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1112D,
+ },
+ [0x1112E]={
+ category="mn",
+ description="CHAKMA VOWEL SIGN O",
+ direction="nsm",
+ linebreak="cm",
+ specials={ "char", 0x11131, 0x11127 },
+ unicodeslot=0x1112E,
+ },
+ [0x1112F]={
+ category="mn",
+ description="CHAKMA VOWEL SIGN AU",
+ direction="nsm",
+ linebreak="cm",
+ specials={ "char", 0x11132, 0x11127 },
+ unicodeslot=0x1112F,
+ },
+ [0x11130]={
+ category="mn",
+ description="CHAKMA VOWEL SIGN OI",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11130,
+ },
+ [0x11131]={
+ category="mn",
+ description="CHAKMA O MARK",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11131,
+ },
+ [0x11132]={
+ category="mn",
+ description="CHAKMA AU MARK",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11132,
+ },
+ [0x11133]={
+ category="mn",
+ description="CHAKMA VIRAMA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11133,
+ },
+ [0x11134]={
+ category="mn",
+ description="CHAKMA MAAYYAA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11134,
+ },
+ [0x11136]={
+ category="nd",
+ description="CHAKMA DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x11136,
+ },
+ [0x11137]={
+ category="nd",
+ description="CHAKMA DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x11137,
+ },
+ [0x11138]={
+ category="nd",
+ description="CHAKMA DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x11138,
+ },
+ [0x11139]={
+ category="nd",
+ description="CHAKMA DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x11139,
+ },
+ [0x1113A]={
+ category="nd",
+ description="CHAKMA DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1113A,
+ },
+ [0x1113B]={
+ category="nd",
+ description="CHAKMA DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1113B,
+ },
+ [0x1113C]={
+ category="nd",
+ description="CHAKMA DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1113C,
+ },
+ [0x1113D]={
+ category="nd",
+ description="CHAKMA DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1113D,
+ },
+ [0x1113E]={
+ category="nd",
+ description="CHAKMA DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1113E,
+ },
+ [0x1113F]={
+ category="nd",
+ description="CHAKMA DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1113F,
+ },
+ [0x11140]={
+ category="po",
+ description="CHAKMA SECTION MARK",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x11140,
+ },
+ [0x11141]={
+ category="po",
+ description="CHAKMA DANDA",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x11141,
+ },
+ [0x11142]={
+ category="po",
+ description="CHAKMA DOUBLE DANDA",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x11142,
+ },
+ [0x11143]={
+ category="po",
+ description="CHAKMA QUESTION MARK",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x11143,
+ },
+ [0x11180]={
+ category="mn",
+ description="SHARADA SIGN CANDRABINDU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11180,
+ },
+ [0x11181]={
+ category="mn",
+ description="SHARADA SIGN ANUSVARA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11181,
+ },
+ [0x11182]={
+ category="mc",
+ description="SHARADA SIGN VISARGA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x11182,
+ },
+ [0x11183]={
+ category="lo",
+ description="SHARADA LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11183,
+ },
+ [0x11184]={
+ category="lo",
+ description="SHARADA LETTER AA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11184,
+ },
+ [0x11185]={
+ category="lo",
+ description="SHARADA LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11185,
+ },
+ [0x11186]={
+ category="lo",
+ description="SHARADA LETTER II",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11186,
+ },
+ [0x11187]={
+ category="lo",
+ description="SHARADA LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11187,
+ },
+ [0x11188]={
+ category="lo",
+ description="SHARADA LETTER UU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11188,
+ },
+ [0x11189]={
+ category="lo",
+ description="SHARADA LETTER VOCALIC R",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11189,
+ },
+ [0x1118A]={
+ category="lo",
+ description="SHARADA LETTER VOCALIC RR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1118A,
+ },
+ [0x1118B]={
+ category="lo",
+ description="SHARADA LETTER VOCALIC L",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1118B,
+ },
+ [0x1118C]={
+ category="lo",
+ description="SHARADA LETTER VOCALIC LL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1118C,
+ },
+ [0x1118D]={
+ category="lo",
+ description="SHARADA LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1118D,
+ },
+ [0x1118E]={
+ category="lo",
+ description="SHARADA LETTER AI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1118E,
+ },
+ [0x1118F]={
+ category="lo",
+ description="SHARADA LETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1118F,
+ },
+ [0x11190]={
+ category="lo",
+ description="SHARADA LETTER AU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11190,
+ },
+ [0x11191]={
+ category="lo",
+ description="SHARADA LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11191,
+ },
+ [0x11192]={
+ category="lo",
+ description="SHARADA LETTER KHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11192,
+ },
+ [0x11193]={
+ category="lo",
+ description="SHARADA LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11193,
+ },
+ [0x11194]={
+ category="lo",
+ description="SHARADA LETTER GHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11194,
+ },
+ [0x11195]={
+ category="lo",
+ description="SHARADA LETTER NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11195,
+ },
+ [0x11196]={
+ category="lo",
+ description="SHARADA LETTER CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11196,
+ },
+ [0x11197]={
+ category="lo",
+ description="SHARADA LETTER CHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11197,
+ },
+ [0x11198]={
+ category="lo",
+ description="SHARADA LETTER JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11198,
+ },
+ [0x11199]={
+ category="lo",
+ description="SHARADA LETTER JHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11199,
+ },
+ [0x1119A]={
+ category="lo",
+ description="SHARADA LETTER NYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1119A,
+ },
+ [0x1119B]={
+ category="lo",
+ description="SHARADA LETTER TTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1119B,
+ },
+ [0x1119C]={
+ category="lo",
+ description="SHARADA LETTER TTHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1119C,
+ },
+ [0x1119D]={
+ category="lo",
+ description="SHARADA LETTER DDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1119D,
+ },
+ [0x1119E]={
+ category="lo",
+ description="SHARADA LETTER DDHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1119E,
+ },
+ [0x1119F]={
+ category="lo",
+ description="SHARADA LETTER NNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1119F,
+ },
+ [0x111A0]={
+ category="lo",
+ description="SHARADA LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111A0,
+ },
+ [0x111A1]={
+ category="lo",
+ description="SHARADA LETTER THA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111A1,
+ },
+ [0x111A2]={
+ category="lo",
+ description="SHARADA LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111A2,
+ },
+ [0x111A3]={
+ category="lo",
+ description="SHARADA LETTER DHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111A3,
+ },
+ [0x111A4]={
+ category="lo",
+ description="SHARADA LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111A4,
+ },
+ [0x111A5]={
+ category="lo",
+ description="SHARADA LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111A5,
+ },
+ [0x111A6]={
+ category="lo",
+ description="SHARADA LETTER PHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111A6,
+ },
+ [0x111A7]={
+ category="lo",
+ description="SHARADA LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111A7,
+ },
+ [0x111A8]={
+ category="lo",
+ description="SHARADA LETTER BHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111A8,
+ },
+ [0x111A9]={
+ category="lo",
+ description="SHARADA LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111A9,
+ },
+ [0x111AA]={
+ category="lo",
+ description="SHARADA LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111AA,
+ },
+ [0x111AB]={
+ category="lo",
+ description="SHARADA LETTER RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111AB,
+ },
+ [0x111AC]={
+ category="lo",
+ description="SHARADA LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111AC,
+ },
+ [0x111AD]={
+ category="lo",
+ description="SHARADA LETTER LLA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111AD,
+ },
+ [0x111AE]={
+ category="lo",
+ description="SHARADA LETTER VA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111AE,
+ },
+ [0x111AF]={
+ category="lo",
+ description="SHARADA LETTER SHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111AF,
+ },
+ [0x111B0]={
+ category="lo",
+ description="SHARADA LETTER SSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111B0,
+ },
+ [0x111B1]={
+ category="lo",
+ description="SHARADA LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111B1,
+ },
+ [0x111B2]={
+ category="lo",
+ description="SHARADA LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111B2,
+ },
+ [0x111B3]={
+ category="mc",
+ description="SHARADA VOWEL SIGN AA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x111B3,
+ },
+ [0x111B4]={
+ category="mc",
+ description="SHARADA VOWEL SIGN I",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x111B4,
+ },
+ [0x111B5]={
+ category="mc",
+ description="SHARADA VOWEL SIGN II",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x111B5,
+ },
+ [0x111B6]={
+ category="mn",
+ description="SHARADA VOWEL SIGN U",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x111B6,
+ },
+ [0x111B7]={
+ category="mn",
+ description="SHARADA VOWEL SIGN UU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x111B7,
+ },
+ [0x111B8]={
+ category="mn",
+ description="SHARADA VOWEL SIGN VOCALIC R",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x111B8,
+ },
+ [0x111B9]={
+ category="mn",
+ description="SHARADA VOWEL SIGN VOCALIC RR",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x111B9,
+ },
+ [0x111BA]={
+ category="mn",
+ description="SHARADA VOWEL SIGN VOCALIC L",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x111BA,
+ },
+ [0x111BB]={
+ category="mn",
+ description="SHARADA VOWEL SIGN VOCALIC LL",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x111BB,
+ },
+ [0x111BC]={
+ category="mn",
+ description="SHARADA VOWEL SIGN E",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x111BC,
+ },
+ [0x111BD]={
+ category="mn",
+ description="SHARADA VOWEL SIGN AI",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x111BD,
+ },
+ [0x111BE]={
+ category="mn",
+ description="SHARADA VOWEL SIGN O",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x111BE,
+ },
+ [0x111BF]={
+ category="mc",
+ description="SHARADA VOWEL SIGN AU",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x111BF,
+ },
+ [0x111C0]={
+ category="mc",
+ description="SHARADA SIGN VIRAMA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x111C0,
+ },
+ [0x111C1]={
+ category="lo",
+ description="SHARADA SIGN AVAGRAHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111C1,
+ },
+ [0x111C2]={
+ category="lo",
+ description="SHARADA SIGN JIHVAMULIYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111C2,
+ },
+ [0x111C3]={
+ category="lo",
+ description="SHARADA SIGN UPADHMANIYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111C3,
+ },
+ [0x111C4]={
+ category="lo",
+ description="SHARADA OM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111C4,
+ },
+ [0x111C5]={
+ category="po",
+ description="SHARADA DANDA",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x111C5,
+ },
+ [0x111C6]={
+ category="po",
+ description="SHARADA DOUBLE DANDA",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x111C6,
+ },
+ [0x111C7]={
+ category="po",
+ description="SHARADA ABBREVIATION SIGN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x111C7,
+ },
+ [0x111C8]={
+ category="po",
+ description="SHARADA SEPARATOR",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x111C8,
+ },
+ [0x111D0]={
+ category="nd",
+ description="SHARADA DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x111D0,
+ },
+ [0x111D1]={
+ category="nd",
+ description="SHARADA DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x111D1,
+ },
+ [0x111D2]={
+ category="nd",
+ description="SHARADA DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x111D2,
+ },
+ [0x111D3]={
+ category="nd",
+ description="SHARADA DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x111D3,
+ },
+ [0x111D4]={
+ category="nd",
+ description="SHARADA DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x111D4,
+ },
+ [0x111D5]={
+ category="nd",
+ description="SHARADA DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x111D5,
+ },
+ [0x111D6]={
+ category="nd",
+ description="SHARADA DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x111D6,
+ },
+ [0x111D7]={
+ category="nd",
+ description="SHARADA DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x111D7,
+ },
+ [0x111D8]={
+ category="nd",
+ description="SHARADA DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x111D8,
+ },
+ [0x111D9]={
+ category="nd",
+ description="SHARADA DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x111D9,
+ },
+ [0x11680]={
+ category="lo",
+ description="TAKRI LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11680,
+ },
+ [0x11681]={
+ category="lo",
+ description="TAKRI LETTER AA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11681,
+ },
+ [0x11682]={
+ category="lo",
+ description="TAKRI LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11682,
+ },
+ [0x11683]={
+ category="lo",
+ description="TAKRI LETTER II",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11683,
+ },
+ [0x11684]={
+ category="lo",
+ description="TAKRI LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11684,
+ },
+ [0x11685]={
+ category="lo",
+ description="TAKRI LETTER UU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11685,
+ },
+ [0x11686]={
+ category="lo",
+ description="TAKRI LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11686,
+ },
+ [0x11687]={
+ category="lo",
+ description="TAKRI LETTER AI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11687,
+ },
+ [0x11688]={
+ category="lo",
+ description="TAKRI LETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11688,
+ },
+ [0x11689]={
+ category="lo",
+ description="TAKRI LETTER AU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11689,
+ },
+ [0x1168A]={
+ category="lo",
+ description="TAKRI LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1168A,
+ },
+ [0x1168B]={
+ category="lo",
+ description="TAKRI LETTER KHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1168B,
+ },
+ [0x1168C]={
+ category="lo",
+ description="TAKRI LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1168C,
+ },
+ [0x1168D]={
+ category="lo",
+ description="TAKRI LETTER GHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1168D,
+ },
+ [0x1168E]={
+ category="lo",
+ description="TAKRI LETTER NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1168E,
+ },
+ [0x1168F]={
+ category="lo",
+ description="TAKRI LETTER CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1168F,
+ },
+ [0x11690]={
+ category="lo",
+ description="TAKRI LETTER CHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11690,
+ },
+ [0x11691]={
+ category="lo",
+ description="TAKRI LETTER JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11691,
+ },
+ [0x11692]={
+ category="lo",
+ description="TAKRI LETTER JHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11692,
+ },
+ [0x11693]={
+ category="lo",
+ description="TAKRI LETTER NYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11693,
+ },
+ [0x11694]={
+ category="lo",
+ description="TAKRI LETTER TTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11694,
+ },
+ [0x11695]={
+ category="lo",
+ description="TAKRI LETTER TTHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11695,
+ },
+ [0x11696]={
+ category="lo",
+ description="TAKRI LETTER DDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11696,
+ },
+ [0x11697]={
+ category="lo",
+ description="TAKRI LETTER DDHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11697,
+ },
+ [0x11698]={
+ category="lo",
+ description="TAKRI LETTER NNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11698,
+ },
+ [0x11699]={
+ category="lo",
+ description="TAKRI LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11699,
+ },
+ [0x1169A]={
+ category="lo",
+ description="TAKRI LETTER THA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1169A,
+ },
+ [0x1169B]={
+ category="lo",
+ description="TAKRI LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1169B,
+ },
+ [0x1169C]={
+ category="lo",
+ description="TAKRI LETTER DHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1169C,
+ },
+ [0x1169D]={
+ category="lo",
+ description="TAKRI LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1169D,
+ },
+ [0x1169E]={
+ category="lo",
+ description="TAKRI LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1169E,
+ },
+ [0x1169F]={
+ category="lo",
+ description="TAKRI LETTER PHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1169F,
+ },
+ [0x116A0]={
+ category="lo",
+ description="TAKRI LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x116A0,
+ },
+ [0x116A1]={
+ category="lo",
+ description="TAKRI LETTER BHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x116A1,
+ },
+ [0x116A2]={
+ category="lo",
+ description="TAKRI LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x116A2,
+ },
+ [0x116A3]={
+ category="lo",
+ description="TAKRI LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x116A3,
+ },
+ [0x116A4]={
+ category="lo",
+ description="TAKRI LETTER RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x116A4,
+ },
+ [0x116A5]={
+ category="lo",
+ description="TAKRI LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x116A5,
+ },
+ [0x116A6]={
+ category="lo",
+ description="TAKRI LETTER VA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x116A6,
+ },
+ [0x116A7]={
+ category="lo",
+ description="TAKRI LETTER SHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x116A7,
+ },
+ [0x116A8]={
+ category="lo",
+ description="TAKRI LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x116A8,
+ },
+ [0x116A9]={
+ category="lo",
+ description="TAKRI LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x116A9,
+ },
+ [0x116AA]={
+ category="lo",
+ description="TAKRI LETTER RRA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x116AA,
+ },
+ [0x116AB]={
+ category="mn",
+ description="TAKRI SIGN ANUSVARA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x116AB,
+ },
+ [0x116AC]={
+ category="mc",
+ description="TAKRI SIGN VISARGA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x116AC,
+ },
+ [0x116AD]={
+ category="mn",
+ description="TAKRI VOWEL SIGN AA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x116AD,
+ },
+ [0x116AE]={
+ category="mc",
+ description="TAKRI VOWEL SIGN I",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x116AE,
+ },
+ [0x116AF]={
+ category="mc",
+ description="TAKRI VOWEL SIGN II",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x116AF,
+ },
+ [0x116B0]={
+ category="mn",
+ description="TAKRI VOWEL SIGN U",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x116B0,
+ },
+ [0x116B1]={
+ category="mn",
+ description="TAKRI VOWEL SIGN UU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x116B1,
+ },
+ [0x116B2]={
+ category="mn",
+ description="TAKRI VOWEL SIGN E",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x116B2,
+ },
+ [0x116B3]={
+ category="mn",
+ description="TAKRI VOWEL SIGN AI",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x116B3,
+ },
+ [0x116B4]={
+ category="mn",
+ description="TAKRI VOWEL SIGN O",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x116B4,
+ },
+ [0x116B5]={
+ category="mn",
+ description="TAKRI VOWEL SIGN AU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x116B5,
+ },
+ [0x116B6]={
+ category="mc",
+ description="TAKRI SIGN VIRAMA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x116B6,
+ },
+ [0x116B7]={
+ category="mn",
+ description="TAKRI SIGN NUKTA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x116B7,
+ },
+ [0x116C0]={
+ category="nd",
+ description="TAKRI DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x116C0,
+ },
+ [0x116C1]={
+ category="nd",
+ description="TAKRI DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x116C1,
+ },
+ [0x116C2]={
+ category="nd",
+ description="TAKRI DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x116C2,
+ },
+ [0x116C3]={
+ category="nd",
+ description="TAKRI DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x116C3,
+ },
+ [0x116C4]={
+ category="nd",
+ description="TAKRI DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x116C4,
+ },
+ [0x116C5]={
+ category="nd",
+ description="TAKRI DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x116C5,
+ },
+ [0x116C6]={
+ category="nd",
+ description="TAKRI DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x116C6,
+ },
+ [0x116C7]={
+ category="nd",
+ description="TAKRI DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x116C7,
+ },
+ [0x116C8]={
+ category="nd",
+ description="TAKRI DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x116C8,
+ },
+ [0x116C9]={
+ category="nd",
+ description="TAKRI DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x116C9,
+ },
[0x12000]={
category="lo",
description="CUNEIFORM SIGN A",
@@ -140022,7 +143971,7 @@ characters.data={
description="CUNEIFORM SIGN ARAD TIMES KUR",
direction="l",
linebreak="al",
- mathclass="ord",
+ mathclass="ordinary",
mathname="backprime",
unicodeslot=0x12035,
},
@@ -158002,6 +161951,937 @@ characters.data={
linebreak="al",
unicodeslot=0x16A38,
},
+ [0x16F00]={
+ category="lo",
+ description="MIAO LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F00,
+ },
+ [0x16F01]={
+ category="lo",
+ description="MIAO LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F01,
+ },
+ [0x16F02]={
+ category="lo",
+ description="MIAO LETTER YI PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F02,
+ },
+ [0x16F03]={
+ category="lo",
+ description="MIAO LETTER PLA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F03,
+ },
+ [0x16F04]={
+ category="lo",
+ description="MIAO LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F04,
+ },
+ [0x16F05]={
+ category="lo",
+ description="MIAO LETTER MHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F05,
+ },
+ [0x16F06]={
+ category="lo",
+ description="MIAO LETTER ARCHAIC MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F06,
+ },
+ [0x16F07]={
+ category="lo",
+ description="MIAO LETTER FA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F07,
+ },
+ [0x16F08]={
+ category="lo",
+ description="MIAO LETTER VA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F08,
+ },
+ [0x16F09]={
+ category="lo",
+ description="MIAO LETTER VFA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F09,
+ },
+ [0x16F0A]={
+ category="lo",
+ description="MIAO LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F0A,
+ },
+ [0x16F0B]={
+ category="lo",
+ description="MIAO LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F0B,
+ },
+ [0x16F0C]={
+ category="lo",
+ description="MIAO LETTER YI TTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F0C,
+ },
+ [0x16F0D]={
+ category="lo",
+ description="MIAO LETTER YI TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F0D,
+ },
+ [0x16F0E]={
+ category="lo",
+ description="MIAO LETTER TTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F0E,
+ },
+ [0x16F0F]={
+ category="lo",
+ description="MIAO LETTER DDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F0F,
+ },
+ [0x16F10]={
+ category="lo",
+ description="MIAO LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F10,
+ },
+ [0x16F11]={
+ category="lo",
+ description="MIAO LETTER NHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F11,
+ },
+ [0x16F12]={
+ category="lo",
+ description="MIAO LETTER YI NNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F12,
+ },
+ [0x16F13]={
+ category="lo",
+ description="MIAO LETTER ARCHAIC NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F13,
+ },
+ [0x16F14]={
+ category="lo",
+ description="MIAO LETTER NNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F14,
+ },
+ [0x16F15]={
+ category="lo",
+ description="MIAO LETTER NNHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F15,
+ },
+ [0x16F16]={
+ category="lo",
+ description="MIAO LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F16,
+ },
+ [0x16F17]={
+ category="lo",
+ description="MIAO LETTER LYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F17,
+ },
+ [0x16F18]={
+ category="lo",
+ description="MIAO LETTER LHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F18,
+ },
+ [0x16F19]={
+ category="lo",
+ description="MIAO LETTER LHYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F19,
+ },
+ [0x16F1A]={
+ category="lo",
+ description="MIAO LETTER TLHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F1A,
+ },
+ [0x16F1B]={
+ category="lo",
+ description="MIAO LETTER DLHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F1B,
+ },
+ [0x16F1C]={
+ category="lo",
+ description="MIAO LETTER TLHYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F1C,
+ },
+ [0x16F1D]={
+ category="lo",
+ description="MIAO LETTER DLHYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F1D,
+ },
+ [0x16F1E]={
+ category="lo",
+ description="MIAO LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F1E,
+ },
+ [0x16F1F]={
+ category="lo",
+ description="MIAO LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F1F,
+ },
+ [0x16F20]={
+ category="lo",
+ description="MIAO LETTER YI KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F20,
+ },
+ [0x16F21]={
+ category="lo",
+ description="MIAO LETTER QA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F21,
+ },
+ [0x16F22]={
+ category="lo",
+ description="MIAO LETTER QGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F22,
+ },
+ [0x16F23]={
+ category="lo",
+ description="MIAO LETTER NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F23,
+ },
+ [0x16F24]={
+ category="lo",
+ description="MIAO LETTER NGHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F24,
+ },
+ [0x16F25]={
+ category="lo",
+ description="MIAO LETTER ARCHAIC NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F25,
+ },
+ [0x16F26]={
+ category="lo",
+ description="MIAO LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F26,
+ },
+ [0x16F27]={
+ category="lo",
+ description="MIAO LETTER XA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F27,
+ },
+ [0x16F28]={
+ category="lo",
+ description="MIAO LETTER GHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F28,
+ },
+ [0x16F29]={
+ category="lo",
+ description="MIAO LETTER GHHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F29,
+ },
+ [0x16F2A]={
+ category="lo",
+ description="MIAO LETTER TSSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F2A,
+ },
+ [0x16F2B]={
+ category="lo",
+ description="MIAO LETTER DZZA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F2B,
+ },
+ [0x16F2C]={
+ category="lo",
+ description="MIAO LETTER NYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F2C,
+ },
+ [0x16F2D]={
+ category="lo",
+ description="MIAO LETTER NYHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F2D,
+ },
+ [0x16F2E]={
+ category="lo",
+ description="MIAO LETTER TSHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F2E,
+ },
+ [0x16F2F]={
+ category="lo",
+ description="MIAO LETTER DZHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F2F,
+ },
+ [0x16F30]={
+ category="lo",
+ description="MIAO LETTER YI TSHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F30,
+ },
+ [0x16F31]={
+ category="lo",
+ description="MIAO LETTER YI DZHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F31,
+ },
+ [0x16F32]={
+ category="lo",
+ description="MIAO LETTER REFORMED TSHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F32,
+ },
+ [0x16F33]={
+ category="lo",
+ description="MIAO LETTER SHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F33,
+ },
+ [0x16F34]={
+ category="lo",
+ description="MIAO LETTER SSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F34,
+ },
+ [0x16F35]={
+ category="lo",
+ description="MIAO LETTER ZHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F35,
+ },
+ [0x16F36]={
+ category="lo",
+ description="MIAO LETTER ZSHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F36,
+ },
+ [0x16F37]={
+ category="lo",
+ description="MIAO LETTER TSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F37,
+ },
+ [0x16F38]={
+ category="lo",
+ description="MIAO LETTER DZA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F38,
+ },
+ [0x16F39]={
+ category="lo",
+ description="MIAO LETTER YI TSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F39,
+ },
+ [0x16F3A]={
+ category="lo",
+ description="MIAO LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F3A,
+ },
+ [0x16F3B]={
+ category="lo",
+ description="MIAO LETTER ZA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F3B,
+ },
+ [0x16F3C]={
+ category="lo",
+ description="MIAO LETTER ZSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F3C,
+ },
+ [0x16F3D]={
+ category="lo",
+ description="MIAO LETTER ZZA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F3D,
+ },
+ [0x16F3E]={
+ category="lo",
+ description="MIAO LETTER ZZSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F3E,
+ },
+ [0x16F3F]={
+ category="lo",
+ description="MIAO LETTER ARCHAIC ZZA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F3F,
+ },
+ [0x16F40]={
+ category="lo",
+ description="MIAO LETTER ZZYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F40,
+ },
+ [0x16F41]={
+ category="lo",
+ description="MIAO LETTER ZZSYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F41,
+ },
+ [0x16F42]={
+ category="lo",
+ description="MIAO LETTER WA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F42,
+ },
+ [0x16F43]={
+ category="lo",
+ description="MIAO LETTER AH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F43,
+ },
+ [0x16F44]={
+ category="lo",
+ description="MIAO LETTER HHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F44,
+ },
+ [0x16F50]={
+ category="lo",
+ description="MIAO LETTER NASALIZATION",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F50,
+ },
+ [0x16F51]={
+ category="mc",
+ description="MIAO SIGN ASPIRATION",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F51,
+ },
+ [0x16F52]={
+ category="mc",
+ description="MIAO SIGN REFORMED VOICING",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F52,
+ },
+ [0x16F53]={
+ category="mc",
+ description="MIAO SIGN REFORMED ASPIRATION",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F53,
+ },
+ [0x16F54]={
+ category="mc",
+ description="MIAO VOWEL SIGN A",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F54,
+ },
+ [0x16F55]={
+ category="mc",
+ description="MIAO VOWEL SIGN AA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F55,
+ },
+ [0x16F56]={
+ category="mc",
+ description="MIAO VOWEL SIGN AHH",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F56,
+ },
+ [0x16F57]={
+ category="mc",
+ description="MIAO VOWEL SIGN AN",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F57,
+ },
+ [0x16F58]={
+ category="mc",
+ description="MIAO VOWEL SIGN ANG",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F58,
+ },
+ [0x16F59]={
+ category="mc",
+ description="MIAO VOWEL SIGN O",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F59,
+ },
+ [0x16F5A]={
+ category="mc",
+ description="MIAO VOWEL SIGN OO",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F5A,
+ },
+ [0x16F5B]={
+ category="mc",
+ description="MIAO VOWEL SIGN WO",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F5B,
+ },
+ [0x16F5C]={
+ category="mc",
+ description="MIAO VOWEL SIGN W",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F5C,
+ },
+ [0x16F5D]={
+ category="mc",
+ description="MIAO VOWEL SIGN E",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F5D,
+ },
+ [0x16F5E]={
+ category="mc",
+ description="MIAO VOWEL SIGN EN",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F5E,
+ },
+ [0x16F5F]={
+ category="mc",
+ description="MIAO VOWEL SIGN ENG",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F5F,
+ },
+ [0x16F60]={
+ category="mc",
+ description="MIAO VOWEL SIGN OEY",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F60,
+ },
+ [0x16F61]={
+ category="mc",
+ description="MIAO VOWEL SIGN I",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F61,
+ },
+ [0x16F62]={
+ category="mc",
+ description="MIAO VOWEL SIGN IA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F62,
+ },
+ [0x16F63]={
+ category="mc",
+ description="MIAO VOWEL SIGN IAN",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F63,
+ },
+ [0x16F64]={
+ category="mc",
+ description="MIAO VOWEL SIGN IANG",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F64,
+ },
+ [0x16F65]={
+ category="mc",
+ description="MIAO VOWEL SIGN IO",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F65,
+ },
+ [0x16F66]={
+ category="mc",
+ description="MIAO VOWEL SIGN IE",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F66,
+ },
+ [0x16F67]={
+ category="mc",
+ description="MIAO VOWEL SIGN II",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F67,
+ },
+ [0x16F68]={
+ category="mc",
+ description="MIAO VOWEL SIGN IU",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F68,
+ },
+ [0x16F69]={
+ category="mc",
+ description="MIAO VOWEL SIGN ING",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F69,
+ },
+ [0x16F6A]={
+ category="mc",
+ description="MIAO VOWEL SIGN U",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F6A,
+ },
+ [0x16F6B]={
+ category="mc",
+ description="MIAO VOWEL SIGN UA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F6B,
+ },
+ [0x16F6C]={
+ category="mc",
+ description="MIAO VOWEL SIGN UAN",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F6C,
+ },
+ [0x16F6D]={
+ category="mc",
+ description="MIAO VOWEL SIGN UANG",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F6D,
+ },
+ [0x16F6E]={
+ category="mc",
+ description="MIAO VOWEL SIGN UU",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F6E,
+ },
+ [0x16F6F]={
+ category="mc",
+ description="MIAO VOWEL SIGN UEI",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F6F,
+ },
+ [0x16F70]={
+ category="mc",
+ description="MIAO VOWEL SIGN UNG",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F70,
+ },
+ [0x16F71]={
+ category="mc",
+ description="MIAO VOWEL SIGN Y",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F71,
+ },
+ [0x16F72]={
+ category="mc",
+ description="MIAO VOWEL SIGN YI",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F72,
+ },
+ [0x16F73]={
+ category="mc",
+ description="MIAO VOWEL SIGN AE",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F73,
+ },
+ [0x16F74]={
+ category="mc",
+ description="MIAO VOWEL SIGN AEE",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F74,
+ },
+ [0x16F75]={
+ category="mc",
+ description="MIAO VOWEL SIGN ERR",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F75,
+ },
+ [0x16F76]={
+ category="mc",
+ description="MIAO VOWEL SIGN ROUNDED ERR",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F76,
+ },
+ [0x16F77]={
+ category="mc",
+ description="MIAO VOWEL SIGN ER",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F77,
+ },
+ [0x16F78]={
+ category="mc",
+ description="MIAO VOWEL SIGN ROUNDED ER",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F78,
+ },
+ [0x16F79]={
+ category="mc",
+ description="MIAO VOWEL SIGN AI",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F79,
+ },
+ [0x16F7A]={
+ category="mc",
+ description="MIAO VOWEL SIGN EI",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F7A,
+ },
+ [0x16F7B]={
+ category="mc",
+ description="MIAO VOWEL SIGN AU",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F7B,
+ },
+ [0x16F7C]={
+ category="mc",
+ description="MIAO VOWEL SIGN OU",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F7C,
+ },
+ [0x16F7D]={
+ category="mc",
+ description="MIAO VOWEL SIGN N",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F7D,
+ },
+ [0x16F7E]={
+ category="mc",
+ description="MIAO VOWEL SIGN NG",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x16F7E,
+ },
+ [0x16F8F]={
+ category="mn",
+ description="MIAO TONE RIGHT",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x16F8F,
+ },
+ [0x16F90]={
+ category="mn",
+ description="MIAO TONE TOP RIGHT",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x16F90,
+ },
+ [0x16F91]={
+ category="mn",
+ description="MIAO TONE ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x16F91,
+ },
+ [0x16F92]={
+ category="mn",
+ description="MIAO TONE BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x16F92,
+ },
+ [0x16F93]={
+ category="lm",
+ description="MIAO LETTER TONE-2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F93,
+ },
+ [0x16F94]={
+ category="lm",
+ description="MIAO LETTER TONE-3",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F94,
+ },
+ [0x16F95]={
+ category="lm",
+ description="MIAO LETTER TONE-4",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F95,
+ },
+ [0x16F96]={
+ category="lm",
+ description="MIAO LETTER TONE-5",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F96,
+ },
+ [0x16F97]={
+ category="lm",
+ description="MIAO LETTER TONE-6",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F97,
+ },
+ [0x16F98]={
+ category="lm",
+ description="MIAO LETTER TONE-7",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F98,
+ },
+ [0x16F99]={
+ category="lm",
+ description="MIAO LETTER TONE-8",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F99,
+ },
+ [0x16F9A]={
+ category="lm",
+ description="MIAO LETTER REFORMED TONE-1",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F9A,
+ },
+ [0x16F9B]={
+ category="lm",
+ description="MIAO LETTER REFORMED TONE-2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F9B,
+ },
+ [0x16F9C]={
+ category="lm",
+ description="MIAO LETTER REFORMED TONE-4",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F9C,
+ },
+ [0x16F9D]={
+ category="lm",
+ description="MIAO LETTER REFORMED TONE-5",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F9D,
+ },
+ [0x16F9E]={
+ category="lm",
+ description="MIAO LETTER REFORMED TONE-6",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F9E,
+ },
+ [0x16F9F]={
+ category="lm",
+ description="MIAO LETTER REFORMED TONE-8",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16F9F,
+ },
[0x1B000]={
category="lo",
cjkwd="w",
@@ -168920,11 +173800,11 @@ characters.data={
},
[0x1D6FB]={
category="sm",
+ comment="mathname='nabla'",
description="MATHEMATICAL ITALIC NABLA",
direction="l",
linebreak="al",
mathclass="default",
- mathname="nabla",
specials={ "font", 0x2207 },
unicodeslot=0x1D6FB,
visual="it",
@@ -171227,1425 +176107,2714 @@ characters.data={
specials={ "font", 0x0039 },
unicodeslot=0x1D7FF,
},
+ [0x1EE00]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL ALEF",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0627 },
+ unicodeslot=0x1EE00,
+ },
+ [0x1EE01]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL BEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0628 },
+ unicodeslot=0x1EE01,
+ },
+ [0x1EE02]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL JEEM",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x062C },
+ unicodeslot=0x1EE02,
+ },
+ [0x1EE03]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DAL",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x062F },
+ unicodeslot=0x1EE03,
+ },
+ [0x1EE05]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL WAW",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0648 },
+ unicodeslot=0x1EE05,
+ },
+ [0x1EE06]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL ZAIN",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0632 },
+ unicodeslot=0x1EE06,
+ },
+ [0x1EE07]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL HAH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x062D },
+ unicodeslot=0x1EE07,
+ },
+ [0x1EE08]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL TAH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0637 },
+ unicodeslot=0x1EE08,
+ },
+ [0x1EE09]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL YEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x064A },
+ unicodeslot=0x1EE09,
+ },
+ [0x1EE0A]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL KAF",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0643 },
+ unicodeslot=0x1EE0A,
+ },
+ [0x1EE0B]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL LAM",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0644 },
+ unicodeslot=0x1EE0B,
+ },
+ [0x1EE0C]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL MEEM",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0645 },
+ unicodeslot=0x1EE0C,
+ },
+ [0x1EE0D]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL NOON",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0646 },
+ unicodeslot=0x1EE0D,
+ },
+ [0x1EE0E]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL SEEN",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0633 },
+ unicodeslot=0x1EE0E,
+ },
+ [0x1EE0F]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL AIN",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0639 },
+ unicodeslot=0x1EE0F,
+ },
+ [0x1EE10]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL FEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0641 },
+ unicodeslot=0x1EE10,
+ },
+ [0x1EE11]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL SAD",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0635 },
+ unicodeslot=0x1EE11,
+ },
+ [0x1EE12]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL QAF",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0642 },
+ unicodeslot=0x1EE12,
+ },
+ [0x1EE13]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL REH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0631 },
+ unicodeslot=0x1EE13,
+ },
+ [0x1EE14]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL SHEEN",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0634 },
+ unicodeslot=0x1EE14,
+ },
+ [0x1EE15]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL TEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x062A },
+ unicodeslot=0x1EE15,
+ },
+ [0x1EE16]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL THEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x062B },
+ unicodeslot=0x1EE16,
+ },
+ [0x1EE17]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL KHAH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x062E },
+ unicodeslot=0x1EE17,
+ },
+ [0x1EE18]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL THAL",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0630 },
+ unicodeslot=0x1EE18,
+ },
+ [0x1EE19]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DAD",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0636 },
+ unicodeslot=0x1EE19,
+ },
+ [0x1EE1A]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL ZAH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0638 },
+ unicodeslot=0x1EE1A,
+ },
+ [0x1EE1B]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL GHAIN",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x063A },
+ unicodeslot=0x1EE1B,
+ },
+ [0x1EE1C]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DOTLESS BEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x066E },
+ unicodeslot=0x1EE1C,
+ },
+ [0x1EE1D]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DOTLESS NOON",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x06BA },
+ unicodeslot=0x1EE1D,
+ },
+ [0x1EE1E]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DOTLESS FEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x06A1 },
+ unicodeslot=0x1EE1E,
+ },
+ [0x1EE1F]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DOTLESS QAF",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x066F },
+ unicodeslot=0x1EE1F,
+ },
+ [0x1EE21]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL INITIAL BEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0628 },
+ unicodeslot=0x1EE21,
+ },
+ [0x1EE22]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL INITIAL JEEM",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x062C },
+ unicodeslot=0x1EE22,
+ },
+ [0x1EE24]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL INITIAL HEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0647 },
+ unicodeslot=0x1EE24,
+ },
+ [0x1EE27]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL INITIAL HAH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x062D },
+ unicodeslot=0x1EE27,
+ },
+ [0x1EE29]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL INITIAL YEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x064A },
+ unicodeslot=0x1EE29,
+ },
+ [0x1EE2A]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL INITIAL KAF",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0643 },
+ unicodeslot=0x1EE2A,
+ },
+ [0x1EE2B]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL INITIAL LAM",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0644 },
+ unicodeslot=0x1EE2B,
+ },
+ [0x1EE2C]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL INITIAL MEEM",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0645 },
+ unicodeslot=0x1EE2C,
+ },
+ [0x1EE2D]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL INITIAL NOON",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0646 },
+ unicodeslot=0x1EE2D,
+ },
+ [0x1EE2E]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL INITIAL SEEN",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0633 },
+ unicodeslot=0x1EE2E,
+ },
+ [0x1EE2F]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL INITIAL AIN",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0639 },
+ unicodeslot=0x1EE2F,
+ },
+ [0x1EE30]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL INITIAL FEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0641 },
+ unicodeslot=0x1EE30,
+ },
+ [0x1EE31]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL INITIAL SAD",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0635 },
+ unicodeslot=0x1EE31,
+ },
+ [0x1EE32]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL INITIAL QAF",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0642 },
+ unicodeslot=0x1EE32,
+ },
+ [0x1EE34]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL INITIAL SHEEN",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0634 },
+ unicodeslot=0x1EE34,
+ },
+ [0x1EE35]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL INITIAL TEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x062A },
+ unicodeslot=0x1EE35,
+ },
+ [0x1EE36]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL INITIAL THEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x062B },
+ unicodeslot=0x1EE36,
+ },
+ [0x1EE37]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL INITIAL KHAH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x062E },
+ unicodeslot=0x1EE37,
+ },
+ [0x1EE39]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL INITIAL DAD",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0636 },
+ unicodeslot=0x1EE39,
+ },
+ [0x1EE3B]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL INITIAL GHAIN",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x063A },
+ unicodeslot=0x1EE3B,
+ },
+ [0x1EE42]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL TAILED JEEM",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x062C },
+ unicodeslot=0x1EE42,
+ },
+ [0x1EE47]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL TAILED HAH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x062D },
+ unicodeslot=0x1EE47,
+ },
+ [0x1EE49]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL TAILED YEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x064A },
+ unicodeslot=0x1EE49,
+ },
+ [0x1EE4B]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL TAILED LAM",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0644 },
+ unicodeslot=0x1EE4B,
+ },
+ [0x1EE4D]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL TAILED NOON",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0646 },
+ unicodeslot=0x1EE4D,
+ },
+ [0x1EE4E]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL TAILED SEEN",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0633 },
+ unicodeslot=0x1EE4E,
+ },
+ [0x1EE4F]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL TAILED AIN",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0639 },
+ unicodeslot=0x1EE4F,
+ },
+ [0x1EE51]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL TAILED SAD",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0635 },
+ unicodeslot=0x1EE51,
+ },
+ [0x1EE52]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL TAILED QAF",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0642 },
+ unicodeslot=0x1EE52,
+ },
+ [0x1EE54]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL TAILED SHEEN",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0634 },
+ unicodeslot=0x1EE54,
+ },
+ [0x1EE57]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL TAILED KHAH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x062E },
+ unicodeslot=0x1EE57,
+ },
+ [0x1EE59]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL TAILED DAD",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0636 },
+ unicodeslot=0x1EE59,
+ },
+ [0x1EE5B]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL TAILED GHAIN",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x063A },
+ unicodeslot=0x1EE5B,
+ },
+ [0x1EE5D]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL TAILED DOTLESS NOON",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x06BA },
+ unicodeslot=0x1EE5D,
+ },
+ [0x1EE5F]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL TAILED DOTLESS QAF",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x066F },
+ unicodeslot=0x1EE5F,
+ },
+ [0x1EE61]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL STRETCHED BEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0628 },
+ unicodeslot=0x1EE61,
+ },
+ [0x1EE62]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL STRETCHED JEEM",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x062C },
+ unicodeslot=0x1EE62,
+ },
+ [0x1EE64]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL STRETCHED HEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0647 },
+ unicodeslot=0x1EE64,
+ },
+ [0x1EE67]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL STRETCHED HAH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x062D },
+ unicodeslot=0x1EE67,
+ },
+ [0x1EE68]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL STRETCHED TAH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0637 },
+ unicodeslot=0x1EE68,
+ },
+ [0x1EE69]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL STRETCHED YEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x064A },
+ unicodeslot=0x1EE69,
+ },
+ [0x1EE6A]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL STRETCHED KAF",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0643 },
+ unicodeslot=0x1EE6A,
+ },
+ [0x1EE6C]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL STRETCHED MEEM",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0645 },
+ unicodeslot=0x1EE6C,
+ },
+ [0x1EE6D]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL STRETCHED NOON",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0646 },
+ unicodeslot=0x1EE6D,
+ },
+ [0x1EE6E]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL STRETCHED SEEN",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0633 },
+ unicodeslot=0x1EE6E,
+ },
+ [0x1EE6F]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL STRETCHED AIN",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0639 },
+ unicodeslot=0x1EE6F,
+ },
+ [0x1EE70]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL STRETCHED FEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0641 },
+ unicodeslot=0x1EE70,
+ },
+ [0x1EE71]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL STRETCHED SAD",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0635 },
+ unicodeslot=0x1EE71,
+ },
+ [0x1EE72]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL STRETCHED QAF",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0642 },
+ unicodeslot=0x1EE72,
+ },
+ [0x1EE74]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL STRETCHED SHEEN",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0634 },
+ unicodeslot=0x1EE74,
+ },
+ [0x1EE75]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL STRETCHED TEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x062A },
+ unicodeslot=0x1EE75,
+ },
+ [0x1EE76]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL STRETCHED THEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x062B },
+ unicodeslot=0x1EE76,
+ },
+ [0x1EE77]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL STRETCHED KHAH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x062E },
+ unicodeslot=0x1EE77,
+ },
+ [0x1EE79]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL STRETCHED DAD",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0636 },
+ unicodeslot=0x1EE79,
+ },
+ [0x1EE7A]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL STRETCHED ZAH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0638 },
+ unicodeslot=0x1EE7A,
+ },
+ [0x1EE7B]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL STRETCHED GHAIN",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x063A },
+ unicodeslot=0x1EE7B,
+ },
+ [0x1EE7C]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL STRETCHED DOTLESS BEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x066E },
+ unicodeslot=0x1EE7C,
+ },
+ [0x1EE7E]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL STRETCHED DOTLESS FEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x06A1 },
+ unicodeslot=0x1EE7E,
+ },
+ [0x1EE80]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL LOOPED ALEF",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0627 },
+ unicodeslot=0x1EE80,
+ },
+ [0x1EE81]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL LOOPED BEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0628 },
+ unicodeslot=0x1EE81,
+ },
+ [0x1EE82]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL LOOPED JEEM",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x062C },
+ unicodeslot=0x1EE82,
+ },
+ [0x1EE83]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL LOOPED DAL",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x062F },
+ unicodeslot=0x1EE83,
+ },
+ [0x1EE84]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL LOOPED HEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0647 },
+ unicodeslot=0x1EE84,
+ },
+ [0x1EE85]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL LOOPED WAW",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0648 },
+ unicodeslot=0x1EE85,
+ },
+ [0x1EE86]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL LOOPED ZAIN",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0632 },
+ unicodeslot=0x1EE86,
+ },
+ [0x1EE87]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL LOOPED HAH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x062D },
+ unicodeslot=0x1EE87,
+ },
+ [0x1EE88]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL LOOPED TAH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0637 },
+ unicodeslot=0x1EE88,
+ },
+ [0x1EE89]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL LOOPED YEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x064A },
+ unicodeslot=0x1EE89,
+ },
+ [0x1EE8B]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL LOOPED LAM",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0644 },
+ unicodeslot=0x1EE8B,
+ },
+ [0x1EE8C]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL LOOPED MEEM",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0645 },
+ unicodeslot=0x1EE8C,
+ },
+ [0x1EE8D]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL LOOPED NOON",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0646 },
+ unicodeslot=0x1EE8D,
+ },
+ [0x1EE8E]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL LOOPED SEEN",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0633 },
+ unicodeslot=0x1EE8E,
+ },
+ [0x1EE8F]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL LOOPED AIN",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0639 },
+ unicodeslot=0x1EE8F,
+ },
+ [0x1EE90]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL LOOPED FEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0641 },
+ unicodeslot=0x1EE90,
+ },
+ [0x1EE91]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL LOOPED SAD",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0635 },
+ unicodeslot=0x1EE91,
+ },
+ [0x1EE92]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL LOOPED QAF",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0642 },
+ unicodeslot=0x1EE92,
+ },
+ [0x1EE93]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL LOOPED REH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0631 },
+ unicodeslot=0x1EE93,
+ },
+ [0x1EE94]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL LOOPED SHEEN",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0634 },
+ unicodeslot=0x1EE94,
+ },
+ [0x1EE95]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL LOOPED TEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x062A },
+ unicodeslot=0x1EE95,
+ },
+ [0x1EE96]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL LOOPED THEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x062B },
+ unicodeslot=0x1EE96,
+ },
+ [0x1EE97]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL LOOPED KHAH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x062E },
+ unicodeslot=0x1EE97,
+ },
+ [0x1EE98]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL LOOPED THAL",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0630 },
+ unicodeslot=0x1EE98,
+ },
+ [0x1EE99]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL LOOPED DAD",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0636 },
+ unicodeslot=0x1EE99,
+ },
+ [0x1EE9A]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL LOOPED ZAH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0638 },
+ unicodeslot=0x1EE9A,
+ },
+ [0x1EE9B]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL LOOPED GHAIN",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x063A },
+ unicodeslot=0x1EE9B,
+ },
+ [0x1EEA1]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DOUBLE-STRUCK BEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0628 },
+ unicodeslot=0x1EEA1,
+ },
+ [0x1EEA2]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DOUBLE-STRUCK JEEM",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x062C },
+ unicodeslot=0x1EEA2,
+ },
+ [0x1EEA3]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DOUBLE-STRUCK DAL",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x062F },
+ unicodeslot=0x1EEA3,
+ },
+ [0x1EEA5]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DOUBLE-STRUCK WAW",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0648 },
+ unicodeslot=0x1EEA5,
+ },
+ [0x1EEA6]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DOUBLE-STRUCK ZAIN",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0632 },
+ unicodeslot=0x1EEA6,
+ },
+ [0x1EEA7]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DOUBLE-STRUCK HAH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x062D },
+ unicodeslot=0x1EEA7,
+ },
+ [0x1EEA8]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DOUBLE-STRUCK TAH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0637 },
+ unicodeslot=0x1EEA8,
+ },
+ [0x1EEA9]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DOUBLE-STRUCK YEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x064A },
+ unicodeslot=0x1EEA9,
+ },
+ [0x1EEAB]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DOUBLE-STRUCK LAM",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0644 },
+ unicodeslot=0x1EEAB,
+ },
+ [0x1EEAC]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DOUBLE-STRUCK MEEM",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0645 },
+ unicodeslot=0x1EEAC,
+ },
+ [0x1EEAD]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DOUBLE-STRUCK NOON",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0646 },
+ unicodeslot=0x1EEAD,
+ },
+ [0x1EEAE]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DOUBLE-STRUCK SEEN",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0633 },
+ unicodeslot=0x1EEAE,
+ },
+ [0x1EEAF]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DOUBLE-STRUCK AIN",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0639 },
+ unicodeslot=0x1EEAF,
+ },
+ [0x1EEB0]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DOUBLE-STRUCK FEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0641 },
+ unicodeslot=0x1EEB0,
+ },
+ [0x1EEB1]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DOUBLE-STRUCK SAD",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0635 },
+ unicodeslot=0x1EEB1,
+ },
+ [0x1EEB2]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DOUBLE-STRUCK QAF",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0642 },
+ unicodeslot=0x1EEB2,
+ },
+ [0x1EEB3]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DOUBLE-STRUCK REH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0631 },
+ unicodeslot=0x1EEB3,
+ },
+ [0x1EEB4]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DOUBLE-STRUCK SHEEN",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0634 },
+ unicodeslot=0x1EEB4,
+ },
+ [0x1EEB5]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DOUBLE-STRUCK TEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x062A },
+ unicodeslot=0x1EEB5,
+ },
+ [0x1EEB6]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DOUBLE-STRUCK THEH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x062B },
+ unicodeslot=0x1EEB6,
+ },
+ [0x1EEB7]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DOUBLE-STRUCK KHAH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x062E },
+ unicodeslot=0x1EEB7,
+ },
+ [0x1EEB8]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DOUBLE-STRUCK THAL",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0630 },
+ unicodeslot=0x1EEB8,
+ },
+ [0x1EEB9]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DOUBLE-STRUCK DAD",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0636 },
+ unicodeslot=0x1EEB9,
+ },
+ [0x1EEBA]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DOUBLE-STRUCK ZAH",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x0638 },
+ unicodeslot=0x1EEBA,
+ },
+ [0x1EEBB]={
+ category="lo",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL DOUBLE-STRUCK GHAIN",
+ direction="al",
+ linebreak="al",
+ specials={ "font", 0x063A },
+ unicodeslot=0x1EEBB,
+ },
+ [0x1EEF0]={
+ category="sm",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL OPERATOR MEEM WITH HAH WITH TATWEEL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1EEF0,
+ },
+ [0x1EEF1]={
+ category="sm",
+ comment="check math properties",
+ description="ARABIC MATHEMATICAL OPERATOR HAH WITH DAL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1EEF1,
+ },
[0x1F000]={
category="so",
description="MAHJONG TILE EAST WIND",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F000,
},
[0x1F001]={
category="so",
description="MAHJONG TILE SOUTH WIND",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F001,
},
[0x1F002]={
category="so",
description="MAHJONG TILE WEST WIND",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F002,
},
[0x1F003]={
category="so",
description="MAHJONG TILE NORTH WIND",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F003,
},
[0x1F004]={
category="so",
description="MAHJONG TILE RED DRAGON",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F004,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x1F005]={
category="so",
description="MAHJONG TILE GREEN DRAGON",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F005,
},
[0x1F006]={
category="so",
description="MAHJONG TILE WHITE DRAGON",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F006,
},
[0x1F007]={
category="so",
description="MAHJONG TILE ONE OF CHARACTERS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F007,
},
[0x1F008]={
category="so",
description="MAHJONG TILE TWO OF CHARACTERS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F008,
},
[0x1F009]={
category="so",
description="MAHJONG TILE THREE OF CHARACTERS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F009,
},
[0x1F00A]={
category="so",
description="MAHJONG TILE FOUR OF CHARACTERS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F00A,
},
[0x1F00B]={
category="so",
description="MAHJONG TILE FIVE OF CHARACTERS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F00B,
},
[0x1F00C]={
category="so",
description="MAHJONG TILE SIX OF CHARACTERS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F00C,
},
[0x1F00D]={
category="so",
description="MAHJONG TILE SEVEN OF CHARACTERS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F00D,
},
[0x1F00E]={
category="so",
description="MAHJONG TILE EIGHT OF CHARACTERS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F00E,
},
[0x1F00F]={
category="so",
description="MAHJONG TILE NINE OF CHARACTERS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F00F,
},
[0x1F010]={
category="so",
description="MAHJONG TILE ONE OF BAMBOOS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F010,
},
[0x1F011]={
category="so",
description="MAHJONG TILE TWO OF BAMBOOS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F011,
},
[0x1F012]={
category="so",
description="MAHJONG TILE THREE OF BAMBOOS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F012,
},
[0x1F013]={
category="so",
description="MAHJONG TILE FOUR OF BAMBOOS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F013,
},
[0x1F014]={
category="so",
description="MAHJONG TILE FIVE OF BAMBOOS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F014,
},
[0x1F015]={
category="so",
description="MAHJONG TILE SIX OF BAMBOOS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F015,
},
[0x1F016]={
category="so",
description="MAHJONG TILE SEVEN OF BAMBOOS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F016,
},
[0x1F017]={
category="so",
description="MAHJONG TILE EIGHT OF BAMBOOS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F017,
},
[0x1F018]={
category="so",
description="MAHJONG TILE NINE OF BAMBOOS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F018,
},
[0x1F019]={
category="so",
description="MAHJONG TILE ONE OF CIRCLES",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F019,
},
[0x1F01A]={
category="so",
description="MAHJONG TILE TWO OF CIRCLES",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F01A,
},
[0x1F01B]={
category="so",
description="MAHJONG TILE THREE OF CIRCLES",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F01B,
},
[0x1F01C]={
category="so",
description="MAHJONG TILE FOUR OF CIRCLES",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F01C,
},
[0x1F01D]={
category="so",
description="MAHJONG TILE FIVE OF CIRCLES",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F01D,
},
[0x1F01E]={
category="so",
description="MAHJONG TILE SIX OF CIRCLES",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F01E,
},
[0x1F01F]={
category="so",
description="MAHJONG TILE SEVEN OF CIRCLES",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F01F,
},
[0x1F020]={
category="so",
description="MAHJONG TILE EIGHT OF CIRCLES",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F020,
},
[0x1F021]={
category="so",
description="MAHJONG TILE NINE OF CIRCLES",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F021,
},
[0x1F022]={
category="so",
description="MAHJONG TILE PLUM",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F022,
},
[0x1F023]={
category="so",
description="MAHJONG TILE ORCHID",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F023,
},
[0x1F024]={
category="so",
description="MAHJONG TILE BAMBOO",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F024,
},
[0x1F025]={
category="so",
description="MAHJONG TILE CHRYSANTHEMUM",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F025,
},
[0x1F026]={
category="so",
description="MAHJONG TILE SPRING",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F026,
},
[0x1F027]={
category="so",
description="MAHJONG TILE SUMMER",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F027,
},
[0x1F028]={
category="so",
description="MAHJONG TILE AUTUMN",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F028,
},
[0x1F029]={
category="so",
description="MAHJONG TILE WINTER",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F029,
},
[0x1F02A]={
category="so",
description="MAHJONG TILE JOKER",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F02A,
},
[0x1F02B]={
category="so",
description="MAHJONG TILE BACK",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F02B,
},
[0x1F030]={
category="so",
description="DOMINO TILE HORIZONTAL BACK",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F030,
},
[0x1F031]={
category="so",
description="DOMINO TILE HORIZONTAL-00-00",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F031,
},
[0x1F032]={
category="so",
description="DOMINO TILE HORIZONTAL-00-01",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F032,
},
[0x1F033]={
category="so",
description="DOMINO TILE HORIZONTAL-00-02",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F033,
},
[0x1F034]={
category="so",
description="DOMINO TILE HORIZONTAL-00-03",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F034,
},
[0x1F035]={
category="so",
description="DOMINO TILE HORIZONTAL-00-04",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F035,
},
[0x1F036]={
category="so",
description="DOMINO TILE HORIZONTAL-00-05",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F036,
},
[0x1F037]={
category="so",
description="DOMINO TILE HORIZONTAL-00-06",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F037,
},
[0x1F038]={
category="so",
description="DOMINO TILE HORIZONTAL-01-00",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F038,
},
[0x1F039]={
category="so",
description="DOMINO TILE HORIZONTAL-01-01",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F039,
},
[0x1F03A]={
category="so",
description="DOMINO TILE HORIZONTAL-01-02",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F03A,
},
[0x1F03B]={
category="so",
description="DOMINO TILE HORIZONTAL-01-03",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F03B,
},
[0x1F03C]={
category="so",
description="DOMINO TILE HORIZONTAL-01-04",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F03C,
},
[0x1F03D]={
category="so",
description="DOMINO TILE HORIZONTAL-01-05",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F03D,
},
[0x1F03E]={
category="so",
description="DOMINO TILE HORIZONTAL-01-06",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F03E,
},
[0x1F03F]={
category="so",
description="DOMINO TILE HORIZONTAL-02-00",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F03F,
},
[0x1F040]={
category="so",
description="DOMINO TILE HORIZONTAL-02-01",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F040,
},
[0x1F041]={
category="so",
description="DOMINO TILE HORIZONTAL-02-02",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F041,
},
[0x1F042]={
category="so",
description="DOMINO TILE HORIZONTAL-02-03",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F042,
},
[0x1F043]={
category="so",
description="DOMINO TILE HORIZONTAL-02-04",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F043,
},
[0x1F044]={
category="so",
description="DOMINO TILE HORIZONTAL-02-05",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F044,
},
[0x1F045]={
category="so",
description="DOMINO TILE HORIZONTAL-02-06",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F045,
},
[0x1F046]={
category="so",
description="DOMINO TILE HORIZONTAL-03-00",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F046,
},
[0x1F047]={
category="so",
description="DOMINO TILE HORIZONTAL-03-01",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F047,
},
[0x1F048]={
category="so",
description="DOMINO TILE HORIZONTAL-03-02",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F048,
},
[0x1F049]={
category="so",
description="DOMINO TILE HORIZONTAL-03-03",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F049,
},
[0x1F04A]={
category="so",
description="DOMINO TILE HORIZONTAL-03-04",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F04A,
},
[0x1F04B]={
category="so",
description="DOMINO TILE HORIZONTAL-03-05",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F04B,
},
[0x1F04C]={
category="so",
description="DOMINO TILE HORIZONTAL-03-06",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F04C,
},
[0x1F04D]={
category="so",
description="DOMINO TILE HORIZONTAL-04-00",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F04D,
},
[0x1F04E]={
category="so",
description="DOMINO TILE HORIZONTAL-04-01",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F04E,
},
[0x1F04F]={
category="so",
description="DOMINO TILE HORIZONTAL-04-02",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F04F,
},
[0x1F050]={
category="so",
description="DOMINO TILE HORIZONTAL-04-03",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F050,
},
[0x1F051]={
category="so",
description="DOMINO TILE HORIZONTAL-04-04",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F051,
},
[0x1F052]={
category="so",
description="DOMINO TILE HORIZONTAL-04-05",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F052,
},
[0x1F053]={
category="so",
description="DOMINO TILE HORIZONTAL-04-06",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F053,
},
[0x1F054]={
category="so",
description="DOMINO TILE HORIZONTAL-05-00",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F054,
},
[0x1F055]={
category="so",
description="DOMINO TILE HORIZONTAL-05-01",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F055,
},
[0x1F056]={
category="so",
description="DOMINO TILE HORIZONTAL-05-02",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F056,
},
[0x1F057]={
category="so",
description="DOMINO TILE HORIZONTAL-05-03",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F057,
},
[0x1F058]={
category="so",
description="DOMINO TILE HORIZONTAL-05-04",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F058,
},
[0x1F059]={
category="so",
description="DOMINO TILE HORIZONTAL-05-05",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F059,
},
[0x1F05A]={
category="so",
description="DOMINO TILE HORIZONTAL-05-06",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F05A,
},
[0x1F05B]={
category="so",
description="DOMINO TILE HORIZONTAL-06-00",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F05B,
},
[0x1F05C]={
category="so",
description="DOMINO TILE HORIZONTAL-06-01",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F05C,
},
[0x1F05D]={
category="so",
description="DOMINO TILE HORIZONTAL-06-02",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F05D,
},
[0x1F05E]={
category="so",
description="DOMINO TILE HORIZONTAL-06-03",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F05E,
},
[0x1F05F]={
category="so",
description="DOMINO TILE HORIZONTAL-06-04",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F05F,
},
[0x1F060]={
category="so",
description="DOMINO TILE HORIZONTAL-06-05",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F060,
},
[0x1F061]={
category="so",
description="DOMINO TILE HORIZONTAL-06-06",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F061,
},
[0x1F062]={
category="so",
description="DOMINO TILE VERTICAL BACK",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F062,
},
[0x1F063]={
category="so",
description="DOMINO TILE VERTICAL-00-00",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F063,
},
[0x1F064]={
category="so",
description="DOMINO TILE VERTICAL-00-01",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F064,
},
[0x1F065]={
category="so",
description="DOMINO TILE VERTICAL-00-02",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F065,
},
[0x1F066]={
category="so",
description="DOMINO TILE VERTICAL-00-03",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F066,
},
[0x1F067]={
category="so",
description="DOMINO TILE VERTICAL-00-04",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F067,
},
[0x1F068]={
category="so",
description="DOMINO TILE VERTICAL-00-05",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F068,
},
[0x1F069]={
category="so",
description="DOMINO TILE VERTICAL-00-06",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F069,
},
[0x1F06A]={
category="so",
description="DOMINO TILE VERTICAL-01-00",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F06A,
},
[0x1F06B]={
category="so",
description="DOMINO TILE VERTICAL-01-01",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F06B,
},
[0x1F06C]={
category="so",
description="DOMINO TILE VERTICAL-01-02",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F06C,
},
[0x1F06D]={
category="so",
description="DOMINO TILE VERTICAL-01-03",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F06D,
},
[0x1F06E]={
category="so",
description="DOMINO TILE VERTICAL-01-04",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F06E,
},
[0x1F06F]={
category="so",
description="DOMINO TILE VERTICAL-01-05",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F06F,
},
[0x1F070]={
category="so",
description="DOMINO TILE VERTICAL-01-06",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F070,
},
[0x1F071]={
category="so",
description="DOMINO TILE VERTICAL-02-00",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F071,
},
[0x1F072]={
category="so",
description="DOMINO TILE VERTICAL-02-01",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F072,
},
[0x1F073]={
category="so",
description="DOMINO TILE VERTICAL-02-02",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F073,
},
[0x1F074]={
category="so",
description="DOMINO TILE VERTICAL-02-03",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F074,
},
[0x1F075]={
category="so",
description="DOMINO TILE VERTICAL-02-04",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F075,
},
[0x1F076]={
category="so",
description="DOMINO TILE VERTICAL-02-05",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F076,
},
[0x1F077]={
category="so",
description="DOMINO TILE VERTICAL-02-06",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F077,
},
[0x1F078]={
category="so",
description="DOMINO TILE VERTICAL-03-00",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F078,
},
[0x1F079]={
category="so",
description="DOMINO TILE VERTICAL-03-01",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F079,
},
[0x1F07A]={
category="so",
description="DOMINO TILE VERTICAL-03-02",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F07A,
},
[0x1F07B]={
category="so",
description="DOMINO TILE VERTICAL-03-03",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F07B,
},
[0x1F07C]={
category="so",
description="DOMINO TILE VERTICAL-03-04",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F07C,
},
[0x1F07D]={
category="so",
description="DOMINO TILE VERTICAL-03-05",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F07D,
},
[0x1F07E]={
category="so",
description="DOMINO TILE VERTICAL-03-06",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F07E,
},
[0x1F07F]={
category="so",
description="DOMINO TILE VERTICAL-04-00",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F07F,
},
[0x1F080]={
category="so",
description="DOMINO TILE VERTICAL-04-01",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F080,
},
[0x1F081]={
category="so",
description="DOMINO TILE VERTICAL-04-02",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F081,
},
[0x1F082]={
category="so",
description="DOMINO TILE VERTICAL-04-03",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F082,
},
[0x1F083]={
category="so",
description="DOMINO TILE VERTICAL-04-04",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F083,
},
[0x1F084]={
category="so",
description="DOMINO TILE VERTICAL-04-05",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F084,
},
[0x1F085]={
category="so",
description="DOMINO TILE VERTICAL-04-06",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F085,
},
[0x1F086]={
category="so",
description="DOMINO TILE VERTICAL-05-00",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F086,
},
[0x1F087]={
category="so",
description="DOMINO TILE VERTICAL-05-01",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F087,
},
[0x1F088]={
category="so",
description="DOMINO TILE VERTICAL-05-02",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F088,
},
[0x1F089]={
category="so",
description="DOMINO TILE VERTICAL-05-03",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F089,
},
[0x1F08A]={
category="so",
description="DOMINO TILE VERTICAL-05-04",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F08A,
},
[0x1F08B]={
category="so",
description="DOMINO TILE VERTICAL-05-05",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F08B,
},
[0x1F08C]={
category="so",
description="DOMINO TILE VERTICAL-05-06",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F08C,
},
[0x1F08D]={
category="so",
description="DOMINO TILE VERTICAL-06-00",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F08D,
},
[0x1F08E]={
category="so",
description="DOMINO TILE VERTICAL-06-01",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F08E,
},
[0x1F08F]={
category="so",
description="DOMINO TILE VERTICAL-06-02",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F08F,
},
[0x1F090]={
category="so",
description="DOMINO TILE VERTICAL-06-03",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F090,
},
[0x1F091]={
category="so",
description="DOMINO TILE VERTICAL-06-04",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F091,
},
[0x1F092]={
category="so",
description="DOMINO TILE VERTICAL-06-05",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F092,
},
[0x1F093]={
category="so",
description="DOMINO TILE VERTICAL-06-06",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F093,
},
[0x1F0A0]={
category="so",
description="PLAYING CARD BACK",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0A0,
},
[0x1F0A1]={
category="so",
description="PLAYING CARD ACE OF SPADES",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0A1,
},
[0x1F0A2]={
category="so",
description="PLAYING CARD TWO OF SPADES",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0A2,
},
[0x1F0A3]={
category="so",
description="PLAYING CARD THREE OF SPADES",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0A3,
},
[0x1F0A4]={
category="so",
description="PLAYING CARD FOUR OF SPADES",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0A4,
},
[0x1F0A5]={
category="so",
description="PLAYING CARD FIVE OF SPADES",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0A5,
},
[0x1F0A6]={
category="so",
description="PLAYING CARD SIX OF SPADES",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0A6,
},
[0x1F0A7]={
category="so",
description="PLAYING CARD SEVEN OF SPADES",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0A7,
},
[0x1F0A8]={
category="so",
description="PLAYING CARD EIGHT OF SPADES",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0A8,
},
[0x1F0A9]={
category="so",
description="PLAYING CARD NINE OF SPADES",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0A9,
},
[0x1F0AA]={
category="so",
description="PLAYING CARD TEN OF SPADES",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0AA,
},
[0x1F0AB]={
category="so",
description="PLAYING CARD JACK OF SPADES",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0AB,
},
[0x1F0AC]={
category="so",
description="PLAYING CARD KNIGHT OF SPADES",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0AC,
},
[0x1F0AD]={
category="so",
description="PLAYING CARD QUEEN OF SPADES",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0AD,
},
[0x1F0AE]={
category="so",
description="PLAYING CARD KING OF SPADES",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0AE,
},
[0x1F0B1]={
category="so",
description="PLAYING CARD ACE OF HEARTS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0B1,
},
[0x1F0B2]={
category="so",
description="PLAYING CARD TWO OF HEARTS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0B2,
},
[0x1F0B3]={
category="so",
description="PLAYING CARD THREE OF HEARTS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0B3,
},
[0x1F0B4]={
category="so",
description="PLAYING CARD FOUR OF HEARTS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0B4,
},
[0x1F0B5]={
category="so",
description="PLAYING CARD FIVE OF HEARTS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0B5,
},
[0x1F0B6]={
category="so",
description="PLAYING CARD SIX OF HEARTS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0B6,
},
[0x1F0B7]={
category="so",
description="PLAYING CARD SEVEN OF HEARTS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0B7,
},
[0x1F0B8]={
category="so",
description="PLAYING CARD EIGHT OF HEARTS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0B8,
},
[0x1F0B9]={
category="so",
description="PLAYING CARD NINE OF HEARTS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0B9,
},
[0x1F0BA]={
category="so",
description="PLAYING CARD TEN OF HEARTS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0BA,
},
[0x1F0BB]={
category="so",
description="PLAYING CARD JACK OF HEARTS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0BB,
},
[0x1F0BC]={
category="so",
description="PLAYING CARD KNIGHT OF HEARTS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0BC,
},
[0x1F0BD]={
category="so",
description="PLAYING CARD QUEEN OF HEARTS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0BD,
},
[0x1F0BE]={
category="so",
description="PLAYING CARD KING OF HEARTS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0BE,
},
[0x1F0C1]={
category="so",
description="PLAYING CARD ACE OF DIAMONDS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0C1,
},
[0x1F0C2]={
category="so",
description="PLAYING CARD TWO OF DIAMONDS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0C2,
},
[0x1F0C3]={
category="so",
description="PLAYING CARD THREE OF DIAMONDS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0C3,
},
[0x1F0C4]={
category="so",
description="PLAYING CARD FOUR OF DIAMONDS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0C4,
},
[0x1F0C5]={
category="so",
description="PLAYING CARD FIVE OF DIAMONDS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0C5,
},
[0x1F0C6]={
category="so",
description="PLAYING CARD SIX OF DIAMONDS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0C6,
},
[0x1F0C7]={
category="so",
description="PLAYING CARD SEVEN OF DIAMONDS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0C7,
},
[0x1F0C8]={
category="so",
description="PLAYING CARD EIGHT OF DIAMONDS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0C8,
},
[0x1F0C9]={
category="so",
description="PLAYING CARD NINE OF DIAMONDS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0C9,
},
[0x1F0CA]={
category="so",
description="PLAYING CARD TEN OF DIAMONDS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0CA,
},
[0x1F0CB]={
category="so",
description="PLAYING CARD JACK OF DIAMONDS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0CB,
},
[0x1F0CC]={
category="so",
description="PLAYING CARD KNIGHT OF DIAMONDS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0CC,
},
[0x1F0CD]={
category="so",
description="PLAYING CARD QUEEN OF DIAMONDS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0CD,
},
[0x1F0CE]={
category="so",
description="PLAYING CARD KING OF DIAMONDS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0CE,
},
[0x1F0CF]={
category="so",
description="PLAYING CARD BLACK JOKER",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0CF,
},
[0x1F0D1]={
category="so",
description="PLAYING CARD ACE OF CLUBS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0D1,
},
[0x1F0D2]={
category="so",
description="PLAYING CARD TWO OF CLUBS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0D2,
},
[0x1F0D3]={
category="so",
description="PLAYING CARD THREE OF CLUBS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0D3,
},
[0x1F0D4]={
category="so",
description="PLAYING CARD FOUR OF CLUBS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0D4,
},
[0x1F0D5]={
category="so",
description="PLAYING CARD FIVE OF CLUBS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0D5,
},
[0x1F0D6]={
category="so",
description="PLAYING CARD SIX OF CLUBS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0D6,
},
[0x1F0D7]={
category="so",
description="PLAYING CARD SEVEN OF CLUBS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0D7,
},
[0x1F0D8]={
category="so",
description="PLAYING CARD EIGHT OF CLUBS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0D8,
},
[0x1F0D9]={
category="so",
description="PLAYING CARD NINE OF CLUBS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0D9,
},
[0x1F0DA]={
category="so",
description="PLAYING CARD TEN OF CLUBS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0DA,
},
[0x1F0DB]={
category="so",
description="PLAYING CARD JACK OF CLUBS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0DB,
},
[0x1F0DC]={
category="so",
description="PLAYING CARD KNIGHT OF CLUBS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0DC,
},
[0x1F0DD]={
category="so",
description="PLAYING CARD QUEEN OF CLUBS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0DD,
},
[0x1F0DE]={
category="so",
description="PLAYING CARD KING OF CLUBS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0DE,
},
[0x1F0DF]={
category="so",
description="PLAYING CARD WHITE JOKER",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F0DF,
},
[0x1F100]={
@@ -173521,6 +179690,22 @@ characters.data={
linebreak="ai",
unicodeslot=0x1F169,
},
+ [0x1F16A]={
+ category="so",
+ description="RAISED MC SIGN",
+ direction="on",
+ linebreak="al",
+ specials={ "super", 0x004D, 0x0043 },
+ unicodeslot=0x1F16A,
+ },
+ [0x1F16B]={
+ category="so",
+ description="RAISED MD SIGN",
+ direction="on",
+ linebreak="al",
+ specials={ "super", 0x004D, 0x0044 },
+ unicodeslot=0x1F16B,
+ },
[0x1F170]={
category="so",
cjkwd="a",
@@ -173648,6 +179833,10 @@ characters.data={
direction="l",
linebreak="ai",
unicodeslot=0x1F17F,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x1F180]={
category="so",
@@ -173870,182 +180059,182 @@ characters.data={
category="so",
description="REGIONAL INDICATOR SYMBOL LETTER A",
direction="l",
- linebreak="al",
+ linebreak="ri",
unicodeslot=0x1F1E6,
},
[0x1F1E7]={
category="so",
description="REGIONAL INDICATOR SYMBOL LETTER B",
direction="l",
- linebreak="al",
+ linebreak="ri",
unicodeslot=0x1F1E7,
},
[0x1F1E8]={
category="so",
description="REGIONAL INDICATOR SYMBOL LETTER C",
direction="l",
- linebreak="al",
+ linebreak="ri",
unicodeslot=0x1F1E8,
},
[0x1F1E9]={
category="so",
description="REGIONAL INDICATOR SYMBOL LETTER D",
direction="l",
- linebreak="al",
+ linebreak="ri",
unicodeslot=0x1F1E9,
},
[0x1F1EA]={
category="so",
description="REGIONAL INDICATOR SYMBOL LETTER E",
direction="l",
- linebreak="al",
+ linebreak="ri",
unicodeslot=0x1F1EA,
},
[0x1F1EB]={
category="so",
description="REGIONAL INDICATOR SYMBOL LETTER F",
direction="l",
- linebreak="al",
+ linebreak="ri",
unicodeslot=0x1F1EB,
},
[0x1F1EC]={
category="so",
description="REGIONAL INDICATOR SYMBOL LETTER G",
direction="l",
- linebreak="al",
+ linebreak="ri",
unicodeslot=0x1F1EC,
},
[0x1F1ED]={
category="so",
description="REGIONAL INDICATOR SYMBOL LETTER H",
direction="l",
- linebreak="al",
+ linebreak="ri",
unicodeslot=0x1F1ED,
},
[0x1F1EE]={
category="so",
description="REGIONAL INDICATOR SYMBOL LETTER I",
direction="l",
- linebreak="al",
+ linebreak="ri",
unicodeslot=0x1F1EE,
},
[0x1F1EF]={
category="so",
description="REGIONAL INDICATOR SYMBOL LETTER J",
direction="l",
- linebreak="al",
+ linebreak="ri",
unicodeslot=0x1F1EF,
},
[0x1F1F0]={
category="so",
description="REGIONAL INDICATOR SYMBOL LETTER K",
direction="l",
- linebreak="al",
+ linebreak="ri",
unicodeslot=0x1F1F0,
},
[0x1F1F1]={
category="so",
description="REGIONAL INDICATOR SYMBOL LETTER L",
direction="l",
- linebreak="al",
+ linebreak="ri",
unicodeslot=0x1F1F1,
},
[0x1F1F2]={
category="so",
description="REGIONAL INDICATOR SYMBOL LETTER M",
direction="l",
- linebreak="al",
+ linebreak="ri",
unicodeslot=0x1F1F2,
},
[0x1F1F3]={
category="so",
description="REGIONAL INDICATOR SYMBOL LETTER N",
direction="l",
- linebreak="al",
+ linebreak="ri",
unicodeslot=0x1F1F3,
},
[0x1F1F4]={
category="so",
description="REGIONAL INDICATOR SYMBOL LETTER O",
direction="l",
- linebreak="al",
+ linebreak="ri",
unicodeslot=0x1F1F4,
},
[0x1F1F5]={
category="so",
description="REGIONAL INDICATOR SYMBOL LETTER P",
direction="l",
- linebreak="al",
+ linebreak="ri",
unicodeslot=0x1F1F5,
},
[0x1F1F6]={
category="so",
description="REGIONAL INDICATOR SYMBOL LETTER Q",
direction="l",
- linebreak="al",
+ linebreak="ri",
unicodeslot=0x1F1F6,
},
[0x1F1F7]={
category="so",
description="REGIONAL INDICATOR SYMBOL LETTER R",
direction="l",
- linebreak="al",
+ linebreak="ri",
unicodeslot=0x1F1F7,
},
[0x1F1F8]={
category="so",
description="REGIONAL INDICATOR SYMBOL LETTER S",
direction="l",
- linebreak="al",
+ linebreak="ri",
unicodeslot=0x1F1F8,
},
[0x1F1F9]={
category="so",
description="REGIONAL INDICATOR SYMBOL LETTER T",
direction="l",
- linebreak="al",
+ linebreak="ri",
unicodeslot=0x1F1F9,
},
[0x1F1FA]={
category="so",
description="REGIONAL INDICATOR SYMBOL LETTER U",
direction="l",
- linebreak="al",
+ linebreak="ri",
unicodeslot=0x1F1FA,
},
[0x1F1FB]={
category="so",
description="REGIONAL INDICATOR SYMBOL LETTER V",
direction="l",
- linebreak="al",
+ linebreak="ri",
unicodeslot=0x1F1FB,
},
[0x1F1FC]={
category="so",
description="REGIONAL INDICATOR SYMBOL LETTER W",
direction="l",
- linebreak="al",
+ linebreak="ri",
unicodeslot=0x1F1FC,
},
[0x1F1FD]={
category="so",
description="REGIONAL INDICATOR SYMBOL LETTER X",
direction="l",
- linebreak="al",
+ linebreak="ri",
unicodeslot=0x1F1FD,
},
[0x1F1FE]={
category="so",
description="REGIONAL INDICATOR SYMBOL LETTER Y",
direction="l",
- linebreak="al",
+ linebreak="ri",
unicodeslot=0x1F1FE,
},
[0x1F1FF]={
category="so",
description="REGIONAL INDICATOR SYMBOL LETTER Z",
direction="l",
- linebreak="al",
+ linebreak="ri",
unicodeslot=0x1F1FF,
},
[0x1F200]={
@@ -174173,6 +180362,10 @@ characters.data={
linebreak="id",
specials={ "square", 0x7121 },
unicodeslot=0x1F21A,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x1F21B]={
category="so",
@@ -174362,6 +180555,10 @@ characters.data={
linebreak="id",
specials={ "square", 0x6307 },
unicodeslot=0x1F22F,
+ variants={
+ [0xFE0E]="text style",
+ [0xFE0F]="emoji style",
+ },
},
[0x1F230]={
category="so",
@@ -174565,1050 +180762,1050 @@ characters.data={
category="so",
description="CYCLONE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F300,
},
[0x1F301]={
category="so",
description="FOGGY",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F301,
},
[0x1F302]={
category="so",
description="CLOSED UMBRELLA",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F302,
},
[0x1F303]={
category="so",
description="NIGHT WITH STARS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F303,
},
[0x1F304]={
category="so",
description="SUNRISE OVER MOUNTAINS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F304,
},
[0x1F305]={
category="so",
description="SUNRISE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F305,
},
[0x1F306]={
category="so",
description="CITYSCAPE AT DUSK",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F306,
},
[0x1F307]={
category="so",
description="SUNSET OVER BUILDINGS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F307,
},
[0x1F308]={
category="so",
description="RAINBOW",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F308,
},
[0x1F309]={
category="so",
description="BRIDGE AT NIGHT",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F309,
},
[0x1F30A]={
category="so",
description="WATER WAVE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F30A,
},
[0x1F30B]={
category="so",
description="VOLCANO",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F30B,
},
[0x1F30C]={
category="so",
description="MILKY WAY",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F30C,
},
[0x1F30D]={
category="so",
description="EARTH GLOBE EUROPE-AFRICA",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F30D,
},
[0x1F30E]={
category="so",
description="EARTH GLOBE AMERICAS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F30E,
},
[0x1F30F]={
category="so",
description="EARTH GLOBE ASIA-AUSTRALIA",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F30F,
},
[0x1F310]={
category="so",
description="GLOBE WITH MERIDIANS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F310,
},
[0x1F311]={
category="so",
description="NEW MOON SYMBOL",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F311,
},
[0x1F312]={
category="so",
description="WAXING CRESCENT MOON SYMBOL",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F312,
},
[0x1F313]={
category="so",
description="FIRST QUARTER MOON SYMBOL",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F313,
},
[0x1F314]={
category="so",
description="WAXING GIBBOUS MOON SYMBOL",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F314,
},
[0x1F315]={
category="so",
description="FULL MOON SYMBOL",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F315,
},
[0x1F316]={
category="so",
description="WANING GIBBOUS MOON SYMBOL",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F316,
},
[0x1F317]={
category="so",
description="LAST QUARTER MOON SYMBOL",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F317,
},
[0x1F318]={
category="so",
description="WANING CRESCENT MOON SYMBOL",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F318,
},
[0x1F319]={
category="so",
description="CRESCENT MOON",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F319,
},
[0x1F31A]={
category="so",
description="NEW MOON WITH FACE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F31A,
},
[0x1F31B]={
category="so",
description="FIRST QUARTER MOON WITH FACE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F31B,
},
[0x1F31C]={
category="so",
description="LAST QUARTER MOON WITH FACE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F31C,
},
[0x1F31D]={
category="so",
description="FULL MOON WITH FACE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F31D,
},
[0x1F31E]={
category="so",
description="SUN WITH FACE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F31E,
},
[0x1F31F]={
category="so",
description="GLOWING STAR",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F31F,
},
[0x1F320]={
category="so",
description="SHOOTING STAR",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F320,
},
[0x1F330]={
category="so",
description="CHESTNUT",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F330,
},
[0x1F331]={
category="so",
description="SEEDLING",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F331,
},
[0x1F332]={
category="so",
description="EVERGREEN TREE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F332,
},
[0x1F333]={
category="so",
description="DECIDUOUS TREE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F333,
},
[0x1F334]={
category="so",
description="PALM TREE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F334,
},
[0x1F335]={
category="so",
description="CACTUS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F335,
},
[0x1F337]={
category="so",
description="TULIP",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F337,
},
[0x1F338]={
category="so",
description="CHERRY BLOSSOM",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F338,
},
[0x1F339]={
category="so",
description="ROSE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F339,
},
[0x1F33A]={
category="so",
description="HIBISCUS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F33A,
},
[0x1F33B]={
category="so",
description="SUNFLOWER",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F33B,
},
[0x1F33C]={
category="so",
description="BLOSSOM",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F33C,
},
[0x1F33D]={
category="so",
description="EAR OF MAIZE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F33D,
},
[0x1F33E]={
category="so",
description="EAR OF RICE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F33E,
},
[0x1F33F]={
category="so",
description="HERB",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F33F,
},
[0x1F340]={
category="so",
description="FOUR LEAF CLOVER",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F340,
},
[0x1F341]={
category="so",
description="MAPLE LEAF",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F341,
},
[0x1F342]={
category="so",
description="FALLEN LEAF",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F342,
},
[0x1F343]={
category="so",
description="LEAF FLUTTERING IN WIND",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F343,
},
[0x1F344]={
category="so",
description="MUSHROOM",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F344,
},
[0x1F345]={
category="so",
description="TOMATO",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F345,
},
[0x1F346]={
category="so",
description="AUBERGINE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F346,
},
[0x1F347]={
category="so",
description="GRAPES",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F347,
},
[0x1F348]={
category="so",
description="MELON",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F348,
},
[0x1F349]={
category="so",
description="WATERMELON",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F349,
},
[0x1F34A]={
category="so",
description="TANGERINE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F34A,
},
[0x1F34B]={
category="so",
description="LEMON",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F34B,
},
[0x1F34C]={
category="so",
description="BANANA",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F34C,
},
[0x1F34D]={
category="so",
description="PINEAPPLE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F34D,
},
[0x1F34E]={
category="so",
description="RED APPLE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F34E,
},
[0x1F34F]={
category="so",
description="GREEN APPLE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F34F,
},
[0x1F350]={
category="so",
description="PEAR",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F350,
},
[0x1F351]={
category="so",
description="PEACH",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F351,
},
[0x1F352]={
category="so",
description="CHERRIES",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F352,
},
[0x1F353]={
category="so",
description="STRAWBERRY",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F353,
},
[0x1F354]={
category="so",
description="HAMBURGER",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F354,
},
[0x1F355]={
category="so",
description="SLICE OF PIZZA",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F355,
},
[0x1F356]={
category="so",
description="MEAT ON BONE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F356,
},
[0x1F357]={
category="so",
description="POULTRY LEG",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F357,
},
[0x1F358]={
category="so",
description="RICE CRACKER",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F358,
},
[0x1F359]={
category="so",
description="RICE BALL",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F359,
},
[0x1F35A]={
category="so",
description="COOKED RICE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F35A,
},
[0x1F35B]={
category="so",
description="CURRY AND RICE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F35B,
},
[0x1F35C]={
category="so",
description="STEAMING BOWL",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F35C,
},
[0x1F35D]={
category="so",
description="SPAGHETTI",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F35D,
},
[0x1F35E]={
category="so",
description="BREAD",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F35E,
},
[0x1F35F]={
category="so",
description="FRENCH FRIES",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F35F,
},
[0x1F360]={
category="so",
description="ROASTED SWEET POTATO",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F360,
},
[0x1F361]={
category="so",
description="DANGO",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F361,
},
[0x1F362]={
category="so",
description="ODEN",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F362,
},
[0x1F363]={
category="so",
description="SUSHI",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F363,
},
[0x1F364]={
category="so",
description="FRIED SHRIMP",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F364,
},
[0x1F365]={
category="so",
description="FISH CAKE WITH SWIRL DESIGN",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F365,
},
[0x1F366]={
category="so",
description="SOFT ICE CREAM",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F366,
},
[0x1F367]={
category="so",
description="SHAVED ICE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F367,
},
[0x1F368]={
category="so",
description="ICE CREAM",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F368,
},
[0x1F369]={
category="so",
description="DOUGHNUT",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F369,
},
[0x1F36A]={
category="so",
description="COOKIE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F36A,
},
[0x1F36B]={
category="so",
description="CHOCOLATE BAR",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F36B,
},
[0x1F36C]={
category="so",
description="CANDY",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F36C,
},
[0x1F36D]={
category="so",
description="LOLLIPOP",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F36D,
},
[0x1F36E]={
category="so",
description="CUSTARD",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F36E,
},
[0x1F36F]={
category="so",
description="HONEY POT",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F36F,
},
[0x1F370]={
category="so",
description="SHORTCAKE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F370,
},
[0x1F371]={
category="so",
description="BENTO BOX",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F371,
},
[0x1F372]={
category="so",
description="POT OF FOOD",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F372,
},
[0x1F373]={
category="so",
description="COOKING",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F373,
},
[0x1F374]={
category="so",
description="FORK AND KNIFE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F374,
},
[0x1F375]={
category="so",
description="TEACUP WITHOUT HANDLE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F375,
},
[0x1F376]={
category="so",
description="SAKE BOTTLE AND CUP",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F376,
},
[0x1F377]={
category="so",
description="WINE GLASS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F377,
},
[0x1F378]={
category="so",
description="COCKTAIL GLASS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F378,
},
[0x1F379]={
category="so",
description="TROPICAL DRINK",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F379,
},
[0x1F37A]={
category="so",
description="BEER MUG",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F37A,
},
[0x1F37B]={
category="so",
description="CLINKING BEER MUGS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F37B,
},
[0x1F37C]={
category="so",
description="BABY BOTTLE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F37C,
},
[0x1F380]={
category="so",
description="RIBBON",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F380,
},
[0x1F381]={
category="so",
description="WRAPPED PRESENT",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F381,
},
[0x1F382]={
category="so",
description="BIRTHDAY CAKE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F382,
},
[0x1F383]={
category="so",
description="JACK-O-LANTERN",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F383,
},
[0x1F384]={
category="so",
description="CHRISTMAS TREE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F384,
},
[0x1F385]={
category="so",
description="FATHER CHRISTMAS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F385,
},
[0x1F386]={
category="so",
description="FIREWORKS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F386,
},
[0x1F387]={
category="so",
description="FIREWORK SPARKLER",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F387,
},
[0x1F388]={
category="so",
description="BALLOON",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F388,
},
[0x1F389]={
category="so",
description="PARTY POPPER",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F389,
},
[0x1F38A]={
category="so",
description="CONFETTI BALL",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F38A,
},
[0x1F38B]={
category="so",
description="TANABATA TREE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F38B,
},
[0x1F38C]={
category="so",
description="CROSSED FLAGS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F38C,
},
[0x1F38D]={
category="so",
description="PINE DECORATION",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F38D,
},
[0x1F38E]={
category="so",
description="JAPANESE DOLLS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F38E,
},
[0x1F38F]={
category="so",
description="CARP STREAMER",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F38F,
},
[0x1F390]={
category="so",
description="WIND CHIME",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F390,
},
[0x1F391]={
category="so",
description="MOON VIEWING CEREMONY",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F391,
},
[0x1F392]={
category="so",
description="SCHOOL SATCHEL",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F392,
},
[0x1F393]={
category="so",
description="GRADUATION CAP",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F393,
},
[0x1F3A0]={
category="so",
description="CAROUSEL HORSE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F3A0,
},
[0x1F3A1]={
category="so",
description="FERRIS WHEEL",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F3A1,
},
[0x1F3A2]={
category="so",
description="ROLLER COASTER",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F3A2,
},
[0x1F3A3]={
category="so",
description="FISHING POLE AND FISH",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F3A3,
},
[0x1F3A4]={
category="so",
description="MICROPHONE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F3A4,
},
[0x1F3A5]={
category="so",
description="MOVIE CAMERA",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F3A5,
},
[0x1F3A6]={
category="so",
description="CINEMA",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F3A6,
},
[0x1F3A7]={
category="so",
description="HEADPHONE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F3A7,
},
[0x1F3A8]={
category="so",
description="ARTIST PALETTE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F3A8,
},
[0x1F3A9]={
category="so",
description="TOP HAT",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F3A9,
},
[0x1F3AA]={
category="so",
description="CIRCUS TENT",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F3AA,
},
[0x1F3AB]={
category="so",
description="TICKET",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F3AB,
},
[0x1F3AC]={
category="so",
description="CLAPPER BOARD",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F3AC,
},
[0x1F3AD]={
category="so",
description="PERFORMING ARTS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F3AD,
},
[0x1F3AE]={
category="so",
description="VIDEO GAME",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F3AE,
},
[0x1F3AF]={
category="so",
description="DIRECT HIT",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F3AF,
},
[0x1F3B0]={
category="so",
description="SLOT MACHINE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F3B0,
},
[0x1F3B1]={
category="so",
description="BILLIARDS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F3B1,
},
[0x1F3B2]={
category="so",
description="GAME DIE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F3B2,
},
[0x1F3B3]={
category="so",
description="BOWLING",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F3B3,
},
[0x1F3B4]={
category="so",
description="FLOWER PLAYING CARDS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F3B4,
},
[0x1F3B5]={
@@ -175629,35 +181826,35 @@ characters.data={
category="so",
description="SAXOPHONE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F3B7,
},
[0x1F3B8]={
category="so",
description="GUITAR",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F3B8,
},
[0x1F3B9]={
category="so",
description="MUSICAL KEYBOARD",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F3B9,
},
[0x1F3BA]={
category="so",
description="TRUMPET",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F3BA,
},
[0x1F3BB]={
category="so",
description="VIOLIN",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F3BB,
},
[0x1F3BC]={
@@ -175671,1316 +181868,1316 @@ characters.data={
category="so",
description="RUNNING SHIRT WITH SASH",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F3BD,
},
[0x1F3BE]={
category="so",
description="TENNIS RACQUET AND BALL",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F3BE,
},
[0x1F3BF]={
category="so",
description="SKI AND SKI BOOT",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F3BF,
},
[0x1F3C0]={
category="so",
description="BASKETBALL AND HOOP",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F3C0,
},
[0x1F3C1]={
category="so",
description="CHEQUERED FLAG",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F3C1,
},
[0x1F3C2]={
category="so",
description="SNOWBOARDER",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F3C2,
},
[0x1F3C3]={
category="so",
description="RUNNER",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F3C3,
},
[0x1F3C4]={
category="so",
description="SURFER",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F3C4,
},
[0x1F3C6]={
category="so",
description="TROPHY",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F3C6,
},
[0x1F3C7]={
category="so",
description="HORSE RACING",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F3C7,
},
[0x1F3C8]={
category="so",
description="AMERICAN FOOTBALL",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F3C8,
},
[0x1F3C9]={
category="so",
description="RUGBY FOOTBALL",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F3C9,
},
[0x1F3CA]={
category="so",
description="SWIMMER",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F3CA,
},
[0x1F3E0]={
category="so",
description="HOUSE BUILDING",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F3E0,
},
[0x1F3E1]={
category="so",
description="HOUSE WITH GARDEN",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F3E1,
},
[0x1F3E2]={
category="so",
description="OFFICE BUILDING",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F3E2,
},
[0x1F3E3]={
category="so",
description="JAPANESE POST OFFICE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F3E3,
},
[0x1F3E4]={
category="so",
description="EUROPEAN POST OFFICE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F3E4,
},
[0x1F3E5]={
category="so",
description="HOSPITAL",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F3E5,
},
[0x1F3E6]={
category="so",
description="BANK",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F3E6,
},
[0x1F3E7]={
category="so",
description="AUTOMATED TELLER MACHINE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F3E7,
},
[0x1F3E8]={
category="so",
description="HOTEL",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F3E8,
},
[0x1F3E9]={
category="so",
description="LOVE HOTEL",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F3E9,
},
[0x1F3EA]={
category="so",
description="CONVENIENCE STORE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F3EA,
},
[0x1F3EB]={
category="so",
description="SCHOOL",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F3EB,
},
[0x1F3EC]={
category="so",
description="DEPARTMENT STORE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F3EC,
},
[0x1F3ED]={
category="so",
description="FACTORY",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F3ED,
},
[0x1F3EE]={
category="so",
description="IZAKAYA LANTERN",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F3EE,
},
[0x1F3EF]={
category="so",
description="JAPANESE CASTLE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F3EF,
},
[0x1F3F0]={
category="so",
description="EUROPEAN CASTLE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F3F0,
},
[0x1F400]={
category="so",
description="RAT",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F400,
},
[0x1F401]={
category="so",
description="MOUSE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F401,
},
[0x1F402]={
category="so",
description="OX",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F402,
},
[0x1F403]={
category="so",
description="WATER BUFFALO",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F403,
},
[0x1F404]={
category="so",
description="COW",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F404,
},
[0x1F405]={
category="so",
description="TIGER",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F405,
},
[0x1F406]={
category="so",
description="LEOPARD",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F406,
},
[0x1F407]={
category="so",
description="RABBIT",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F407,
},
[0x1F408]={
category="so",
description="CAT",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F408,
},
[0x1F409]={
category="so",
description="DRAGON",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F409,
},
[0x1F40A]={
category="so",
description="CROCODILE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F40A,
},
[0x1F40B]={
category="so",
description="WHALE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F40B,
},
[0x1F40C]={
category="so",
description="SNAIL",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F40C,
},
[0x1F40D]={
category="so",
description="SNAKE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F40D,
},
[0x1F40E]={
category="so",
description="HORSE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F40E,
},
[0x1F40F]={
category="so",
description="RAM",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F40F,
},
[0x1F410]={
category="so",
description="GOAT",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F410,
},
[0x1F411]={
category="so",
description="SHEEP",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F411,
},
[0x1F412]={
category="so",
description="MONKEY",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F412,
},
[0x1F413]={
category="so",
description="ROOSTER",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F413,
},
[0x1F414]={
category="so",
description="CHICKEN",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F414,
},
[0x1F415]={
category="so",
description="DOG",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F415,
},
[0x1F416]={
category="so",
description="PIG",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F416,
},
[0x1F417]={
category="so",
description="BOAR",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F417,
},
[0x1F418]={
category="so",
description="ELEPHANT",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F418,
},
[0x1F419]={
category="so",
description="OCTOPUS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F419,
},
[0x1F41A]={
category="so",
description="SPIRAL SHELL",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F41A,
},
[0x1F41B]={
category="so",
description="BUG",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F41B,
},
[0x1F41C]={
category="so",
description="ANT",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F41C,
},
[0x1F41D]={
category="so",
description="HONEYBEE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F41D,
},
[0x1F41E]={
category="so",
description="LADY BEETLE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F41E,
},
[0x1F41F]={
category="so",
description="FISH",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F41F,
},
[0x1F420]={
category="so",
description="TROPICAL FISH",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F420,
},
[0x1F421]={
category="so",
description="BLOWFISH",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F421,
},
[0x1F422]={
category="so",
description="TURTLE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F422,
},
[0x1F423]={
category="so",
description="HATCHING CHICK",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F423,
},
[0x1F424]={
category="so",
description="BABY CHICK",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F424,
},
[0x1F425]={
category="so",
description="FRONT-FACING BABY CHICK",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F425,
},
[0x1F426]={
category="so",
description="BIRD",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F426,
},
[0x1F427]={
category="so",
description="PENGUIN",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F427,
},
[0x1F428]={
category="so",
description="KOALA",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F428,
},
[0x1F429]={
category="so",
description="POODLE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F429,
},
[0x1F42A]={
category="so",
description="DROMEDARY CAMEL",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F42A,
},
[0x1F42B]={
category="so",
description="BACTRIAN CAMEL",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F42B,
},
[0x1F42C]={
category="so",
description="DOLPHIN",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F42C,
},
[0x1F42D]={
category="so",
description="MOUSE FACE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F42D,
},
[0x1F42E]={
category="so",
description="COW FACE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F42E,
},
[0x1F42F]={
category="so",
description="TIGER FACE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F42F,
},
[0x1F430]={
category="so",
description="RABBIT FACE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F430,
},
[0x1F431]={
category="so",
description="CAT FACE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F431,
},
[0x1F432]={
category="so",
description="DRAGON FACE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F432,
},
[0x1F433]={
category="so",
description="SPOUTING WHALE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F433,
},
[0x1F434]={
category="so",
description="HORSE FACE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F434,
},
[0x1F435]={
category="so",
description="MONKEY FACE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F435,
},
[0x1F436]={
category="so",
description="DOG FACE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F436,
},
[0x1F437]={
category="so",
description="PIG FACE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F437,
},
[0x1F438]={
category="so",
description="FROG FACE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F438,
},
[0x1F439]={
category="so",
description="HAMSTER FACE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F439,
},
[0x1F43A]={
category="so",
description="WOLF FACE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F43A,
},
[0x1F43B]={
category="so",
description="BEAR FACE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F43B,
},
[0x1F43C]={
category="so",
description="PANDA FACE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F43C,
},
[0x1F43D]={
category="so",
description="PIG NOSE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F43D,
},
[0x1F43E]={
category="so",
description="PAW PRINTS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F43E,
},
[0x1F440]={
category="so",
description="EYES",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F440,
},
[0x1F442]={
category="so",
description="EAR",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F442,
},
[0x1F443]={
category="so",
description="NOSE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F443,
},
[0x1F444]={
category="so",
description="MOUTH",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F444,
},
[0x1F445]={
category="so",
description="TONGUE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F445,
},
[0x1F446]={
category="so",
description="WHITE UP POINTING BACKHAND INDEX",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F446,
},
[0x1F447]={
category="so",
description="WHITE DOWN POINTING BACKHAND INDEX",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F447,
},
[0x1F448]={
category="so",
description="WHITE LEFT POINTING BACKHAND INDEX",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F448,
},
[0x1F449]={
category="so",
description="WHITE RIGHT POINTING BACKHAND INDEX",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F449,
},
[0x1F44A]={
category="so",
description="FISTED HAND SIGN",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F44A,
},
[0x1F44B]={
category="so",
description="WAVING HAND SIGN",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F44B,
},
[0x1F44C]={
category="so",
description="OK HAND SIGN",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F44C,
},
[0x1F44D]={
category="so",
description="THUMBS UP SIGN",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F44D,
},
[0x1F44E]={
category="so",
description="THUMBS DOWN SIGN",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F44E,
},
[0x1F44F]={
category="so",
description="CLAPPING HANDS SIGN",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F44F,
},
[0x1F450]={
category="so",
description="OPEN HANDS SIGN",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F450,
},
[0x1F451]={
category="so",
description="CROWN",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F451,
},
[0x1F452]={
category="so",
description="WOMANS HAT",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F452,
},
[0x1F453]={
category="so",
description="EYEGLASSES",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F453,
},
[0x1F454]={
category="so",
description="NECKTIE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F454,
},
[0x1F455]={
category="so",
description="T-SHIRT",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F455,
},
[0x1F456]={
category="so",
description="JEANS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F456,
},
[0x1F457]={
category="so",
description="DRESS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F457,
},
[0x1F458]={
category="so",
description="KIMONO",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F458,
},
[0x1F459]={
category="so",
description="BIKINI",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F459,
},
[0x1F45A]={
category="so",
description="WOMANS CLOTHES",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F45A,
},
[0x1F45B]={
category="so",
description="PURSE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F45B,
},
[0x1F45C]={
category="so",
description="HANDBAG",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F45C,
},
[0x1F45D]={
category="so",
description="POUCH",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F45D,
},
[0x1F45E]={
category="so",
description="MANS SHOE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F45E,
},
[0x1F45F]={
category="so",
description="ATHLETIC SHOE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F45F,
},
[0x1F460]={
category="so",
description="HIGH-HEELED SHOE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F460,
},
[0x1F461]={
category="so",
description="WOMANS SANDAL",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F461,
},
[0x1F462]={
category="so",
description="WOMANS BOOTS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F462,
},
[0x1F463]={
category="so",
description="FOOTPRINTS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F463,
},
[0x1F464]={
category="so",
description="BUST IN SILHOUETTE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F464,
},
[0x1F465]={
category="so",
description="BUSTS IN SILHOUETTE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F465,
},
[0x1F466]={
category="so",
description="BOY",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F466,
},
[0x1F467]={
category="so",
description="GIRL",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F467,
},
[0x1F468]={
category="so",
description="MAN",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F468,
},
[0x1F469]={
category="so",
description="WOMAN",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F469,
},
[0x1F46A]={
category="so",
description="FAMILY",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F46A,
},
[0x1F46B]={
category="so",
description="MAN AND WOMAN HOLDING HANDS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F46B,
},
[0x1F46C]={
category="so",
description="TWO MEN HOLDING HANDS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F46C,
},
[0x1F46D]={
category="so",
description="TWO WOMEN HOLDING HANDS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F46D,
},
[0x1F46E]={
category="so",
description="POLICE OFFICER",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F46E,
},
[0x1F46F]={
category="so",
description="WOMAN WITH BUNNY EARS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F46F,
},
[0x1F470]={
category="so",
description="BRIDE WITH VEIL",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F470,
},
[0x1F471]={
category="so",
description="PERSON WITH BLOND HAIR",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F471,
},
[0x1F472]={
category="so",
description="MAN WITH GUA PI MAO",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F472,
},
[0x1F473]={
category="so",
description="MAN WITH TURBAN",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F473,
},
[0x1F474]={
category="so",
description="OLDER MAN",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F474,
},
[0x1F475]={
category="so",
description="OLDER WOMAN",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F475,
},
[0x1F476]={
category="so",
description="BABY",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F476,
},
[0x1F477]={
category="so",
description="CONSTRUCTION WORKER",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F477,
},
[0x1F478]={
category="so",
description="PRINCESS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F478,
},
[0x1F479]={
category="so",
description="JAPANESE OGRE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F479,
},
[0x1F47A]={
category="so",
description="JAPANESE GOBLIN",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F47A,
},
[0x1F47B]={
category="so",
description="GHOST",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F47B,
},
[0x1F47C]={
category="so",
description="BABY ANGEL",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F47C,
},
[0x1F47D]={
category="so",
description="EXTRATERRESTRIAL ALIEN",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F47D,
},
[0x1F47E]={
category="so",
description="ALIEN MONSTER",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F47E,
},
[0x1F47F]={
category="so",
description="IMP",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F47F,
},
[0x1F480]={
category="so",
description="SKULL",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F480,
},
[0x1F481]={
category="so",
description="INFORMATION DESK PERSON",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F481,
},
[0x1F482]={
category="so",
description="GUARDSMAN",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F482,
},
[0x1F483]={
category="so",
description="DANCER",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F483,
},
[0x1F484]={
category="so",
description="LIPSTICK",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F484,
},
[0x1F485]={
category="so",
description="NAIL POLISH",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F485,
},
[0x1F486]={
category="so",
description="FACE MASSAGE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F486,
},
[0x1F487]={
category="so",
description="HAIRCUT",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F487,
},
[0x1F488]={
category="so",
description="BARBER POLE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F488,
},
[0x1F489]={
category="so",
description="SYRINGE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F489,
},
[0x1F48A]={
category="so",
description="PILL",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F48A,
},
[0x1F48B]={
category="so",
description="KISS MARK",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F48B,
},
[0x1F48C]={
category="so",
description="LOVE LETTER",
- direction="l",
- linebreak="al",
+ direction="on",
+ linebreak="id",
unicodeslot=0x1F48C,
},
[0x1F48D]={
category="so",
description="RING",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F48D,
},
[0x1F48E]={
category="so",
description="GEM STONE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F48E,
},
[0x1F48F]={
category="so",
description="KISS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F48F,
},
[0x1F490]={
category="so",
description="BOUQUET",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F490,
},
[0x1F491]={
category="so",
description="COUPLE WITH HEART",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F491,
},
[0x1F492]={
category="so",
description="WEDDING",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F492,
},
[0x1F493]={
category="so",
description="BEATING HEART",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F493,
},
[0x1F494]={
category="so",
description="BROKEN HEART",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F494,
},
[0x1F495]={
category="so",
description="TWO HEARTS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F495,
},
[0x1F496]={
category="so",
description="SPARKLING HEART",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F496,
},
[0x1F497]={
category="so",
description="GROWING HEART",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F497,
},
[0x1F498]={
category="so",
description="HEART WITH ARROW",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F498,
},
[0x1F499]={
category="so",
description="BLUE HEART",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F499,
},
[0x1F49A]={
category="so",
description="GREEN HEART",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F49A,
},
[0x1F49B]={
category="so",
description="YELLOW HEART",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F49B,
},
[0x1F49C]={
category="so",
description="PURPLE HEART",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F49C,
},
[0x1F49D]={
category="so",
description="HEART WITH RIBBON",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F49D,
},
[0x1F49E]={
category="so",
description="REVOLVING HEARTS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F49E,
},
[0x1F49F]={
category="so",
description="HEART DECORATION",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F49F,
},
[0x1F4A0]={
@@ -176994,7 +183191,7 @@ characters.data={
category="so",
description="ELECTRIC LIGHT BULB",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4A1,
},
[0x1F4A2]={
@@ -177008,7 +183205,7 @@ characters.data={
category="so",
description="BOMB",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4A3,
},
[0x1F4A4]={
@@ -177022,70 +183219,70 @@ characters.data={
category="so",
description="COLLISION SYMBOL",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4A5,
},
[0x1F4A6]={
category="so",
description="SPLASHING SWEAT SYMBOL",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4A6,
},
[0x1F4A7]={
category="so",
description="DROPLET",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4A7,
},
[0x1F4A8]={
category="so",
description="DASH SYMBOL",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4A8,
},
[0x1F4A9]={
category="so",
description="PILE OF POO",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4A9,
},
[0x1F4AA]={
category="so",
description="FLEXED BICEPS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4AA,
},
[0x1F4AB]={
category="so",
description="DIZZY SYMBOL",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4AB,
},
[0x1F4AC]={
category="so",
description="SPEECH BALLOON",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4AC,
},
[0x1F4AD]={
category="so",
description="THOUGHT BALLOON",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4AD,
},
[0x1F4AE]={
category="so",
description="WHITE FLOWER",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4AE,
},
[0x1F4AF]={
@@ -177099,7 +183296,7 @@ characters.data={
category="so",
description="MONEY BAG",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4B0,
},
[0x1F4B1]={
@@ -177120,511 +183317,511 @@ characters.data={
category="so",
description="CREDIT CARD",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4B3,
},
[0x1F4B4]={
category="so",
description="BANKNOTE WITH YEN SIGN",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4B4,
},
[0x1F4B5]={
category="so",
description="BANKNOTE WITH DOLLAR SIGN",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4B5,
},
[0x1F4B6]={
category="so",
description="BANKNOTE WITH EURO SIGN",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4B6,
},
[0x1F4B7]={
category="so",
description="BANKNOTE WITH POUND SIGN",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4B7,
},
[0x1F4B8]={
category="so",
description="MONEY WITH WINGS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4B8,
},
[0x1F4B9]={
category="so",
description="CHART WITH UPWARDS TREND AND YEN SIGN",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4B9,
},
[0x1F4BA]={
category="so",
description="SEAT",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4BA,
},
[0x1F4BB]={
category="so",
description="PERSONAL COMPUTER",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4BB,
},
[0x1F4BC]={
category="so",
description="BRIEFCASE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4BC,
},
[0x1F4BD]={
category="so",
description="MINIDISC",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4BD,
},
[0x1F4BE]={
category="so",
description="FLOPPY DISK",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4BE,
},
[0x1F4BF]={
category="so",
description="OPTICAL DISC",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4BF,
},
[0x1F4C0]={
category="so",
description="DVD",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4C0,
},
[0x1F4C1]={
category="so",
description="FILE FOLDER",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4C1,
},
[0x1F4C2]={
category="so",
description="OPEN FILE FOLDER",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4C2,
},
[0x1F4C3]={
category="so",
description="PAGE WITH CURL",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4C3,
},
[0x1F4C4]={
category="so",
description="PAGE FACING UP",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4C4,
},
[0x1F4C5]={
category="so",
description="CALENDAR",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4C5,
},
[0x1F4C6]={
category="so",
description="TEAR-OFF CALENDAR",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4C6,
},
[0x1F4C7]={
category="so",
description="CARD INDEX",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4C7,
},
[0x1F4C8]={
category="so",
description="CHART WITH UPWARDS TREND",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4C8,
},
[0x1F4C9]={
category="so",
description="CHART WITH DOWNWARDS TREND",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4C9,
},
[0x1F4CA]={
category="so",
description="BAR CHART",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4CA,
},
[0x1F4CB]={
category="so",
description="CLIPBOARD",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4CB,
},
[0x1F4CC]={
category="so",
description="PUSHPIN",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4CC,
},
[0x1F4CD]={
category="so",
description="ROUND PUSHPIN",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4CD,
},
[0x1F4CE]={
category="so",
description="PAPERCLIP",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4CE,
},
[0x1F4CF]={
category="so",
description="STRAIGHT RULER",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4CF,
},
[0x1F4D0]={
category="so",
description="TRIANGULAR RULER",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4D0,
},
[0x1F4D1]={
category="so",
description="BOOKMARK TABS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4D1,
},
[0x1F4D2]={
category="so",
description="LEDGER",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4D2,
},
[0x1F4D3]={
category="so",
description="NOTEBOOK",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4D3,
},
[0x1F4D4]={
category="so",
description="NOTEBOOK WITH DECORATIVE COVER",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4D4,
},
[0x1F4D5]={
category="so",
description="CLOSED BOOK",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4D5,
},
[0x1F4D6]={
category="so",
description="OPEN BOOK",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4D6,
},
[0x1F4D7]={
category="so",
description="GREEN BOOK",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4D7,
},
[0x1F4D8]={
category="so",
description="BLUE BOOK",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4D8,
},
[0x1F4D9]={
category="so",
description="ORANGE BOOK",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4D9,
},
[0x1F4DA]={
category="so",
description="BOOKS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4DA,
},
[0x1F4DB]={
category="so",
description="NAME BADGE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4DB,
},
[0x1F4DC]={
category="so",
description="SCROLL",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4DC,
},
[0x1F4DD]={
category="so",
description="MEMO",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4DD,
},
[0x1F4DE]={
category="so",
description="TELEPHONE RECEIVER",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4DE,
},
[0x1F4DF]={
category="so",
description="PAGER",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4DF,
},
[0x1F4E0]={
category="so",
description="FAX MACHINE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4E0,
},
[0x1F4E1]={
category="so",
description="SATELLITE ANTENNA",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4E1,
},
[0x1F4E2]={
category="so",
description="PUBLIC ADDRESS LOUDSPEAKER",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4E2,
},
[0x1F4E3]={
category="so",
description="CHEERING MEGAPHONE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4E3,
},
[0x1F4E4]={
category="so",
description="OUTBOX TRAY",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4E4,
},
[0x1F4E5]={
category="so",
description="INBOX TRAY",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4E5,
},
[0x1F4E6]={
category="so",
description="PACKAGE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4E6,
},
[0x1F4E7]={
category="so",
description="E-MAIL SYMBOL",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4E7,
},
[0x1F4E8]={
category="so",
description="INCOMING ENVELOPE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4E8,
},
[0x1F4E9]={
category="so",
description="ENVELOPE WITH DOWNWARDS ARROW ABOVE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4E9,
},
[0x1F4EA]={
category="so",
description="CLOSED MAILBOX WITH LOWERED FLAG",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4EA,
},
[0x1F4EB]={
category="so",
description="CLOSED MAILBOX WITH RAISED FLAG",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4EB,
},
[0x1F4EC]={
category="so",
description="OPEN MAILBOX WITH RAISED FLAG",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4EC,
},
[0x1F4ED]={
category="so",
description="OPEN MAILBOX WITH LOWERED FLAG",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4ED,
},
[0x1F4EE]={
category="so",
description="POSTBOX",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4EE,
},
[0x1F4EF]={
category="so",
description="POSTAL HORN",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4EF,
},
[0x1F4F0]={
category="so",
description="NEWSPAPER",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4F0,
},
[0x1F4F1]={
category="so",
description="MOBILE PHONE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4F1,
},
[0x1F4F2]={
category="so",
description="MOBILE PHONE WITH RIGHTWARDS ARROW AT LEFT",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4F2,
},
[0x1F4F3]={
category="so",
description="VIBRATION MODE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4F3,
},
[0x1F4F4]={
category="so",
description="MOBILE PHONE OFF",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4F4,
},
[0x1F4F5]={
category="so",
description="NO MOBILE PHONES",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4F5,
},
[0x1F4F6]={
category="so",
description="ANTENNA WITH BARS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4F6,
},
[0x1F4F7]={
category="so",
description="CAMERA",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4F7,
},
[0x1F4F9]={
category="so",
description="VIDEO CAMERA",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4F9,
},
[0x1F4FA]={
category="so",
description="TELEVISION",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4FA,
},
[0x1F4FB]={
category="so",
description="RADIO",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4FB,
},
[0x1F4FC]={
category="so",
description="VIDEOCASSETTE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F4FC,
},
[0x1F500]={
@@ -177680,112 +183877,112 @@ characters.data={
category="so",
description="SPEAKER WITH CANCELLATION STROKE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F507,
},
[0x1F508]={
category="so",
description="SPEAKER",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F508,
},
[0x1F509]={
category="so",
description="SPEAKER WITH ONE SOUND WAVE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F509,
},
[0x1F50A]={
category="so",
description="SPEAKER WITH THREE SOUND WAVES",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F50A,
},
[0x1F50B]={
category="so",
description="BATTERY",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F50B,
},
[0x1F50C]={
category="so",
description="ELECTRIC PLUG",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F50C,
},
[0x1F50D]={
category="so",
description="LEFT-POINTING MAGNIFYING GLASS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F50D,
},
[0x1F50E]={
category="so",
description="RIGHT-POINTING MAGNIFYING GLASS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F50E,
},
[0x1F50F]={
category="so",
description="LOCK WITH INK PEN",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F50F,
},
[0x1F510]={
category="so",
description="CLOSED LOCK WITH KEY",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F510,
},
[0x1F511]={
category="so",
description="KEY",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F511,
},
[0x1F512]={
category="so",
description="LOCK",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F512,
},
[0x1F513]={
category="so",
description="OPEN LOCK",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F513,
},
[0x1F514]={
category="so",
description="BELL",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F514,
},
[0x1F515]={
category="so",
description="BELL WITH CANCELLATION STROKE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F515,
},
[0x1F516]={
category="so",
description="BOOKMARK",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F516,
},
[0x1F517]={
@@ -177882,7 +184079,7 @@ characters.data={
[0x1F524]={
category="so",
description="INPUT SYMBOL FOR LATIN LETTERS",
- direction="l",
+ direction="on",
linebreak="al",
unicodeslot=0x1F524,
},
@@ -177890,91 +184087,91 @@ characters.data={
category="so",
description="FIRE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F525,
},
[0x1F526]={
category="so",
description="ELECTRIC TORCH",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F526,
},
[0x1F527]={
category="so",
description="WRENCH",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F527,
},
[0x1F528]={
category="so",
description="HAMMER",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F528,
},
[0x1F529]={
category="so",
description="NUT AND BOLT",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F529,
},
[0x1F52A]={
category="so",
description="HOCHO",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F52A,
},
[0x1F52B]={
category="so",
description="PISTOL",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F52B,
},
[0x1F52C]={
category="so",
description="MICROSCOPE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F52C,
},
[0x1F52D]={
category="so",
description="TELESCOPE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F52D,
},
[0x1F52E]={
category="so",
description="CRYSTAL BALL",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F52E,
},
[0x1F52F]={
category="so",
description="SIX POINTED STAR WITH MIDDLE DOT",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F52F,
},
[0x1F530]={
category="so",
description="JAPANESE SYMBOL FOR BEGINNER",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F530,
},
[0x1F531]={
category="so",
description="TRIDENT EMBLEM",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F531,
},
[0x1F532]={
@@ -178061,1138 +184258,1257 @@ characters.data={
linebreak="al",
unicodeslot=0x1F53D,
},
+ [0x1F540]={
+ category="so",
+ description="CIRCLED CROSS POMMEE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F540,
+ },
+ [0x1F541]={
+ category="so",
+ description="CROSS POMMEE WITH HALF-CIRCLE BELOW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F541,
+ },
+ [0x1F542]={
+ category="so",
+ description="CROSS POMMEE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F542,
+ },
+ [0x1F543]={
+ category="so",
+ description="NOTCHED LEFT SEMICIRCLE WITH THREE DOTS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F543,
+ },
[0x1F550]={
category="so",
description="CLOCK FACE ONE OCLOCK",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F550,
},
[0x1F551]={
category="so",
description="CLOCK FACE TWO OCLOCK",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F551,
},
[0x1F552]={
category="so",
description="CLOCK FACE THREE OCLOCK",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F552,
},
[0x1F553]={
category="so",
description="CLOCK FACE FOUR OCLOCK",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F553,
},
[0x1F554]={
category="so",
description="CLOCK FACE FIVE OCLOCK",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F554,
},
[0x1F555]={
category="so",
description="CLOCK FACE SIX OCLOCK",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F555,
},
[0x1F556]={
category="so",
description="CLOCK FACE SEVEN OCLOCK",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F556,
},
[0x1F557]={
category="so",
description="CLOCK FACE EIGHT OCLOCK",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F557,
},
[0x1F558]={
category="so",
description="CLOCK FACE NINE OCLOCK",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F558,
},
[0x1F559]={
category="so",
description="CLOCK FACE TEN OCLOCK",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F559,
},
[0x1F55A]={
category="so",
description="CLOCK FACE ELEVEN OCLOCK",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F55A,
},
[0x1F55B]={
category="so",
description="CLOCK FACE TWELVE OCLOCK",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F55B,
},
[0x1F55C]={
category="so",
description="CLOCK FACE ONE-THIRTY",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F55C,
},
[0x1F55D]={
category="so",
description="CLOCK FACE TWO-THIRTY",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F55D,
},
[0x1F55E]={
category="so",
description="CLOCK FACE THREE-THIRTY",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F55E,
},
[0x1F55F]={
category="so",
description="CLOCK FACE FOUR-THIRTY",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F55F,
},
[0x1F560]={
category="so",
description="CLOCK FACE FIVE-THIRTY",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F560,
},
[0x1F561]={
category="so",
description="CLOCK FACE SIX-THIRTY",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F561,
},
[0x1F562]={
category="so",
description="CLOCK FACE SEVEN-THIRTY",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F562,
},
[0x1F563]={
category="so",
description="CLOCK FACE EIGHT-THIRTY",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F563,
},
[0x1F564]={
category="so",
description="CLOCK FACE NINE-THIRTY",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F564,
},
[0x1F565]={
category="so",
description="CLOCK FACE TEN-THIRTY",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F565,
},
[0x1F566]={
category="so",
description="CLOCK FACE ELEVEN-THIRTY",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F566,
},
[0x1F567]={
category="so",
description="CLOCK FACE TWELVE-THIRTY",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F567,
},
[0x1F5FB]={
category="so",
description="MOUNT FUJI",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F5FB,
},
[0x1F5FC]={
category="so",
description="TOKYO TOWER",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F5FC,
},
[0x1F5FD]={
category="so",
description="STATUE OF LIBERTY",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F5FD,
},
[0x1F5FE]={
category="so",
description="SILHOUETTE OF JAPAN",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F5FE,
},
[0x1F5FF]={
category="so",
description="MOYAI",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F5FF,
},
+ [0x1F600]={
+ category="so",
+ description="GRINNING FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F600,
+ },
[0x1F601]={
category="so",
description="GRINNING FACE WITH SMILING EYES",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F601,
},
[0x1F602]={
category="so",
description="FACE WITH TEARS OF JOY",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F602,
},
[0x1F603]={
category="so",
description="SMILING FACE WITH OPEN MOUTH",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F603,
},
[0x1F604]={
category="so",
description="SMILING FACE WITH OPEN MOUTH AND SMILING EYES",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F604,
},
[0x1F605]={
category="so",
description="SMILING FACE WITH OPEN MOUTH AND COLD SWEAT",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F605,
},
[0x1F606]={
category="so",
description="SMILING FACE WITH OPEN MOUTH AND TIGHTLY-CLOSED EYES",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F606,
},
[0x1F607]={
category="so",
description="SMILING FACE WITH HALO",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F607,
},
[0x1F608]={
category="so",
description="SMILING FACE WITH HORNS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F608,
},
[0x1F609]={
category="so",
description="WINKING FACE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F609,
},
[0x1F60A]={
category="so",
description="SMILING FACE WITH SMILING EYES",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F60A,
},
[0x1F60B]={
category="so",
description="FACE SAVOURING DELICIOUS FOOD",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F60B,
},
[0x1F60C]={
category="so",
description="RELIEVED FACE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F60C,
},
[0x1F60D]={
category="so",
description="SMILING FACE WITH HEART-SHAPED EYES",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F60D,
},
[0x1F60E]={
category="so",
description="SMILING FACE WITH SUNGLASSES",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F60E,
},
[0x1F60F]={
category="so",
description="SMIRKING FACE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F60F,
},
[0x1F610]={
category="so",
description="NEUTRAL FACE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F610,
},
+ [0x1F611]={
+ category="so",
+ description="EXPRESSIONLESS FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F611,
+ },
[0x1F612]={
category="so",
description="UNAMUSED FACE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F612,
},
[0x1F613]={
category="so",
description="FACE WITH COLD SWEAT",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F613,
},
[0x1F614]={
category="so",
description="PENSIVE FACE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F614,
},
+ [0x1F615]={
+ category="so",
+ description="CONFUSED FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F615,
+ },
[0x1F616]={
category="so",
description="CONFOUNDED FACE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F616,
},
+ [0x1F617]={
+ category="so",
+ description="KISSING FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F617,
+ },
[0x1F618]={
category="so",
description="FACE THROWING A KISS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F618,
},
+ [0x1F619]={
+ category="so",
+ description="KISSING FACE WITH SMILING EYES",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F619,
+ },
[0x1F61A]={
category="so",
description="KISSING FACE WITH CLOSED EYES",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F61A,
},
+ [0x1F61B]={
+ category="so",
+ description="FACE WITH STUCK-OUT TONGUE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F61B,
+ },
[0x1F61C]={
category="so",
description="FACE WITH STUCK-OUT TONGUE AND WINKING EYE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F61C,
},
[0x1F61D]={
category="so",
description="FACE WITH STUCK-OUT TONGUE AND TIGHTLY-CLOSED EYES",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F61D,
},
[0x1F61E]={
category="so",
description="DISAPPOINTED FACE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F61E,
},
+ [0x1F61F]={
+ category="so",
+ description="WORRIED FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F61F,
+ },
[0x1F620]={
category="so",
description="ANGRY FACE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F620,
},
[0x1F621]={
category="so",
description="POUTING FACE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F621,
},
[0x1F622]={
category="so",
description="CRYING FACE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F622,
},
[0x1F623]={
category="so",
description="PERSEVERING FACE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F623,
},
[0x1F624]={
category="so",
description="FACE WITH LOOK OF TRIUMPH",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F624,
},
[0x1F625]={
category="so",
description="DISAPPOINTED BUT RELIEVED FACE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F625,
},
+ [0x1F626]={
+ category="so",
+ description="FROWNING FACE WITH OPEN MOUTH",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F626,
+ },
+ [0x1F627]={
+ category="so",
+ description="ANGUISHED FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F627,
+ },
[0x1F628]={
category="so",
description="FEARFUL FACE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F628,
},
[0x1F629]={
category="so",
description="WEARY FACE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F629,
},
[0x1F62A]={
category="so",
description="SLEEPY FACE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F62A,
},
[0x1F62B]={
category="so",
description="TIRED FACE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F62B,
},
+ [0x1F62C]={
+ category="so",
+ description="GRIMACING FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F62C,
+ },
[0x1F62D]={
category="so",
description="LOUDLY CRYING FACE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F62D,
},
+ [0x1F62E]={
+ category="so",
+ description="FACE WITH OPEN MOUTH",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F62E,
+ },
+ [0x1F62F]={
+ category="so",
+ description="HUSHED FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F62F,
+ },
[0x1F630]={
category="so",
description="FACE WITH OPEN MOUTH AND COLD SWEAT",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F630,
},
[0x1F631]={
category="so",
description="FACE SCREAMING IN FEAR",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F631,
},
[0x1F632]={
category="so",
description="ASTONISHED FACE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F632,
},
[0x1F633]={
category="so",
description="FLUSHED FACE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F633,
},
+ [0x1F634]={
+ category="so",
+ description="SLEEPING FACE",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x1F634,
+ },
[0x1F635]={
category="so",
description="DIZZY FACE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F635,
},
[0x1F636]={
category="so",
description="FACE WITHOUT MOUTH",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F636,
},
[0x1F637]={
category="so",
description="FACE WITH MEDICAL MASK",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F637,
},
[0x1F638]={
category="so",
description="GRINNING CAT FACE WITH SMILING EYES",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F638,
},
[0x1F639]={
category="so",
description="CAT FACE WITH TEARS OF JOY",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F639,
},
[0x1F63A]={
category="so",
description="SMILING CAT FACE WITH OPEN MOUTH",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F63A,
},
[0x1F63B]={
category="so",
description="SMILING CAT FACE WITH HEART-SHAPED EYES",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F63B,
},
[0x1F63C]={
category="so",
description="CAT FACE WITH WRY SMILE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F63C,
},
[0x1F63D]={
category="so",
description="KISSING CAT FACE WITH CLOSED EYES",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F63D,
},
[0x1F63E]={
category="so",
description="POUTING CAT FACE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F63E,
},
[0x1F63F]={
category="so",
description="CRYING CAT FACE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F63F,
},
[0x1F640]={
category="so",
description="WEARY CAT FACE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F640,
},
[0x1F645]={
category="so",
description="FACE WITH NO GOOD GESTURE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F645,
},
[0x1F646]={
category="so",
description="FACE WITH OK GESTURE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F646,
},
[0x1F647]={
category="so",
description="PERSON BOWING DEEPLY",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F647,
},
[0x1F648]={
category="so",
description="SEE-NO-EVIL MONKEY",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F648,
},
[0x1F649]={
category="so",
description="HEAR-NO-EVIL MONKEY",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F649,
},
[0x1F64A]={
category="so",
description="SPEAK-NO-EVIL MONKEY",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F64A,
},
[0x1F64B]={
category="so",
description="HAPPY PERSON RAISING ONE HAND",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F64B,
},
[0x1F64C]={
category="so",
description="PERSON RAISING BOTH HANDS IN CELEBRATION",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F64C,
},
[0x1F64D]={
category="so",
description="PERSON FROWNING",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F64D,
},
[0x1F64E]={
category="so",
description="PERSON WITH POUTING FACE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F64E,
},
[0x1F64F]={
category="so",
description="PERSON WITH FOLDED HANDS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F64F,
},
[0x1F680]={
category="so",
description="ROCKET",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F680,
},
[0x1F681]={
category="so",
description="HELICOPTER",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F681,
},
[0x1F682]={
category="so",
description="STEAM LOCOMOTIVE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F682,
},
[0x1F683]={
category="so",
description="RAILWAY CAR",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F683,
},
[0x1F684]={
category="so",
description="HIGH-SPEED TRAIN",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F684,
},
[0x1F685]={
category="so",
description="HIGH-SPEED TRAIN WITH BULLET NOSE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F685,
},
[0x1F686]={
category="so",
description="TRAIN",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F686,
},
[0x1F687]={
category="so",
description="METRO",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F687,
},
[0x1F688]={
category="so",
description="LIGHT RAIL",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F688,
},
[0x1F689]={
category="so",
description="STATION",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F689,
},
[0x1F68A]={
category="so",
description="TRAM",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F68A,
},
[0x1F68B]={
category="so",
description="TRAM CAR",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F68B,
},
[0x1F68C]={
category="so",
description="BUS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F68C,
},
[0x1F68D]={
category="so",
description="ONCOMING BUS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F68D,
},
[0x1F68E]={
category="so",
description="TROLLEYBUS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F68E,
},
[0x1F68F]={
category="so",
description="BUS STOP",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F68F,
},
[0x1F690]={
category="so",
description="MINIBUS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F690,
},
[0x1F691]={
category="so",
description="AMBULANCE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F691,
},
[0x1F692]={
category="so",
description="FIRE ENGINE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F692,
},
[0x1F693]={
category="so",
description="POLICE CAR",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F693,
},
[0x1F694]={
category="so",
description="ONCOMING POLICE CAR",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F694,
},
[0x1F695]={
category="so",
description="TAXI",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F695,
},
[0x1F696]={
category="so",
description="ONCOMING TAXI",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F696,
},
[0x1F697]={
category="so",
description="AUTOMOBILE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F697,
},
[0x1F698]={
category="so",
description="ONCOMING AUTOMOBILE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F698,
},
[0x1F699]={
category="so",
description="RECREATIONAL VEHICLE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F699,
},
[0x1F69A]={
category="so",
description="DELIVERY TRUCK",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F69A,
},
[0x1F69B]={
category="so",
description="ARTICULATED LORRY",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F69B,
},
[0x1F69C]={
category="so",
description="TRACTOR",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F69C,
},
[0x1F69D]={
category="so",
description="MONORAIL",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F69D,
},
[0x1F69E]={
category="so",
description="MOUNTAIN RAILWAY",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F69E,
},
[0x1F69F]={
category="so",
description="SUSPENSION RAILWAY",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F69F,
},
[0x1F6A0]={
category="so",
description="MOUNTAIN CABLEWAY",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F6A0,
},
[0x1F6A1]={
category="so",
description="AERIAL TRAMWAY",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F6A1,
},
[0x1F6A2]={
category="so",
description="SHIP",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F6A2,
},
[0x1F6A3]={
category="so",
description="ROWBOAT",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F6A3,
},
[0x1F6A4]={
category="so",
description="SPEEDBOAT",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F6A4,
},
[0x1F6A5]={
category="so",
description="HORIZONTAL TRAFFIC LIGHT",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F6A5,
},
[0x1F6A6]={
category="so",
description="VERTICAL TRAFFIC LIGHT",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F6A6,
},
[0x1F6A7]={
category="so",
description="CONSTRUCTION SIGN",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F6A7,
},
[0x1F6A8]={
category="so",
description="POLICE CARS REVOLVING LIGHT",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F6A8,
},
[0x1F6A9]={
category="so",
description="TRIANGULAR FLAG ON POST",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F6A9,
},
[0x1F6AA]={
category="so",
description="DOOR",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F6AA,
},
[0x1F6AB]={
category="so",
description="NO ENTRY SIGN",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F6AB,
},
[0x1F6AC]={
category="so",
description="SMOKING SYMBOL",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F6AC,
},
[0x1F6AD]={
category="so",
description="NO SMOKING SYMBOL",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F6AD,
},
[0x1F6AE]={
category="so",
description="PUT LITTER IN ITS PLACE SYMBOL",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F6AE,
},
[0x1F6AF]={
category="so",
description="DO NOT LITTER SYMBOL",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F6AF,
},
[0x1F6B0]={
category="so",
description="POTABLE WATER SYMBOL",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F6B0,
},
[0x1F6B1]={
category="so",
description="NON-POTABLE WATER SYMBOL",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F6B1,
},
[0x1F6B2]={
category="so",
description="BICYCLE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F6B2,
},
[0x1F6B3]={
category="so",
description="NO BICYCLES",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F6B3,
},
[0x1F6B4]={
category="so",
description="BICYCLIST",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F6B4,
},
[0x1F6B5]={
category="so",
description="MOUNTAIN BICYCLIST",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F6B5,
},
[0x1F6B6]={
category="so",
description="PEDESTRIAN",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F6B6,
},
[0x1F6B7]={
category="so",
description="NO PEDESTRIANS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F6B7,
},
[0x1F6B8]={
category="so",
description="CHILDREN CROSSING",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F6B8,
},
[0x1F6B9]={
category="so",
description="MENS SYMBOL",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F6B9,
},
[0x1F6BA]={
category="so",
description="WOMENS SYMBOL",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F6BA,
},
[0x1F6BB]={
category="so",
description="RESTROOM",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F6BB,
},
[0x1F6BC]={
category="so",
description="BABY SYMBOL",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F6BC,
},
[0x1F6BD]={
category="so",
description="TOILET",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F6BD,
},
[0x1F6BE]={
category="so",
description="WATER CLOSET",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F6BE,
},
[0x1F6BF]={
category="so",
description="SHOWER",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F6BF,
},
[0x1F6C0]={
category="so",
description="BATH",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F6C0,
},
[0x1F6C1]={
category="so",
description="BATHTUB",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F6C1,
},
[0x1F6C2]={
category="so",
description="PASSPORT CONTROL",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F6C2,
},
[0x1F6C3]={
category="so",
description="CUSTOMS",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F6C3,
},
[0x1F6C4]={
category="so",
description="BAGGAGE CLAIM",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F6C4,
},
[0x1F6C5]={
category="so",
description="LEFT LUGGAGE",
direction="on",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x1F6C5,
},
[0x1F700]={
diff --git a/Master/texmf-dist/tex/context/base/char-enc.lua b/Master/texmf-dist/tex/context/base/char-enc.lua
index ef6805e54f3..048837eec18 100644
--- a/Master/texmf-dist/tex/context/base/char-enc.lua
+++ b/Master/texmf-dist/tex/context/base/char-enc.lua
@@ -1,9 +1,10 @@
-if not modules then modules = { } end modules ['char-syn'] = {
+if not modules then modules = { } end modules ['char-enc'] = {
version = 1.001,
comment = "companion to char-ini.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
copyright = "PRAGMA ADE / ConTeXt Development Team",
license = "see context related readme files"
+ -- dataonly = true,
}
-- Thanks to tex4ht for these mappings.
@@ -144,25 +145,25 @@ characters.synonyms = allocate { -- afm mess
Yen = 0x00A5,
}
---~ if not characters.enccodes then
---~
---~ local enccodes = { } characters.enccodes = enccodes
---~
---~ for unicode, data in next, characters.data do
---~ local encname = data.adobename or data.contextname
---~ if encname then
---~ enccodes[encname] = unicode
---~ end
---~ end
---~
---~ for name, unicode in next, characters.synonyms do
---~ if not enccodes[name] then enccodes[name] = unicode end
---~ end
---~
---~
---~ end
---~
---~ storage.register("characters.enccodes", characters.enccodes, "characters.enccodes")
+-- if not characters.enccodes then
+--
+-- local enccodes = { } characters.enccodes = enccodes
+--
+-- for unicode, data in next, characters.data do
+-- local encname = data.adobename or data.contextname
+-- if encname then
+-- enccodes[encname] = unicode
+-- end
+-- end
+--
+-- for name, unicode in next, characters.synonyms do
+-- if not enccodes[name] then enccodes[name] = unicode end
+-- end
+--
+--
+-- end
+--
+-- storage.register("characters.enccodes", characters.enccodes, "characters.enccodes")
-- As this table is seldom used, we can delay its definition. Beware, this means
-- that table.print would not work on this file unless it is accessed once. This
diff --git a/Master/texmf-dist/tex/context/base/char-ent.lua b/Master/texmf-dist/tex/context/base/char-ent.lua
index d2ac22bbf2c..58ee9472ca3 100644
--- a/Master/texmf-dist/tex/context/base/char-ent.lua
+++ b/Master/texmf-dist/tex/context/base/char-ent.lua
@@ -1,15 +1,14 @@
-if not modules then modules = { } end modules ['math-ent'] = {
+if not modules then modules = { } end modules ['char-ent'] = {
version = 1.001,
comment = "companion to math-ini.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
copyright = "derived from the mathml 2.0 specification",
+ dataonly = true,
}
-- http://www.w3.org/2003/entities/2007/w3centities-f.ent
-- http://www.w3.org/2003/entities/2007/htmlmathml-f.ent
--- this might go into char-def
-
local entities = utilities.storage.allocate {
["AElig"] = "Æ", -- U+000C6
["AMP"] = "&", -- U+00026
@@ -568,7 +567,8 @@ local entities = utilities.storage.allocate {
["Ugr"] = "Υ", -- U+003A5
["Ugrave"] = "Ù", -- U+000D9
["Umacr"] = "Ū", -- U+0016A
- ["UnderBar"] = "_", -- U+0005F
+ -- ["UnderBar"] = "_", -- U+0005F
+ ["UnderBar"] = "‾", -- U+0203E
["UnderBrace"] = "⏟", -- U+023DF
["UnderBracket"] = "⎵", -- U+023B5
["UnderParenthesis"] = "⏝", -- U+023DD
diff --git a/Master/texmf-dist/tex/context/base/char-ini.lua b/Master/texmf-dist/tex/context/base/char-ini.lua
index 244b8d2a70e..b75f5eda758 100644
--- a/Master/texmf-dist/tex/context/base/char-ini.lua
+++ b/Master/texmf-dist/tex/context/base/char-ini.lua
@@ -10,26 +10,17 @@ if not modules then modules = { } end modules ['char-ini'] = {
-- we can remove the tag range starting at 0xE0000 (special applications)
-local tex = tex
-local utf = unicode.utf8
-
-local utfchar, utfbyte, utfvalues = utf.char, utf.byte, string.utfvalues
-local ustring = unicode.ustring
+local utfchar, utfbyte, utfvalues, ustring = utf.char, utf.byte, utf.values, utf.ustring
local concat, unpack, tohash = table.concat, table.unpack, table.tohash
local next, tonumber, type, rawget, rawset = next, tonumber, type, rawget, rawset
local format, lower, gsub, match, gmatch = string.format, string.lower, string.gsub, string.match, string.match, string.gmatch
-local P, R, lpegmatch = lpeg.P, lpeg.R, lpeg.match
+local P, R, Cs, lpegmatch, patterns = lpeg.P, lpeg.R, lpeg.Cs, lpeg.match, lpeg.patterns
+
+local utf8byte = patterns.utf8byte
+local utf8char = patterns.utf8char
local allocate = utilities.storage.allocate
local mark = utilities.storage.mark
-local texsetlccode = tex.setlccode
-local texsetuccode = tex.setuccode
-local texsetsfcode = tex.setsfcode
-local texsetcatcode = tex.setcatcode
-
-local contextsprint = context.sprint
-local ctxcatcodes = tex.ctxcatcodes
-local texcatcodes = tex.texcatcodes
local setmetatableindex = table.setmetatableindex
@@ -48,7 +39,6 @@ loaded!
characters = characters or { }
local characters = characters
-
local data = characters.data
if data then
@@ -64,7 +54,7 @@ end
local pattern = (P("0x") + P("U+")) * ((R("09","AF")^1 * P(-1)) / function(s) return tonumber(s,16) end)
-lpeg.patterns.chartonumber = pattern
+patterns.chartonumber = pattern
local function chartonumber(k)
if type(k) == "string" then
@@ -136,185 +126,259 @@ setmetatableindex(data, function(t,k)
end)
local blocks = allocate {
- ["aegeannumbers"] = { first = 0x10100, last = 0x1013F, description = "Aegean Numbers" },
- ["alphabeticpresentationforms"] = { first = 0x0FB00, last = 0x0FB4F, description = "Alphabetic Presentation Forms" },
- ["ancientgreekmusicalnotation"] = { first = 0x1D200, last = 0x1D24F, description = "Ancient Greek Musical Notation" },
- ["ancientgreeknumbers"] = { first = 0x10140, last = 0x1018F, description = "Ancient Greek Numbers" },
- ["ancientsymbols"] = { first = 0x10190, last = 0x101CF, description = "Ancient Symbols" },
- ["arabic"] = { first = 0x00600, last = 0x006FF, description = "Arabic" },
- ["arabicpresentationformsa"] = { first = 0x0FB50, last = 0x0FDFF, description = "Arabic Presentation Forms-A" },
- ["arabicpresentationformsb"] = { first = 0x0FE70, last = 0x0FEFF, description = "Arabic Presentation Forms-B" },
- ["arabicsupplement"] = { first = 0x00750, last = 0x0077F, description = "Arabic Supplement" },
- ["armenian"] = { first = 0x00530, last = 0x0058F, description = "Armenian" },
- ["arrows"] = { first = 0x02190, last = 0x021FF, description = "Arrows" },
- ["balinese"] = { first = 0x01B00, last = 0x01B7F, description = "Balinese" },
- ["basiclatin"] = { first = 0x00000, last = 0x0007F, description = "Basic Latin" },
- ["bengali"] = { first = 0x00980, last = 0x009FF, description = "Bengali" },
- ["blockelements"] = { first = 0x02580, last = 0x0259F, description = "Block Elements" },
- ["bopomofo"] = { first = 0x03100, last = 0x0312F, description = "Bopomofo" },
- ["bopomofoextended"] = { first = 0x031A0, last = 0x031BF, description = "Bopomofo Extended" },
- ["boxdrawing"] = { first = 0x02500, last = 0x0257F, description = "Box Drawing" },
- ["braillepatterns"] = { first = 0x02800, last = 0x028FF, description = "Braille Patterns" },
- ["buginese"] = { first = 0x01A00, last = 0x01A1F, description = "Buginese" },
- ["buhid"] = { first = 0x01740, last = 0x0175F, description = "Buhid" },
- ["byzantinemusicalsymbols"] = { first = 0x1D000, last = 0x1D0FF, description = "Byzantine Musical Symbols" },
- ["carian"] = { first = 0x102A0, last = 0x102DF, description = "Carian" },
- ["cham"] = { first = 0x0AA00, last = 0x0AA5F, description = "Cham" },
- ["cherokee"] = { first = 0x013A0, last = 0x013FF, description = "Cherokee" },
- ["cjkcompatibility"] = { first = 0x03300, last = 0x033FF, description = "CJK Compatibility" },
- ["cjkcompatibilityforms"] = { first = 0x0FE30, last = 0x0FE4F, description = "CJK Compatibility Forms" },
- ["cjkcompatibilityideographs"] = { first = 0x0F900, last = 0x0FAFF, description = "CJK Compatibility Ideographs" },
- ["cjkcompatibilityideographssupplement"] = { first = 0x2F800, last = 0x2FA1F, description = "CJK Compatibility Ideographs Supplement" },
- ["cjkradicalssupplement"] = { first = 0x02E80, last = 0x02EFF, description = "CJK Radicals Supplement" },
- ["cjkstrokes"] = { first = 0x031C0, last = 0x031EF, description = "CJK Strokes" },
- ["cjksymbolsandpunctuation"] = { first = 0x03000, last = 0x0303F, description = "CJK Symbols and Punctuation" },
- ["cjkunifiedideographs"] = { first = 0x04E00, last = 0x09FFF, description = "CJK Unified Ideographs" },
- ["cjkunifiedideographsextensiona"] = { first = 0x03400, last = 0x04DBF, description = "CJK Unified Ideographs Extension A" },
- ["cjkunifiedideographsextensionb"] = { first = 0x20000, last = 0x2A6DF, description = "CJK Unified Ideographs Extension B" },
- ["combiningdiacriticalmarks"] = { first = 0x00300, last = 0x0036F, description = "Combining Diacritical Marks" },
- ["combiningdiacriticalmarksforsymbols"] = { first = 0x020D0, last = 0x020FF, description = "Combining Diacritical Marks for Symbols" },
- ["combiningdiacriticalmarkssupplement"] = { first = 0x01DC0, last = 0x01DFF, description = "Combining Diacritical Marks Supplement" },
- ["combininghalfmarks"] = { first = 0x0FE20, last = 0x0FE2F, description = "Combining Half Marks" },
- ["controlpictures"] = { first = 0x02400, last = 0x0243F, description = "Control Pictures" },
- ["coptic"] = { first = 0x02C80, last = 0x02CFF, description = "Coptic" },
- ["countingrodnumerals"] = { first = 0x1D360, last = 0x1D37F, description = "Counting Rod Numerals" },
- ["cuneiform"] = { first = 0x12000, last = 0x123FF, description = "Cuneiform" },
- ["cuneiformnumbersandpunctuation"] = { first = 0x12400, last = 0x1247F, description = "Cuneiform Numbers and Punctuation" },
- ["currencysymbols"] = { first = 0x020A0, last = 0x020CF, description = "Currency Symbols" },
- ["cypriotsyllabary"] = { first = 0x10800, last = 0x1083F, description = "Cypriot Syllabary" },
- ["cyrillic"] = { first = 0x00400, last = 0x004FF, description = "Cyrillic" },
- ["cyrillicextendeda"] = { first = 0x02DE0, last = 0x02DFF, description = "Cyrillic Extended-A" },
- ["cyrillicextendedb"] = { first = 0x0A640, last = 0x0A69F, description = "Cyrillic Extended-B" },
- ["cyrillicsupplement"] = { first = 0x00500, last = 0x0052F, description = "Cyrillic Supplement" },
- ["deseret"] = { first = 0x10400, last = 0x1044F, description = "Deseret" },
- ["devanagari"] = { first = 0x00900, last = 0x0097F, description = "Devanagari" },
- ["dingbats"] = { first = 0x02700, last = 0x027BF, description = "Dingbats" },
- ["dominotiles"] = { first = 0x1F030, last = 0x1F09F, description = "Domino Tiles" },
- ["enclosedalphanumerics"] = { first = 0x02460, last = 0x024FF, description = "Enclosed Alphanumerics" },
- ["enclosedcjklettersandmonths"] = { first = 0x03200, last = 0x032FF, description = "Enclosed CJK Letters and Months" },
- ["ethiopic"] = { first = 0x01200, last = 0x0137F, description = "Ethiopic" },
- ["ethiopicextended"] = { first = 0x02D80, last = 0x02DDF, description = "Ethiopic Extended" },
- ["ethiopicsupplement"] = { first = 0x01380, last = 0x0139F, description = "Ethiopic Supplement" },
- ["generalpunctuation"] = { first = 0x02000, last = 0x0206F, description = "General Punctuation" },
- ["geometricshapes"] = { first = 0x025A0, last = 0x025FF, description = "Geometric Shapes" },
- ["georgian"] = { first = 0x010A0, last = 0x010FF, description = "Georgian" },
- ["georgiansupplement"] = { first = 0x02D00, last = 0x02D2F, description = "Georgian Supplement" },
- ["glagolitic"] = { first = 0x02C00, last = 0x02C5F, description = "Glagolitic" },
- ["gothic"] = { first = 0x10330, last = 0x1034F, description = "Gothic" },
- ["greekandcoptic"] = { first = 0x00370, last = 0x003FF, description = "Greek and Coptic" },
- ["greekextended"] = { first = 0x01F00, last = 0x01FFF, description = "Greek Extended" },
- ["gujarati"] = { first = 0x00A80, last = 0x00AFF, description = "Gujarati" },
- ["gurmukhi"] = { first = 0x00A00, last = 0x00A7F, description = "Gurmukhi" },
- ["halfwidthandfullwidthforms"] = { first = 0x0FF00, last = 0x0FFEF, description = "Halfwidth and Fullwidth Forms" },
- ["hangulcompatibilityjamo"] = { first = 0x03130, last = 0x0318F, description = "Hangul Compatibility Jamo" },
- ["hanguljamo"] = { first = 0x01100, last = 0x011FF, description = "Hangul Jamo" },
- ["hangulsyllables"] = { first = 0x0AC00, last = 0x0D7AF, description = "Hangul Syllables" },
- ["hanunoo"] = { first = 0x01720, last = 0x0173F, description = "Hanunoo" },
- ["hebrew"] = { first = 0x00590, last = 0x005FF, description = "Hebrew" },
- ["highprivateusesurrogates"] = { first = 0x0DB80, last = 0x0DBFF, description = "High Private Use Surrogates" },
- ["highsurrogates"] = { first = 0x0D800, last = 0x0DB7F, description = "High Surrogates" },
- ["hiragana"] = { first = 0x03040, last = 0x0309F, description = "Hiragana" },
- ["ideographicdescriptioncharacters"] = { first = 0x02FF0, last = 0x02FFF, description = "Ideographic Description Characters" },
- ["ipaextensions"] = { first = 0x00250, last = 0x002AF, description = "IPA Extensions" },
- ["kanbun"] = { first = 0x03190, last = 0x0319F, description = "Kanbun" },
- ["kangxiradicals"] = { first = 0x02F00, last = 0x02FDF, description = "Kangxi Radicals" },
- ["kannada"] = { first = 0x00C80, last = 0x00CFF, description = "Kannada" },
- ["katakana"] = { first = 0x030A0, last = 0x030FF, description = "Katakana" },
- ["katakanaphoneticextensions"] = { first = 0x031F0, last = 0x031FF, description = "Katakana Phonetic Extensions" },
- ["kayahli"] = { first = 0x0A900, last = 0x0A92F, description = "Kayah Li" },
- ["kharoshthi"] = { first = 0x10A00, last = 0x10A5F, description = "Kharoshthi" },
- ["khmer"] = { first = 0x01780, last = 0x017FF, description = "Khmer" },
- ["khmersymbols"] = { first = 0x019E0, last = 0x019FF, description = "Khmer Symbols" },
- ["lao"] = { first = 0x00E80, last = 0x00EFF, description = "Lao" },
- ["latinextendeda"] = { first = 0x00100, last = 0x0017F, description = "Latin Extended-A" },
- ["latinextendedadditional"] = { first = 0x01E00, last = 0x01EFF, description = "Latin Extended Additional" },
- ["latinextendedb"] = { first = 0x00180, last = 0x0024F, description = "Latin Extended-B" },
- ["latinextendedc"] = { first = 0x02C60, last = 0x02C7F, description = "Latin Extended-C" },
- ["latinextendedd"] = { first = 0x0A720, last = 0x0A7FF, description = "Latin Extended-D" },
- ["latinsupplement"] = { first = 0x00080, last = 0x000FF, description = "Latin-1 Supplement" },
- ["lepcha"] = { first = 0x01C00, last = 0x01C4F, description = "Lepcha" },
- ["letterlikesymbols"] = { first = 0x02100, last = 0x0214F, description = "Letterlike Symbols" },
- ["limbu"] = { first = 0x01900, last = 0x0194F, description = "Limbu" },
- ["linearbideograms"] = { first = 0x10080, last = 0x100FF, description = "Linear B Ideograms" },
- ["linearbsyllabary"] = { first = 0x10000, last = 0x1007F, description = "Linear B Syllabary" },
- ["lowsurrogates"] = { first = 0x0DC00, last = 0x0DFFF, description = "Low Surrogates" },
- ["lycian"] = { first = 0x10280, last = 0x1029F, description = "Lycian" },
- ["lydian"] = { first = 0x10920, last = 0x1093F, description = "Lydian" },
- ["mahjongtiles"] = { first = 0x1F000, last = 0x1F02F, description = "Mahjong Tiles" },
- ["malayalam"] = { first = 0x00D00, last = 0x00D7F, description = "Malayalam" },
- ["mathematicalalphanumericsymbols"] = { first = 0x1D400, last = 0x1D7FF, description = "Mathematical Alphanumeric Symbols" },
- ["mathematicaloperators"] = { first = 0x02200, last = 0x022FF, description = "Mathematical Operators" },
- ["miscellaneousmathematicalsymbolsa"] = { first = 0x027C0, last = 0x027EF, description = "Miscellaneous Mathematical Symbols-A" },
- ["miscellaneousmathematicalsymbolsb"] = { first = 0x02980, last = 0x029FF, description = "Miscellaneous Mathematical Symbols-B" },
- ["miscellaneoussymbols"] = { first = 0x02600, last = 0x026FF, description = "Miscellaneous Symbols" },
- ["miscellaneoussymbolsandarrows"] = { first = 0x02B00, last = 0x02BFF, description = "Miscellaneous Symbols and Arrows" },
- ["miscellaneoustechnical"] = { first = 0x02300, last = 0x023FF, description = "Miscellaneous Technical" },
- ["modifiertoneletters"] = { first = 0x0A700, last = 0x0A71F, description = "Modifier Tone Letters" },
- ["mongolian"] = { first = 0x01800, last = 0x018AF, description = "Mongolian" },
- ["musicalsymbols"] = { first = 0x1D100, last = 0x1D1FF, description = "Musical Symbols" },
- ["myanmar"] = { first = 0x01000, last = 0x0109F, description = "Myanmar" },
- ["newtailue"] = { first = 0x01980, last = 0x019DF, description = "New Tai Lue" },
- ["nko"] = { first = 0x007C0, last = 0x007FF, description = "NKo" },
- ["numberforms"] = { first = 0x02150, last = 0x0218F, description = "Number Forms" },
- ["ogham"] = { first = 0x01680, last = 0x0169F, description = "Ogham" },
- ["olchiki"] = { first = 0x01C50, last = 0x01C7F, description = "Ol Chiki" },
- ["olditalic"] = { first = 0x10300, last = 0x1032F, description = "Old Italic" },
- ["oldpersian"] = { first = 0x103A0, last = 0x103DF, description = "Old Persian" },
- ["opticalcharacterrecognition"] = { first = 0x02440, last = 0x0245F, description = "Optical Character Recognition" },
- ["oriya"] = { first = 0x00B00, last = 0x00B7F, description = "Oriya" },
- ["osmanya"] = { first = 0x10480, last = 0x104AF, description = "Osmanya" },
- ["phagspa"] = { first = 0x0A840, last = 0x0A87F, description = "Phags-pa" },
- ["phaistosdisc"] = { first = 0x101D0, last = 0x101FF, description = "Phaistos Disc" },
- ["phoenician"] = { first = 0x10900, last = 0x1091F, description = "Phoenician" },
- ["phoneticextensions"] = { first = 0x01D00, last = 0x01D7F, description = "Phonetic Extensions" },
- ["phoneticextensionssupplement"] = { first = 0x01D80, last = 0x01DBF, description = "Phonetic Extensions Supplement" },
- ["privateusearea"] = { first = 0x0E000, last = 0x0F8FF, description = "Private Use Area" },
- ["rejang"] = { first = 0x0A930, last = 0x0A95F, description = "Rejang" },
- ["runic"] = { first = 0x016A0, last = 0x016FF, description = "Runic" },
- ["saurashtra"] = { first = 0x0A880, last = 0x0A8DF, description = "Saurashtra" },
- ["shavian"] = { first = 0x10450, last = 0x1047F, description = "Shavian" },
- ["sinhala"] = { first = 0x00D80, last = 0x00DFF, description = "Sinhala" },
- ["smallformvariants"] = { first = 0x0FE50, last = 0x0FE6F, description = "Small Form Variants" },
- ["spacingmodifierletters"] = { first = 0x002B0, last = 0x002FF, description = "Spacing Modifier Letters" },
- ["specials"] = { first = 0x0FFF0, last = 0x0FFFF, description = "Specials" },
- ["sundanese"] = { first = 0x01B80, last = 0x01BBF, description = "Sundanese" },
- ["superscriptsandsubscripts"] = { first = 0x02070, last = 0x0209F, description = "Superscripts and Subscripts" },
- ["supplementalarrowsa"] = { first = 0x027F0, last = 0x027FF, description = "Supplemental Arrows-A" },
- ["supplementalarrowsb"] = { first = 0x02900, last = 0x0297F, description = "Supplemental Arrows-B" },
- ["supplementalmathematicaloperators"] = { first = 0x02A00, last = 0x02AFF, description = "Supplemental Mathematical Operators" },
- ["supplementalpunctuation"] = { first = 0x02E00, last = 0x02E7F, description = "Supplemental Punctuation" },
- ["supplementaryprivateuseareaa"] = { first = 0xF0000, last = 0xFFFFF, description = "Supplementary Private Use Area-A" },
- ["supplementaryprivateuseareab"] = { first = 0x100000,last = 0x10FFFF,description = "Supplementary Private Use Area-B" },
- ["sylotinagri"] = { first = 0x0A800, last = 0x0A82F, description = "Syloti Nagri" },
- ["syriac"] = { first = 0x00700, last = 0x0074F, description = "Syriac" },
- ["tagalog"] = { first = 0x01700, last = 0x0171F, description = "Tagalog" },
- ["tagbanwa"] = { first = 0x01760, last = 0x0177F, description = "Tagbanwa" },
- ["tags"] = { first = 0xE0000, last = 0xE007F, description = "Tags" },
- ["taile"] = { first = 0x01950, last = 0x0197F, description = "Tai Le" },
- ["taixuanjingsymbols"] = { first = 0x1D300, last = 0x1D35F, description = "Tai Xuan Jing Symbols" },
- ["tamil"] = { first = 0x00B80, last = 0x00BFF, description = "Tamil" },
- ["telugu"] = { first = 0x00C00, last = 0x00C7F, description = "Telugu" },
- ["thaana"] = { first = 0x00780, last = 0x007BF, description = "Thaana" },
- ["thai"] = { first = 0x00E00, last = 0x00E7F, description = "Thai" },
- ["tibetan"] = { first = 0x00F00, last = 0x00FFF, description = "Tibetan" },
- ["tifinagh"] = { first = 0x02D30, last = 0x02D7F, description = "Tifinagh" },
- ["ugaritic"] = { first = 0x10380, last = 0x1039F, description = "Ugaritic" },
- ["unifiedcanadianaboriginalsyllabics"] = { first = 0x01400, last = 0x0167F, description = "Unified Canadian Aboriginal Syllabics" },
- ["vai"] = { first = 0x0A500, last = 0x0A63F, description = "Vai" },
- ["variationselectors"] = { first = 0x0FE00, last = 0x0FE0F, description = "Variation Selectors" },
- ["variationselectorssupplement"] = { first = 0xE0100, last = 0xE01EF, description = "Variation Selectors Supplement" },
- ["verticalforms"] = { first = 0x0FE10, last = 0x0FE1F, description = "Vertical Forms" },
- ["yijinghexagramsymbols"] = { first = 0x04DC0, last = 0x04DFF, description = "Yijing Hexagram Symbols" },
- ["yiradicals"] = { first = 0x0A490, last = 0x0A4CF, description = "Yi Radicals" },
- ["yisyllables"] = { first = 0x0A000, last = 0x0A48F, description = "Yi Syllables" },
+ ["aegeannumbers"] = { first = 0x10100, last = 0x1013F, description = "Aegean Numbers" },
+ ["alchemicalsymbols"] = { first = 0x1F700, last = 0x1F77F, description = "Alchemical Symbols" },
+ ["alphabeticpresentationforms"] = { first = 0x0FB00, last = 0x0FB4F, otf="latn", description = "Alphabetic Presentation Forms" },
+ ["ancientgreekmusicalnotation"] = { first = 0x1D200, last = 0x1D24F, otf="grek", description = "Ancient Greek Musical Notation" },
+ ["ancientgreeknumbers"] = { first = 0x10140, last = 0x1018F, otf="grek", description = "Ancient Greek Numbers" },
+ ["ancientsymbols"] = { first = 0x10190, last = 0x101CF, otf="grek", description = "Ancient Symbols" },
+ ["arabic"] = { first = 0x00600, last = 0x006FF, otf="arab", description = "Arabic" },
+ ["arabicextendeda"] = { first = 0x008A0, last = 0x008FF, description = "Arabic Extended-A" },
+ ["arabicmathematicalalphabeticsymbols"] = { first = 0x1EE00, last = 0x1EEFF, description = "Arabic Mathematical Alphabetic Symbols" },
+ ["arabicpresentationformsa"] = { first = 0x0FB50, last = 0x0FDFF, otf="arab", description = "Arabic Presentation Forms-A" },
+ ["arabicpresentationformsb"] = { first = 0x0FE70, last = 0x0FEFF, otf="arab", description = "Arabic Presentation Forms-B" },
+ ["arabicsupplement"] = { first = 0x00750, last = 0x0077F, otf="arab", description = "Arabic Supplement" },
+ ["armenian"] = { first = 0x00530, last = 0x0058F, otf="armn", description = "Armenian" },
+ ["arrows"] = { first = 0x02190, last = 0x021FF, description = "Arrows" },
+ ["avestan"] = { first = 0x10B00, last = 0x10B3F, description = "Avestan" },
+ ["balinese"] = { first = 0x01B00, last = 0x01B7F, otf="bali", description = "Balinese" },
+ ["bamum"] = { first = 0x0A6A0, last = 0x0A6FF, description = "Bamum" },
+ ["bamumsupplement"] = { first = 0x16800, last = 0x16A3F, description = "Bamum Supplement" },
+ ["basiclatin"] = { first = 0x00000, last = 0x0007F, otf="latn", description = "Basic Latin" },
+ ["batak"] = { first = 0x01BC0, last = 0x01BFF, description = "Batak" },
+ ["bengali"] = { first = 0x00980, last = 0x009FF, otf="beng", description = "Bengali" },
+ ["blockelements"] = { first = 0x02580, last = 0x0259F, otf="bopo", description = "Block Elements" },
+ ["bopomofo"] = { first = 0x03100, last = 0x0312F, otf="bopo", description = "Bopomofo" },
+ ["bopomofoextended"] = { first = 0x031A0, last = 0x031BF, otf="bopo", description = "Bopomofo Extended" },
+ ["boxdrawing"] = { first = 0x02500, last = 0x0257F, description = "Box Drawing" },
+ ["brahmi"] = { first = 0x11000, last = 0x1107F, description = "Brahmi" },
+ ["braillepatterns"] = { first = 0x02800, last = 0x028FF, otf="brai", description = "Braille Patterns" },
+ ["buginese"] = { first = 0x01A00, last = 0x01A1F, otf="bugi", description = "Buginese" },
+ ["buhid"] = { first = 0x01740, last = 0x0175F, otf="buhd", description = "Buhid" },
+ ["byzantinemusicalsymbols"] = { first = 0x1D000, last = 0x1D0FF, otf="byzm", description = "Byzantine Musical Symbols" },
+ ["commonindicnumberforms"] = { first = 0x0A830, last = 0x0A83F, description = "Common Indic Number Forms" },
+ ["carian"] = { first = 0x102A0, last = 0x102DF, description = "Carian" },
+ ["cham"] = { first = 0x0AA00, last = 0x0AA5F, description = "Cham" },
+ ["cherokee"] = { first = 0x013A0, last = 0x013FF, otf="cher", description = "Cherokee" },
+ ["cjkcompatibility"] = { first = 0x03300, last = 0x033FF, otf="hang", description = "CJK Compatibility" },
+ ["cjkcompatibilityforms"] = { first = 0x0FE30, last = 0x0FE4F, otf="hang", description = "CJK Compatibility Forms" },
+ ["cjkcompatibilityideographs"] = { first = 0x0F900, last = 0x0FAFF, otf="hang", description = "CJK Compatibility Ideographs" },
+ ["cjkcompatibilityideographssupplement"] = { first = 0x2F800, last = 0x2FA1F, otf="hang", description = "CJK Compatibility Ideographs Supplement" },
+ ["cjkradicalssupplement"] = { first = 0x02E80, last = 0x02EFF, otf="hang", description = "CJK Radicals Supplement" },
+ ["cjkstrokes"] = { first = 0x031C0, last = 0x031EF, otf="hang", description = "CJK Strokes" },
+ ["cjksymbolsandpunctuation"] = { first = 0x03000, last = 0x0303F, otf="hang", description = "CJK Symbols and Punctuation" },
+ ["cjkunifiedideographs"] = { first = 0x04E00, last = 0x09FFF, otf="hang", description = "CJK Unified Ideographs" },
+ ["cjkunifiedideographsextensiona"] = { first = 0x03400, last = 0x04DBF, otf="hang", description = "CJK Unified Ideographs Extension A" },
+ ["cjkunifiedideographsextensionb"] = { first = 0x20000, last = 0x2A6DF, otf="hang", description = "CJK Unified Ideographs Extension B" },
+ ["combiningdiacriticalmarks"] = { first = 0x00300, last = 0x0036F, description = "Combining Diacritical Marks" },
+ ["combiningdiacriticalmarksforsymbols"] = { first = 0x020D0, last = 0x020FF, description = "Combining Diacritical Marks for Symbols" },
+ ["combiningdiacriticalmarkssupplement"] = { first = 0x01DC0, last = 0x01DFF, description = "Combining Diacritical Marks Supplement" },
+ ["combininghalfmarks"] = { first = 0x0FE20, last = 0x0FE2F, description = "Combining Half Marks" },
+ ["controlpictures"] = { first = 0x02400, last = 0x0243F, description = "Control Pictures" },
+ ["coptic"] = { first = 0x02C80, last = 0x02CFF, otf="copt", description = "Coptic" },
+ ["countingrodnumerals"] = { first = 0x1D360, last = 0x1D37F, description = "Counting Rod Numerals" },
+ ["cuneiform"] = { first = 0x12000, last = 0x123FF, otf="xsux", description = "Cuneiform" },
+ ["cuneiformnumbersandpunctuation"] = { first = 0x12400, last = 0x1247F, otf="xsux", description = "Cuneiform Numbers and Punctuation" },
+ ["currencysymbols"] = { first = 0x020A0, last = 0x020CF, description = "Currency Symbols" },
+ ["cypriotsyllabary"] = { first = 0x10800, last = 0x1083F, otf="cprt", description = "Cypriot Syllabary" },
+ ["cyrillic"] = { first = 0x00400, last = 0x004FF, otf="cyrl", description = "Cyrillic" },
+ ["cyrillicextendeda"] = { first = 0x02DE0, last = 0x02DFF, otf="cyrl", description = "Cyrillic Extended-A" },
+ ["cyrillicextendedb"] = { first = 0x0A640, last = 0x0A69F, otf="cyrl", description = "Cyrillic Extended-B" },
+ ["cyrillicsupplement"] = { first = 0x00500, last = 0x0052F, otf="cyrl", description = "Cyrillic Supplement" },
+ ["deseret"] = { first = 0x10400, last = 0x1044F, otf="dsrt", description = "Deseret" },
+ ["devanagari"] = { first = 0x00900, last = 0x0097F, otf="deva", description = "Devanagari" },
+ ["devanagariextended"] = { first = 0x0A8E0, last = 0x0A8FF, description = "Devanagari Extended" },
+ ["dingbats"] = { first = 0x02700, last = 0x027BF, description = "Dingbats" },
+ ["dominotiles"] = { first = 0x1F030, last = 0x1F09F, description = "Domino Tiles" },
+ ["egyptianhieroglyphs"] = { first = 0x13000, last = 0x1342F, description = "Egyptian Hieroglyphs" },
+ ["emoticons"] = { first = 0x1F600, last = 0x1F64F, description = "Emoticons" },
+ ["enclosedalphanumericsupplement"] = { first = 0x1F100, last = 0x1F1FF, description = "Enclosed Alphanumeric Supplement" },
+ ["enclosedalphanumerics"] = { first = 0x02460, last = 0x024FF, description = "Enclosed Alphanumerics" },
+ ["enclosedcjklettersandmonths"] = { first = 0x03200, last = 0x032FF, description = "Enclosed CJK Letters and Months" },
+ ["enclosedideographicsupplement"] = { first = 0x1F200, last = 0x1F2FF, description = "Enclosed Ideographic Supplement" },
+ ["ethiopic"] = { first = 0x01200, last = 0x0137F, otf="ethi", description = "Ethiopic" },
+ ["ethiopicextended"] = { first = 0x02D80, last = 0x02DDF, otf="ethi", description = "Ethiopic Extended" },
+ ["ethiopicextendeda"] = { first = 0x0AB00, last = 0x0AB2F, description = "Ethiopic Extended-A" },
+ ["ethiopicsupplement"] = { first = 0x01380, last = 0x0139F, otf="ethi", description = "Ethiopic Supplement" },
+ ["generalpunctuation"] = { first = 0x02000, last = 0x0206F, description = "General Punctuation" },
+ ["geometricshapes"] = { first = 0x025A0, last = 0x025FF, description = "Geometric Shapes" },
+ ["georgian"] = { first = 0x010A0, last = 0x010FF, otf="geor", description = "Georgian" },
+ ["georgiansupplement"] = { first = 0x02D00, last = 0x02D2F, otf="geor", description = "Georgian Supplement" },
+ ["glagolitic"] = { first = 0x02C00, last = 0x02C5F, otf="glag", description = "Glagolitic" },
+ ["gothic"] = { first = 0x10330, last = 0x1034F, otf="goth", description = "Gothic" },
+ ["greekandcoptic"] = { first = 0x00370, last = 0x003FF, otf="grek", description = "Greek and Coptic" },
+ ["greekextended"] = { first = 0x01F00, last = 0x01FFF, otf="grek", description = "Greek Extended" },
+ ["gujarati"] = { first = 0x00A80, last = 0x00AFF, otf="gujr", description = "Gujarati" },
+ ["gurmukhi"] = { first = 0x00A00, last = 0x00A7F, otf="guru", description = "Gurmukhi" },
+ ["halfwidthandfullwidthforms"] = { first = 0x0FF00, last = 0x0FFEF, description = "Halfwidth and Fullwidth Forms" },
+ ["hangulcompatibilityjamo"] = { first = 0x03130, last = 0x0318F, otf="jamo", description = "Hangul Compatibility Jamo" },
+ ["hanguljamo"] = { first = 0x01100, last = 0x011FF, otf="jamo", description = "Hangul Jamo" },
+ ["hanguljamoextendeda"] = { first = 0x0A960, last = 0x0A97F, description = "Hangul Jamo Extended-A" },
+ ["hanguljamoextendedb"] = { first = 0x0D7B0, last = 0x0D7FF, description = "Hangul Jamo Extended-B" },
+ ["hangulsyllables"] = { first = 0x0AC00, last = 0x0D7AF, otf="hang", description = "Hangul Syllables" },
+ ["hanunoo"] = { first = 0x01720, last = 0x0173F, otf="hano", description = "Hanunoo" },
+ ["hebrew"] = { first = 0x00590, last = 0x005FF, otf="hebr", description = "Hebrew" },
+ ["highprivateusesurrogates"] = { first = 0x0DB80, last = 0x0DBFF, description = "High Private Use Surrogates" },
+ ["highsurrogates"] = { first = 0x0D800, last = 0x0DB7F, description = "High Surrogates" },
+ ["hiragana"] = { first = 0x03040, last = 0x0309F, otf="kana", description = "Hiragana" },
+ ["ideographicdescriptioncharacters"] = { first = 0x02FF0, last = 0x02FFF, description = "Ideographic Description Characters" },
+ ["imperialaramaic"] = { first = 0x10840, last = 0x1085F, description = "Imperial Aramaic" },
+ ["inscriptionalpahlavi"] = { first = 0x10B60, last = 0x10B7F, description = "Inscriptional Pahlavi" },
+ ["inscriptionalparthian"] = { first = 0x10B40, last = 0x10B5F, description = "Inscriptional Parthian" },
+ ["ipaextensions"] = { first = 0x00250, last = 0x002AF, description = "IPA Extensions" },
+ ["javanese"] = { first = 0x0A980, last = 0x0A9DF, description = "Javanese" },
+ ["kaithi"] = { first = 0x11080, last = 0x110CF, description = "Kaithi" },
+ ["kanasupplement"] = { first = 0x1B000, last = 0x1B0FF, description = "Kana Supplement" },
+ ["kanbun"] = { first = 0x03190, last = 0x0319F, description = "Kanbun" },
+ ["kangxiradicals"] = { first = 0x02F00, last = 0x02FDF, description = "Kangxi Radicals" },
+ ["kannada"] = { first = 0x00C80, last = 0x00CFF, otf="knda", description = "Kannada" },
+ ["katakana"] = { first = 0x030A0, last = 0x030FF, otf="kana", description = "Katakana" },
+ ["katakanaphoneticextensions"] = { first = 0x031F0, last = 0x031FF, otf="kana", description = "Katakana Phonetic Extensions" },
+ ["kayahli"] = { first = 0x0A900, last = 0x0A92F, description = "Kayah Li" },
+ ["kharoshthi"] = { first = 0x10A00, last = 0x10A5F, otf="khar", description = "Kharoshthi" },
+ ["khmer"] = { first = 0x01780, last = 0x017FF, otf="khmr", description = "Khmer" },
+ ["khmersymbols"] = { first = 0x019E0, last = 0x019FF, otf="khmr", description = "Khmer Symbols" },
+ ["lao"] = { first = 0x00E80, last = 0x00EFF, otf="lao", description = "Lao" },
+ ["latinextendeda"] = { first = 0x00100, last = 0x0017F, otf="latn", description = "Latin Extended-A" },
+ ["latinextendedadditional"] = { first = 0x01E00, last = 0x01EFF, otf="latn", description = "Latin Extended Additional" },
+ ["latinextendedb"] = { first = 0x00180, last = 0x0024F, otf="latn", description = "Latin Extended-B" },
+ ["latinextendedc"] = { first = 0x02C60, last = 0x02C7F, otf="latn", description = "Latin Extended-C" },
+ ["latinextendedd"] = { first = 0x0A720, last = 0x0A7FF, otf="latn", description = "Latin Extended-D" },
+ ["latinsupplement"] = { first = 0x00080, last = 0x000FF, otf="latn", description = "Latin-1 Supplement" },
+ ["lepcha"] = { first = 0x01C00, last = 0x01C4F, description = "Lepcha" },
+ ["letterlikesymbols"] = { first = 0x02100, last = 0x0214F, description = "Letterlike Symbols" },
+ ["limbu"] = { first = 0x01900, last = 0x0194F, otf="limb", description = "Limbu" },
+ ["linearbideograms"] = { first = 0x10080, last = 0x100FF, otf="linb", description = "Linear B Ideograms" },
+ ["linearbsyllabary"] = { first = 0x10000, last = 0x1007F, otf="linb", description = "Linear B Syllabary" },
+ ["lisu"] = { first = 0x0A4D0, last = 0x0A4FF, description = "Lisu" },
+ ["lowsurrogates"] = { first = 0x0DC00, last = 0x0DFFF, description = "Low Surrogates" },
+ ["lycian"] = { first = 0x10280, last = 0x1029F, description = "Lycian" },
+ ["lydian"] = { first = 0x10920, last = 0x1093F, description = "Lydian" },
+ ["mahjongtiles"] = { first = 0x1F000, last = 0x1F02F, description = "Mahjong Tiles" },
+ ["malayalam"] = { first = 0x00D00, last = 0x00D7F, otf="mlym", description = "Malayalam" },
+ ["mandiac"] = { first = 0x00840, last = 0x0085F, otf="mand", description = "Mandaic" },
+ ["mathematicalalphanumericsymbols"] = { first = 0x1D400, last = 0x1D7FF, description = "Mathematical Alphanumeric Symbols" },
+ ["mathematicaloperators"] = { first = 0x02200, last = 0x022FF, description = "Mathematical Operators" },
+ ["meeteimayek"] = { first = 0x0ABC0, last = 0x0ABFF, description = "Meetei Mayek" },
+ ["meeteimayekextensions"] = { first = 0x0AAE0, last = 0x0AAFF, description = "Meetei Mayek Extensions" },
+ ["meroiticcursive"] = { first = 0x109A0, last = 0x109FF, description = "Meroitic Cursive" },
+ ["meroitichieroglyphs"] = { first = 0x10980, last = 0x1099F, description = "Meroitic Hieroglyphs" },
+ ["miao"] = { first = 0x16F00, last = 0x16F9F, description = "Miao" },
+ ["miscellaneousmathematicalsymbolsa"] = { first = 0x027C0, last = 0x027EF, description = "Miscellaneous Mathematical Symbols-A" },
+ ["miscellaneousmathematicalsymbolsb"] = { first = 0x02980, last = 0x029FF, description = "Miscellaneous Mathematical Symbols-B" },
+ ["miscellaneoussymbols"] = { first = 0x02600, last = 0x026FF, description = "Miscellaneous Symbols" },
+ ["miscellaneoussymbolsandarrows"] = { first = 0x02B00, last = 0x02BFF, description = "Miscellaneous Symbols and Arrows" },
+ ["miscellaneoussymbolsandpictographs"] = { first = 0x1F300, last = 0x1F5FF, description = "Miscellaneous Symbols And Pictographs" },
+ ["miscellaneoustechnical"] = { first = 0x02300, last = 0x023FF, description = "Miscellaneous Technical" },
+ ["modifiertoneletters"] = { first = 0x0A700, last = 0x0A71F, description = "Modifier Tone Letters" },
+ ["mongolian"] = { first = 0x01800, last = 0x018AF, otf="mong", description = "Mongolian" },
+ ["musicalsymbols"] = { first = 0x1D100, last = 0x1D1FF, otf="musc", description = "Musical Symbols" },
+ ["myanmar"] = { first = 0x01000, last = 0x0109F, otf="mymr", description = "Myanmar" },
+ ["myanmarextendeda"] = { first = 0x0AA60, last = 0x0AA7F, description = "Myanmar Extended-A" },
+ ["newtailue"] = { first = 0x01980, last = 0x019DF, description = "New Tai Lue" },
+ ["nko"] = { first = 0x007C0, last = 0x007FF, otf="nko", description = "NKo" },
+ ["numberforms"] = { first = 0x02150, last = 0x0218F, description = "Number Forms" },
+ ["ogham"] = { first = 0x01680, last = 0x0169F, otf="ogam", description = "Ogham" },
+ ["olchiki"] = { first = 0x01C50, last = 0x01C7F, description = "Ol Chiki" },
+ ["olditalic"] = { first = 0x10300, last = 0x1032F, otf="ital", description = "Old Italic" },
+ ["oldpersian"] = { first = 0x103A0, last = 0x103DF, otf="xpeo", description = "Old Persian" },
+ ["oldsoutharabian"] = { first = 0x10A60, last = 0x10A7F, description = "Old South Arabian" },
+ ["odlturkic"] = { first = 0x10C00, last = 0x10C4F, description = "Old Turkic" },
+ ["opticalcharacterrecognition"] = { first = 0x02440, last = 0x0245F, description = "Optical Character Recognition" },
+ ["oriya"] = { first = 0x00B00, last = 0x00B7F, otf="orya", description = "Oriya" },
+ ["osmanya"] = { first = 0x10480, last = 0x104AF, otf="osma", description = "Osmanya" },
+ ["phagspa"] = { first = 0x0A840, last = 0x0A87F, otf="phag", description = "Phags-pa" },
+ ["phaistosdisc"] = { first = 0x101D0, last = 0x101FF, description = "Phaistos Disc" },
+ ["phoenician"] = { first = 0x10900, last = 0x1091F, otf="phnx", description = "Phoenician" },
+ ["phoneticextensions"] = { first = 0x01D00, last = 0x01D7F, description = "Phonetic Extensions" },
+ ["phoneticextensionssupplement"] = { first = 0x01D80, last = 0x01DBF, description = "Phonetic Extensions Supplement" },
+ ["playingcards"] = { first = 0x1F0A0, last = 0x1F0FF, description = "Playing Cards" },
+ ["privateusearea"] = { first = 0x0E000, last = 0x0F8FF, description = "Private Use Area" },
+ ["rejang"] = { first = 0x0A930, last = 0x0A95F, description = "Rejang" },
+ ["ruminumeralsymbols"] = { first = 0x10E60, last = 0x10E7F, description = "Rumi Numeral Symbols" },
+ ["runic"] = { first = 0x016A0, last = 0x016FF, otf="runr", description = "Runic" },
+ ["samaritan"] = { first = 0x00800, last = 0x0083F, description = "Samaritan" },
+ ["saurashtra"] = { first = 0x0A880, last = 0x0A8DF, description = "Saurashtra" },
+ ["sharada"] = { first = 0x11180, last = 0x111DF, description = "Sharada" },
+ ["shavian"] = { first = 0x10450, last = 0x1047F, otf="shaw", description = "Shavian" },
+ ["sinhala"] = { first = 0x00D80, last = 0x00DFF, otf="sinh", description = "Sinhala" },
+ ["smallformvariants"] = { first = 0x0FE50, last = 0x0FE6F, description = "Small Form Variants" },
+ ["sorasompeng"] = { first = 0x110D0, last = 0x110FF, description = "Sora Sompeng" },
+ ["spacingmodifierletters"] = { first = 0x002B0, last = 0x002FF, description = "Spacing Modifier Letters" },
+ ["specials"] = { first = 0x0FFF0, last = 0x0FFFF, description = "Specials" },
+ ["sundanese"] = { first = 0x01B80, last = 0x01BBF, description = "Sundanese" },
+ ["sundanesesupplement"] = { first = 0x01CC0, last = 0x01CCF, description = "Sundanese Supplement" },
+ ["superscriptsandsubscripts"] = { first = 0x02070, last = 0x0209F, description = "Superscripts and Subscripts" },
+ ["supplementalarrowsa"] = { first = 0x027F0, last = 0x027FF, description = "Supplemental Arrows-A" },
+ ["supplementalarrowsb"] = { first = 0x02900, last = 0x0297F, description = "Supplemental Arrows-B" },
+ ["supplementalmathematicaloperators"] = { first = 0x02A00, last = 0x02AFF, description = "Supplemental Mathematical Operators" },
+ ["supplementalpunctuation"] = { first = 0x02E00, last = 0x02E7F, description = "Supplemental Punctuation" },
+ ["supplementaryprivateuseareaa"] = { first = 0xF0000, last = 0xFFFFF, description = "Supplementary Private Use Area-A" },
+ ["supplementaryprivateuseareab"] = { first = 0x100000,last = 0x10FFFF, description = "Supplementary Private Use Area-B" },
+ ["sylotinagri"] = { first = 0x0A800, last = 0x0A82F, otf="sylo", description = "Syloti Nagri" },
+ ["syriac"] = { first = 0x00700, last = 0x0074F, otf="syrc", description = "Syriac" },
+ ["tagalog"] = { first = 0x01700, last = 0x0171F, otf="tglg", description = "Tagalog" },
+ ["tagbanwa"] = { first = 0x01760, last = 0x0177F, otf="tagb", description = "Tagbanwa" },
+ ["tags"] = { first = 0xE0000, last = 0xE007F, description = "Tags" },
+ ["taile"] = { first = 0x01950, last = 0x0197F, otf="tale", description = "Tai Le" },
+ ["taitham"] = { first = 0x01A20, last = 0x01AAF, description = "Tai Tham" },
+ ["taiviet"] = { first = 0x0AA80, last = 0x0AADF, description = "Tai Viet" },
+ ["taixuanjingsymbols"] = { first = 0x1D300, last = 0x1D35F, description = "Tai Xuan Jing Symbols" },
+ ["takri"] = { first = 0x11680, last = 0x116CF, description = "Takri" },
+ ["tamil"] = { first = 0x00B80, last = 0x00BFF, otf="taml", description = "Tamil" },
+ ["telugu"] = { first = 0x00C00, last = 0x00C7F, otf="telu", description = "Telugu" },
+ ["thaana"] = { first = 0x00780, last = 0x007BF, otf="thaa", description = "Thaana" },
+ ["thai"] = { first = 0x00E00, last = 0x00E7F, otf="thai", description = "Thai" },
+ ["tibetan"] = { first = 0x00F00, last = 0x00FFF, otf="tibt", description = "Tibetan" },
+ ["tifinagh"] = { first = 0x02D30, last = 0x02D7F, otf="tfng", description = "Tifinagh" },
+ ["transportandmapsymbols"] = { first = 0x1F680, last = 0x1F6FF, description = "Transport And Map Symbols" },
+ ["ugaritic"] = { first = 0x10380, last = 0x1039F, otf="ugar", description = "Ugaritic" },
+ ["unifiedcanadianaboriginalsyllabics"] = { first = 0x01400, last = 0x0167F, otf="cans", description = "Unified Canadian Aboriginal Syllabics" },
+ ["unifiedcanadianaboriginalsyllabicsextended"] = { first = 0x018B0, last = 0x018FF, description = "Unified Canadian Aboriginal Syllabics Extended" },
+ ["vai"] = { first = 0x0A500, last = 0x0A63F, description = "Vai" },
+ ["variationselectors"] = { first = 0x0FE00, last = 0x0FE0F, description = "Variation Selectors" },
+ ["variationselectorssupplement"] = { first = 0xE0100, last = 0xE01EF, description = "Variation Selectors Supplement" },
+ ["vedicextensions"] = { first = 0x01CD0, last = 0x01CFF, description = "Vedic Extensions" },
+ ["verticalforms"] = { first = 0x0FE10, last = 0x0FE1F, description = "Vertical Forms" },
+ ["yijinghexagramsymbols"] = { first = 0x04DC0, last = 0x04DFF, otf="yi", description = "Yijing Hexagram Symbols" },
+ ["yiradicals"] = { first = 0x0A490, last = 0x0A4CF, otf="yi", description = "Yi Radicals" },
+ ["yisyllables"] = { first = 0x0A000, last = 0x0A48F, otf="yi", description = "Yi Syllables" },
}
characters.blocks = blocks
-setmetatableindex(blocks, function(t,k)
+function characters.blockrange(name)
+ local b = blocks[name]
+ if b then
+ return b.first, b.last
+ else
+ return 0, 0
+ end
+end
+
+setmetatableindex(blocks, function(t,k) -- we could use an intermediate table if called often
return k and rawget(t,lower(gsub(k,"[^a-zA-Z]","")))
end)
+local otfscripts = utilities.storage.allocate()
+characters.otfscripts = otfscripts
+
+setmetatableindex(otfscripts,function(t,unicode)
+ for k, v in next, blocks do
+ local first, last = v.first, v.last
+ if unicode >= first and unicode <= last then
+ local script = v.otf or "dflt"
+ for u=first,last do
+ t[u] = script
+ end
+ return script
+ end
+ end
+ -- pretty slow when we're here
+ t[unicode] = "dflt"
+ return "dflt"
+end)
+
function characters.getrange(name) -- used in font fallback definitions (name or range)
local range = blocks[name]
if range then
@@ -395,6 +459,8 @@ local is_mark = allocate ( tohash {
"mn", "ms",
} )
+-- to be redone: store checked characters
+
characters.is_character = is_character
characters.is_letter = is_letter
characters.is_command = is_command
@@ -404,7 +470,7 @@ characters.is_mark = is_mark
local mt = { -- yes or no ?
__index = function(t,k)
if type(k) == "number" then
- local c = characters.data[k].category
+ local c = data[k].category
return c and rawget(t,c)
else
-- avoid auto conversion in data.characters lookups
@@ -455,213 +521,47 @@ table we derive a few more.
if not characters.fallbacks then
- -- we could the definition by using a metatable
+ characters.fallbacks = { } -- not than many
- characters.fallbacks = { }
- characters.directions = { }
+ local fallbacks = characters.fallbacks
- local fallbacks = characters.fallbacks
- local directions = characters.directions
-
- for k,v in next, data do
- local specials = v.specials
- if specials and specials[1] == "compat" and specials[2] == 0x0020 and specials[3] then
+ for k, d in next, data do
+ local specials = d.specials
+ if specials and specials[1] == "compat" and specials[2] == 0x0020 then
local s = specials[3]
- fallbacks[k] = s
- fallbacks[s] = k
- end
- directions[k] = v.direction
- end
-
-end
-
-storage.register("characters/fallbacks", characters.fallbacks, "characters.fallbacks") -- accents and such
-storage.register("characters/directions", characters.directions, "characters.directions")
-
---[[ldx--
-The context namespace is used to store methods and data
-which is rather specific to .
---ldx]]--
-
---[[ldx--
-Instead of using a file to define the named glyphs, we
-use the table. After all, we have this information available anyway.
---ldx]]--
-
-function characters.makeactive(n,name) -- let ?
- contextsprint(ctxcatcodes,format("\\catcode%s=13\\unexpanded\\def %s{\\%s}",n,utfchar(n),name))
- -- context("\\catcode%s=13\\unexpanded\\def %s{\\%s}",n,utfchar(n),name)
-end
-
-function tex.uprint(c,n)
- if n then
- -- contextsprint(c,charfromnumber(n))
- contextsprint(c,utfchar(n))
- else
- -- contextsprint(charfromnumber(c))
- contextsprint(utfchar(c))
- end
-end
-
-local temphack = tohash {
- 0x00A0,
- 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x200B, 0x200C, 0x200D,
- 0x202F,
- 0x205F,
- -- 0xFEFF,
-}
-
-function characters.define(tobelettered, tobeactivated) -- catcodetables
-
- if trace_defining then
- report_defining("defining active character commands")
- end
-
- local activated, a = { }, 0
-
- for u, chr in next, data do -- these will be commands
- local fallback = chr.fallback
- if fallback then
- contextsprint("{\\catcode",u,"=13\\unexpanded\\gdef ",utfchar(u),"{\\checkedchar{",u,"}{",fallback,"}}}")
- a = a + 1
- activated[a] = u
- else
- local contextname = chr.contextname
- if contextname then
- local category = chr.category
- if is_character[category] then
- if chr.unicodeslot < 128 then
- if is_letter[category] then
- contextsprint(ctxcatcodes,format("\\def\\%s{%s}",contextname,utfchar(u))) -- has no s
- else
- contextsprint(ctxcatcodes,format("\\chardef\\%s=%s",contextname,u)) -- has no s
- end
- else
- contextsprint(ctxcatcodes,format("\\def\\%s{%s}",contextname,utfchar(u))) -- has no s
- end
- elseif is_command[category] then
-if not temphack[u] then
- contextsprint("{\\catcode",u,"=13\\unexpanded\\gdef ",utfchar(u),"{\\"..contextname,"}}")
- a = a + 1
- activated[a] = u
-end
- end
+ if s then
+ fallbacks[k] = s
+ fallbacks[s] = k
end
end
end
- if tobelettered then -- shared
- local saved = tex.catcodetable
- for i=1,#tobelettered do
- tex.catcodetable = tobelettered[i]
- if trace_defining then
- report_defining("defining letters (global, shared)")
- end
- for u, chr in next, data do
- if not chr.fallback and is_letter[chr.category] and u >= 128 and u <= 65536 then
- texsetcatcode(u,11)
- end
- local range = chr.range
- if range then
- for i=1,range.first,range.last do
- texsetcatcode(i,11)
- end
- end
- end
- texsetcatcode(0x200C,11) -- non-joiner
- texsetcatcode(0x200D,11) -- joiner
- end
- tex.catcodetable = saved
- end
-
- local nofactivated = #tobeactivated
- if tobeactivated and nofactivated > 0 then
- for i=1,nofactivated do
- local u = activated[i]
- if u then
- report_defining("character 0x%05X is active in sets %s (%s)",u,concat(tobeactivated,","),data[u].description)
- end
- end
- local saved = tex.catcodetable
- for i=1,#tobeactivated do
- local vector = tobeactivated[i]
- if trace_defining then
- report_defining("defining %s active characters in vector %s",nofactivated,vector)
- end
- tex.catcodetable = vector
- for i=1,nofactivated do
- local u = activated[i]
- if u then
- texsetcatcode(u,13)
- end
- end
- end
- tex.catcodetable = saved
- end
-
end
---[[ldx--
-Setting the lccodes is also done in a loop over the data table.
---ldx]]--
-
---~ function tex.setsfcode (index,sf) ... end
---~ function tex.setlccode (index,lc,[uc]) ... end -- optional third value, safes call
---~ function tex.setuccode (index,uc,[lc]) ... end
---~ function tex.setcatcode(index,cc) ... end
-
--- we need a function ...
+if storage then
+ storage.register("characters/fallbacks", characters.fallbacks, "characters.fallbacks") -- accents and such
+end
---~ tex.lccode
---~ tex.uccode
---~ tex.sfcode
---~ tex.catcode
+characters.directions = { }
-function characters.setcodes()
- if trace_defining then
- report_defining("defining lc and uc codes")
- end
- for code, chr in next, data do
- local cc = chr.category
- if is_letter[cc] then
- local range = chr.range
- if range then
- for i=range.first,range.last do
- texsetcatcode(i,11) -- letter
- texsetlccode(i,i,i) -- self self
- end
- else
- local lc, uc = chr.lccode, chr.uccode
- if not lc then chr.lccode, lc = code, code end
- if not uc then chr.uccode, uc = code, code end
- texsetcatcode(code,11) -- letter
- if type(lc) == "table" then
- lc = code
- end
- if type(uc) == "table" then
- uc = code
- end
- texsetlccode(code,lc,uc)
- if cc == "lu" then
- texsetsfcode(code,999)
- end
- end
- elseif is_mark[cc] then
- texsetlccode(code,code,code) -- for hyphenation
+setmetatableindex(characters.directions,function(t,k)
+ local d = data[k]
+ if d then
+ local v = d.direction
+ if v then
+ t[k] = v
+ return v
end
end
-end
+ t[k] = false -- maybe 'l'
+ return v
+end)
--[[ldx--
Next comes a whole series of helper methods. These are (will be) part
of the official .
--ldx]]--
---[[ldx--
-A couple of convenience methods. Beware, these are slower than directly
-accessing the data table.
---ldx]]--
-
-- we could make them virtual: characters.contextnames[n]
function characters.contextname(n) return data[n].contextname or "" end
@@ -680,35 +580,17 @@ function characters.category(n,verbose)
end
end
--- xml support (moved)
-
-function characters.remapentity(chr,slot)
- contextsprint(format("{\\catcode%s=13\\xdef%s{\\string%s}}",slot,utfchar(slot),chr))
-end
-
-characters.activeoffset = 0x10000 -- there will be remapped in that byte range
-
--- xml.entities = xml.entities or { }
+-- -- some day we will make a table .. not that many calls to utfchar
--
--- storage.register("xml/entities",xml.entities,"xml.entities") -- this will move to lxml
+-- local utfchar = utf.char
+-- local utfbyte = utf.byte
+-- local utfbytes = { }
+-- local utfchars = { }
--
--- function characters.setmkiventities()
--- local entities = xml.entities
--- entities.lt = "<"
--- entities.amp = "&"
--- entities.gt = ">"
--- end
---
--- function characters.setmkiientities()
--- local entities = xml.entities
--- entities.lt = utfchar(characters.activeoffset + utfbyte("<"))
--- entities.amp = utfchar(characters.activeoffset + utfbyte("&"))
--- entities.gt = utfchar(characters.activeoffset + utfbyte(">"))
--- end
-
--- some day we will make a table
+-- table.setmetatableindex(utfbytes,function(t,k) local v = utfchar(k) t[k] = v return v end)
+-- table.setmetatableindex(utfchars,function(t,k) local v = utfbyte(k) t[k] = v return v end)
-local function utfstring(s)
+local function toutfstring(s)
if type(s) == "table" then
return utfchar(unpack(s)) -- concat { utfchar( unpack(s) ) }
else
@@ -716,7 +598,7 @@ local function utfstring(s)
end
end
-utf.string = utf.string or utfstring
+utf.tostring = toutfstring
local categories = allocate() characters.categories = categories -- lazy table
@@ -737,10 +619,10 @@ local ucchars = allocate() characters.ucchars = ucchars -- lazy table
local shchars = allocate() characters.shchars = shchars -- lazy table
local fschars = allocate() characters.fschars = fschars -- lazy table
-setmetatableindex(lcchars, function(t,u) if u then local c = data[u] c = c and c.lccode c = c and utfstring(c) or (type(u) == "number" and utfchar(u)) or u t[u] = c return c end end)
-setmetatableindex(ucchars, function(t,u) if u then local c = data[u] c = c and c.uccode c = c and utfstring(c) or (type(u) == "number" and utfchar(u)) or u t[u] = c return c end end)
-setmetatableindex(shchars, function(t,u) if u then local c = data[u] c = c and c.shcode c = c and utfstring(c) or (type(u) == "number" and utfchar(u)) or u t[u] = c return c end end)
-setmetatableindex(fschars, function(t,u) if u then local c = data[u] c = c and c.fscode c = c and utfstring(c) or (type(u) == "number" and utfchar(u)) or u t[u] = c return c end end)
+setmetatableindex(lcchars, function(t,u) if u then local c = data[u] c = c and c.lccode c = c and toutfstring(c) or (type(u) == "number" and utfchar(u)) or u t[u] = c return c end end)
+setmetatableindex(ucchars, function(t,u) if u then local c = data[u] c = c and c.uccode c = c and toutfstring(c) or (type(u) == "number" and utfchar(u)) or u t[u] = c return c end end)
+setmetatableindex(shchars, function(t,u) if u then local c = data[u] c = c and c.shcode c = c and toutfstring(c) or (type(u) == "number" and utfchar(u)) or u t[u] = c return c end end)
+setmetatableindex(fschars, function(t,u) if u then local c = data[u] c = c and c.fscode c = c and toutfstring(c) or (type(u) == "number" and utfchar(u)) or u t[u] = c return c end end)
local decomposed = allocate() characters.decomposed = decomposed -- lazy table
local specials = allocate() characters.specials = specials -- lazy table
@@ -815,37 +697,52 @@ function characters.unicodechar(asked)
if n then
return n
elseif type(asked) == "string" then
- asked = gsub(asked," ","")
- return descriptions[asked]
+ return descriptions[asked] or descriptions[gsub(asked," ","")]
end
end
-function characters.lower(str)
- local new, n = { }, 0
- for u in utfvalues(str) do
- n = n + 1
- new[n] = lcchars[u]
- end
- return concat(new)
-end
+-- function characters.lower(str)
+-- local new, n = { }, 0
+-- for u in utfvalues(str) do
+-- n = n + 1
+-- new[n] = lcchars[u]
+-- end
+-- return concat(new)
+-- end
+--
+-- function characters.upper(str)
+-- local new, n = { }, 0
+-- for u in utfvalues(str) do
+-- n = n + 1
+-- new[n] = ucchars[u]
+-- end
+-- return concat(new)
+-- end
+--
+-- function characters.shaped(str)
+-- local new, n = { }, 0
+-- for u in utfvalues(str) do
+-- n = n + 1
+-- new[n] = shchars[u]
+-- end
+-- return concat(new)
+-- end
-function characters.upper(str)
- local new, n = { }, 0
- for u in utfvalues(str) do
- n = n + 1
- new[n] = ucchars[u]
- end
- return concat(new)
-end
+----- tolower = Cs((utf8byte/lcchars)^0)
+----- toupper = Cs((utf8byte/ucchars)^0)
+----- toshape = Cs((utf8byte/shchars)^0)
-function characters.shaped(str)
- local new, n = { }, 0
- for u in utfvalues(str) do
- n = n + 1
- new[n] = shchars[u]
- end
- return concat(new)
-end
+local tolower = Cs((utf8char/lcchars)^0)
+local toupper = Cs((utf8char/ucchars)^0)
+local toshape = Cs((utf8char/shchars)^0)
+
+patterns.tolower = tolower
+patterns.toupper = toupper
+patterns.toshape = toshape
+
+function characters.lower (str) return lpegmatch(tolower,str) end
+function characters.upper (str) return lpegmatch(toupper,str) end
+function characters.shaped(str) return lpegmatch(toshape,str) end
function characters.lettered(str,spacing)
local new, n = { }, 0
@@ -875,6 +772,7 @@ function characters.lettered(str,spacing)
end
return concat(new)
end
+
--[[ldx--
Requesting lower and uppercase codes:
--ldx]]--
@@ -882,17 +780,12 @@ end
function characters.uccode(n) return uccodes[n] end -- obsolete
function characters.lccode(n) return lccodes[n] end -- obsolete
-function characters.flush(n,direct)
+function characters.safechar(n)
local c = data[n]
if c and c.contextname then
- c = "\\" .. c.contextname
- else
- c = utfchar(n)
- end
- if direct then
- return c
+ return "\\" .. c.contextname
else
- contextsprint(c)
+ return utfchar(n)
end
end
@@ -996,13 +889,13 @@ if not characters.superscripts then
if #specials == 2 then
superscripts[k] = specials[2]
else
- report_defining("ignoring superscript %s %s: %s",ustring(k),utfchar(k),v.description)
+ report_defining("ignoring %s %a, char %c, description %a","superscript",ustring(k),k,v.description)
end
elseif what == "sub" then
if #specials == 2 then
subscripts[k] = specials[2]
else
- report_defining("ignoring subscript %s %s: %s",ustring(k),utfchar(k),v.description)
+ report_defining("ignoring %s %a, char %c, description %a","subscript",ustring(k),k,v.description)
end
end
end
@@ -1011,11 +904,255 @@ if not characters.superscripts then
-- print(table.serialize(superscripts, "superscripts", { hexify = true }))
-- print(table.serialize(subscripts, "subscripts", { hexify = true }))
- storage.register("characters/superscripts", superscripts, "characters.superscripts")
- storage.register("characters/subscripts", subscripts, "characters.subscripts")
+ if storage then
+ storage.register("characters/superscripts", superscripts, "characters.superscripts")
+ storage.register("characters/subscripts", subscripts, "characters.subscripts")
+ end
+
+end
+
+-- for the moment only a few
+
+local tracedchars = utilities.strings.tracers
+
+tracedchars[0x00] = "[signal]"
+tracedchars[0x20] = "[space]"
+
+-- the following code will move to char-tex.lua
+
+-- tex
+
+if not tex or not context or not commands then return characters end
+
+local tex = tex
+local texsetlccode = tex.setlccode
+local texsetuccode = tex.setuccode
+local texsetsfcode = tex.setsfcode
+local texsetcatcode = tex.setcatcode
+
+local contextsprint = context.sprint
+local ctxcatcodes = catcodes.numbers.ctxcatcodes
+
+--[[ldx--
+Instead of using a file to define the named glyphs, we
+use the table. After all, we have this information available anyway.
+--ldx]]--
+
+function commands.makeactive(n,name) --
+ contextsprint(ctxcatcodes,format("\\catcode%s=13\\unexpanded\\def %s{\\%s}",n,utfchar(n),name))
+ -- context("\\catcode%s=13\\unexpanded\\def %s{\\%s}",n,utfchar(n),name)
+end
+
+function commands.utfchar(c,n)
+ if n then
+ -- contextsprint(c,charfromnumber(n))
+ contextsprint(c,utfchar(n))
+ else
+ -- contextsprint(charfromnumber(c))
+ contextsprint(utfchar(c))
+ end
+end
+function commands.safechar(n)
+ local c = data[n]
+ if c and c.contextname then
+ contextsprint("\\" .. c.contextname) -- context[c.contextname]()
+ else
+ contextsprint(utfchar(n))
+ end
end
--- interface
+tex.uprint = commands.utfchar
+
+local forbidden = tohash { -- at least now
+ 0x00A0,
+ 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x200B, 0x200C, 0x200D,
+ 0x202F,
+ 0x205F,
+ -- 0xFEFF,
+}
+
+function characters.define(tobelettered, tobeactivated) -- catcodetables
+
+ if trace_defining then
+ report_defining("defining active character commands")
+ end
+
+ local activated, a = { }, 0
+
+ for u, chr in next, data do -- these will be commands
+ local fallback = chr.fallback
+ if fallback then
+ contextsprint("{\\catcode",u,"=13\\unexpanded\\gdef ",utfchar(u),"{\\checkedchar{",u,"}{",fallback,"}}}")
+ a = a + 1
+ activated[a] = u
+ else
+ local contextname = chr.contextname
+ if contextname then
+ local category = chr.category
+ if is_character[category] then
+ if chr.unicodeslot < 128 then
+ if is_letter[category] then
+ contextsprint(ctxcatcodes,format("\\def\\%s{%s}",contextname,utfchar(u))) -- has no s
+ else
+ contextsprint(ctxcatcodes,format("\\chardef\\%s=%s",contextname,u)) -- has no s
+ end
+ else
+ contextsprint(ctxcatcodes,format("\\def\\%s{%s}",contextname,utfchar(u))) -- has no s
+ end
+ elseif is_command[category] and not forbidden[u] then
+ contextsprint("{\\catcode",u,"=13\\unexpanded\\gdef ",utfchar(u),"{\\"..contextname,"}}")
+ a = a + 1
+ activated[a] = u
+ end
+ end
+ end
+ end
+
+ if tobelettered then -- shared
+ local saved = tex.catcodetable
+ for i=1,#tobelettered do
+ tex.catcodetable = tobelettered[i]
+ if trace_defining then
+ report_defining("defining letters (global, shared)")
+ end
+ for u, chr in next, data do
+ if not chr.fallback and is_letter[chr.category] and u >= 128 and u <= 65536 then
+ texsetcatcode(u,11)
+ end
+ local range = chr.range
+ if range then
+ for i=1,range.first,range.last do
+ texsetcatcode(i,11)
+ end
+ end
+ end
+ texsetcatcode(0x200C,11) -- non-joiner
+ texsetcatcode(0x200D,11) -- joiner
+ end
+ tex.catcodetable = saved
+ end
+
+ local nofactivated = #tobeactivated
+ if tobeactivated and nofactivated > 0 then
+ for i=1,nofactivated do
+ local u = activated[i]
+ if u then
+ report_defining("character %U is active in set %a, containing %a",u,data[u].description,tobeactivated)
+ end
+ end
+ local saved = tex.catcodetable
+ for i=1,#tobeactivated do
+ local vector = tobeactivated[i]
+ if trace_defining then
+ report_defining("defining %a active characters in vector %a",nofactivated,vector)
+ end
+ tex.catcodetable = vector
+ for i=1,nofactivated do
+ local u = activated[i]
+ if u then
+ texsetcatcode(u,13)
+ end
+ end
+ end
+ tex.catcodetable = saved
+ end
+
+end
+
+--[[ldx--
+Setting the lccodes is also done in a loop over the data table.
+--ldx]]--
+
+local sfmode = "unset" -- unset, traditional, normal
+
+function characters.setcodes()
+ if trace_defining then
+ report_defining("defining lc and uc codes")
+ end
+ local traditional = sfstate == "traditional" or sfstate == "unset"
+ for code, chr in next, data do
+ local cc = chr.category
+ if is_letter[cc] then
+ local range = chr.range
+ if range then
+ for i=range.first,range.last do
+ texsetcatcode(i,11) -- letter
+ texsetlccode(i,i,i) -- self self
+ end
+ else
+ local lc, uc = chr.lccode, chr.uccode
+ if not lc then
+ chr.lccode, lc = code, code
+ elseif type(lc) == "table" then
+ lc = code
+ end
+ if not uc then
+ chr.uccode, uc = code, code
+ elseif type(uc) == "table" then
+ uc = code
+ end
+ texsetcatcode(code,11) -- letter
+ texsetlccode(code,lc,uc)
+ if traditional and cc == "lu" then
+ texsetsfcode(code,999)
+ end
+ end
+ elseif is_mark[cc] then
+ texsetlccode(code,code,code) -- for hyphenation
+ end
+ end
+ if traditional then
+ sfstate = "traditional"
+ end
+end
+
+-- If this is something that is not documentwide and used a lot, then we
+-- need a more clever approach (trivial but not now).
+
+local function setuppersfcodes(v,n)
+ if sfstate ~= "unset" then
+ report_defining("setting uppercase sf codes to %a",n)
+ for code, chr in next, data do
+ if chr.category == "lu" then
+ texsetsfcode(code,n)
+ end
+ end
+ end
+ sfstate = v
+end
+
+directives.register("characters.spaceafteruppercase",function(v)
+ if v == "traditional" then
+ setuppersfcodes(v,999)
+ elseif v == "normal" then
+ setuppersfcodes(v,1000)
+ end
+end)
+
+-- xml
+
+characters.activeoffset = 0x10000 -- there will be remapped in that byte range
+
+function commands.remapentity(chr,slot)
+ contextsprint(format("{\\catcode%s=13\\xdef%s{\\string%s}}",slot,utfchar(slot),chr))
+end
+
+-- xml.entities = xml.entities or { }
+--
+-- storage.register("xml/entities",xml.entities,"xml.entities") -- this will move to lxml
+--
+-- function characters.setmkiventities()
+-- local entities = xml.entities
+-- entities.lt = "<"
+-- entities.amp = "&"
+-- entities.gt = ">"
+-- end
+--
+-- function characters.setmkiientities()
+-- local entities = xml.entities
+-- entities.lt = utfchar(characters.activeoffset + utfbyte("<"))
+-- entities.amp = utfchar(characters.activeoffset + utfbyte("&"))
+-- entities.gt = utfchar(characters.activeoffset + utfbyte(">"))
+-- end
-commands.utfchar = tex.uprint
diff --git a/Master/texmf-dist/tex/context/base/char-ini.mkiv b/Master/texmf-dist/tex/context/base/char-ini.mkiv
index d1d7574c954..0e2b773f09f 100644
--- a/Master/texmf-dist/tex/context/base/char-ini.mkiv
+++ b/Master/texmf-dist/tex/context/base/char-ini.mkiv
@@ -39,8 +39,12 @@
% {\relax\iffontchar\font#1 \expandafter\firstoftwoarguments\else\expandafter\secondoftwoarguments\fi{\char#1}}
%
% impossible in math mode so there always fallback (till we have gyre):
+%
+% use \normalUchar when possible .. the next one is nice for documents and it also accepts
+% 0x prefixed numbers
+
+\def\utfchar#1{\ctxcommand{utfchar(\number#1)}}
-\def\utfchar #1{\ctxcommand{utfchar(\number#1)}}
\def\checkedchar {\relax\ifmmode\expandafter\checkedmathchar\else\expandafter\checkedtextchar\fi} % #1#2
\def\checkedmathchar#1#2{#2}
\def\checkedtextchar #1{\iffontchar\font#1 \expandafter\firstoftwoarguments\else\expandafter\secondoftwoarguments\fi{\char#1}}
diff --git a/Master/texmf-dist/tex/context/base/char-map.lua b/Master/texmf-dist/tex/context/base/char-map.lua
index 376ebf343b9..749da5289bd 100644
--- a/Master/texmf-dist/tex/context/base/char-map.lua
+++ b/Master/texmf-dist/tex/context/base/char-map.lua
@@ -3,7 +3,8 @@ if not modules then modules = { } end modules ['char-map'] = {
comment = "companion to char-ini.mkiv",
author = "Hans Hagen & Arthur Reutenauer",
copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
+ license = "see context related readme files",
+ dataonly = true,
}
-- not yet used
diff --git a/Master/texmf-dist/tex/context/base/char-tex.lua b/Master/texmf-dist/tex/context/base/char-tex.lua
index e6d6c41e0fa..91aa387b959 100644
--- a/Master/texmf-dist/tex/context/base/char-tex.lua
+++ b/Master/texmf-dist/tex/context/base/char-tex.lua
@@ -189,14 +189,13 @@ local convert_accents_strip = Cs((no_l * accents * no_r + accents + P(1))^0)
local convert_commands_strip = Cs((no_l * commands * no_r + commands + P(1))^0)
function characters.tex.toutf(str,strip)
- if find(str,"\\") then -- we can start at the found position
- if strip then
- return lpegmatch(convert_accents_strip,lpegmatch(convert_commands_strip,str))
- else
- return lpegmatch(convert_accents, lpegmatch(convert_commands, str))
- end
+ if not find(str,"\\") then -- we can start at the found position
+ return str
+ elseif strip then
+ return lpegmatch(convert_accents_strip,lpegmatch(convert_commands_strip,str))
+ else
+ return lpegmatch(convert_accents, lpegmatch(convert_commands, str))
end
- return str
end
--~ print(characters.tex.toutf([[\"{e}]]),true)
diff --git a/Master/texmf-dist/tex/context/base/char-utf.lua b/Master/texmf-dist/tex/context/base/char-utf.lua
index a411c2d82a6..d0e40e664a6 100644
--- a/Master/texmf-dist/tex/context/base/char-utf.lua
+++ b/Master/texmf-dist/tex/context/base/char-utf.lua
@@ -19,10 +19,10 @@ in special kinds of output (for instance ).
over a string.
--ldx]]--
-local utfchar, utfbyte, utfgsub = utf.char, utf.byte, utf.gsub
local concat, gmatch, gsub, find = table.concat, string.gmatch, string.gsub, string.find
-local utfcharacters, utfvalues = string.utfcharacters, string.utfvalues
+local utfchar, utfbyte, utfcharacters, utfvalues = utf.char, utf.byte, utf.characters, utf.values
local allocate = utilities.storage.allocate
+local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
local charfromnumber = characters.fromnumber
@@ -76,6 +76,7 @@ local decomposed = allocate {
["ﬖ"] = "վն",
["ﬗ"] = "մխ",
}
+
characters.decomposed = decomposed
local function initialize() -- maybe only 'mn'
@@ -193,6 +194,20 @@ local private = {
utffilters.private = private
+local tohigh = lpeg.replacer(low) -- frozen, only for basic tex
+local tolow = lpeg.replacer(high) -- frozen, only for basic tex
+
+lpegpatterns.utftohigh = tohigh
+lpegpatterns.utftolow = tolow
+
+function utffilters.harden(str)
+ return lpegmatch(tohigh,str)
+end
+
+function utffilters.soften(str)
+ return lpegmatch(tolow,str)
+end
+
local function set(ch)
local cb
if type(ch) == "number" then
@@ -201,17 +216,24 @@ local function set(ch)
cb = utfbyte(ch)
end
if cb < 256 then
+ escapes[ch] = "\\" .. ch
low[ch] = utfchar(0x0F0000 + cb)
+ if ch == "%" then
+ ch = "%%" -- nasty, but we need this as in replacements (also in lpeg) % is interpreted
+ end
high[utfchar(0x0F0000 + cb)] = ch
- escapes[ch] = "\\" .. ch
end
end
private.set = set
-function private.escape (str) return gsub(str,"(.)", escapes) end
-function private.replace(str) return utfgsub(str,"(.)", low ) end
-function private.revert (str) return utfgsub(str,"(.)", high ) end
+-- function private.escape (str) return gsub(str,"(.)", escapes) end
+-- function private.replace(str) return utfgsub(str,"(.)", low ) end
+-- function private.revert (str) return utfgsub(str,"(.)", high ) end
+
+private.escape = utf.remapper(escapes)
+private.replace = utf.remapper(low)
+private.revert = utf.remapper(high)
for ch in gmatch(special,".") do set(ch) end
@@ -236,111 +258,119 @@ not collecting tokens is not only faster but also saves garbage collecting.
-- I might use the combined loop at some point for the filter
-- some day.
---~ function utffilters.collapse(str) -- not really tested (we could preallocate a table)
---~ if str and str ~= "" then
---~ local nstr = #str
---~ if nstr > 1 then
---~ if initialize then -- saves a call
---~ initialize()
---~ end
---~ local tokens, t, first, done, n = { }, 0, false, false, 0
---~ for second in utfcharacters(str) do
---~ local dec = decomposed[second]
---~ if dec then
---~ if not done then
---~ if n > 0 then
---~ for s in utfcharacters(str) do
---~ if n == 1 then
---~ break
---~ else
---~ t = t + 1
---~ tokens[t] = s
---~ n = n - 1
---~ end
---~ end
---~ end
---~ done = true
---~ elseif first then
---~ t = t + 1
---~ tokens[t] = first
---~ end
---~ t = t + 1
---~ tokens[t] = dec
---~ first = false
---~ elseif done then
---~ local crs = high[second]
---~ if crs then
---~ if first then
---~ t = t + 1
---~ tokens[t] = first
---~ end
---~ first = crs
---~ else
---~ local cgf = graphemes[first]
---~ if cgf and cgf[second] then
---~ first = cgf[second]
---~ elseif first then
---~ t = t + 1
---~ tokens[t] = first
---~ first = second
---~ else
---~ first = second
---~ end
---~ end
---~ else
---~ local crs = high[second]
---~ if crs then
---~ for s in utfcharacters(str) do
---~ if n == 1 then
---~ break
---~ else
---~ t = t + 1
---~ tokens[t] = s
---~ n = n - 1
---~ end
---~ end
---~ if first then
---~ t = t + 1
---~ tokens[t] = first
---~ end
---~ first = crs
---~ done = true
---~ else
---~ local cgf = graphemes[first]
---~ if cgf and cgf[second] then
---~ for s in utfcharacters(str) do
---~ if n == 1 then
---~ break
---~ else
---~ t = t + 1
---~ tokens[t] = s
---~ n = n - 1
---~ end
---~ end
---~ first = cgf[second]
---~ done = true
---~ else
---~ first = second
---~ n = n + 1
---~ end
---~ end
---~ end
---~ end
---~ if done then
---~ if first then
---~ t = t + 1
---~ tokens[t] = first
---~ end
---~ return concat(tokens) -- seldom called
---~ end
---~ elseif nstr > 0 then
---~ return high[str] or str
---~ end
---~ end
---~ return str
---~ end
-
-function utffilters.collapse(str) -- not really tested (we could preallocate a table)
+-- function utffilters.collapse(str) -- not really tested (we could preallocate a table)
+-- if str and str ~= "" then
+-- local nstr = #str
+-- if nstr > 1 then
+-- if initialize then -- saves a call
+-- initialize()
+-- end
+-- local tokens, t, first, done, n = { }, 0, false, false, 0
+-- for second in utfcharacters(str) do
+-- local dec = decomposed[second]
+-- if dec then
+-- if not done then
+-- if n > 0 then
+-- for s in utfcharacters(str) do
+-- if n == 1 then
+-- break
+-- else
+-- t = t + 1
+-- tokens[t] = s
+-- n = n - 1
+-- end
+-- end
+-- end
+-- done = true
+-- elseif first then
+-- t = t + 1
+-- tokens[t] = first
+-- end
+-- t = t + 1
+-- tokens[t] = dec
+-- first = false
+-- elseif done then
+-- local crs = high[second]
+-- if crs then
+-- if first then
+-- t = t + 1
+-- tokens[t] = first
+-- end
+-- first = crs
+-- else
+-- local cgf = graphemes[first]
+-- if cgf and cgf[second] then
+-- first = cgf[second]
+-- elseif first then
+-- t = t + 1
+-- tokens[t] = first
+-- first = second
+-- else
+-- first = second
+-- end
+-- end
+-- else
+-- local crs = high[second]
+-- if crs then
+-- for s in utfcharacters(str) do
+-- if n == 1 then
+-- break
+-- else
+-- t = t + 1
+-- tokens[t] = s
+-- n = n - 1
+-- end
+-- end
+-- if first then
+-- t = t + 1
+-- tokens[t] = first
+-- end
+-- first = crs
+-- done = true
+-- else
+-- local cgf = graphemes[first]
+-- if cgf and cgf[second] then
+-- for s in utfcharacters(str) do
+-- if n == 1 then
+-- break
+-- else
+-- t = t + 1
+-- tokens[t] = s
+-- n = n - 1
+-- end
+-- end
+-- first = cgf[second]
+-- done = true
+-- else
+-- first = second
+-- n = n + 1
+-- end
+-- end
+-- end
+-- end
+-- if done then
+-- if first then
+-- t = t + 1
+-- tokens[t] = first
+-- end
+-- return concat(tokens) -- seldom called
+-- end
+-- elseif nstr > 0 then
+-- return high[str] or str
+-- end
+-- end
+-- return str
+-- end
+
+local skippable = table.tohash { "mkiv", "mkvi" }
+local filesuffix = file.suffix
+
+-- we could reuse tokens but it's seldom populated anyway
+
+function utffilters.collapse(str,filename) -- not really tested (we could preallocate a table)
+ if skippable[filesuffix(filename)] then
+ return str
+ end
if str and str ~= "" then
local nstr = #str
if nstr > 1 then
@@ -481,6 +511,14 @@ if sequencers then
sequencers.enableaction(textfileactions,"characters.filters.utf.decompose")
end
+ directives.register("filters.utf.collapse", function(v)
+ sequencers[v and "enableaction" or "disableaction"](textfileactions,"characters.filters.utf.collapse")
+ end)
+
+ directives.register("filters.utf.decompose", function(v)
+ sequencers[v and "enableaction" or "disableaction"](textfileactions,"characters.filters.utf.decompose")
+ end)
+
end
--[[ldx--
diff --git a/Master/texmf-dist/tex/context/base/chem-ini.lua b/Master/texmf-dist/tex/context/base/chem-ini.lua
index 4d47982a220..10db1a1e44e 100644
--- a/Master/texmf-dist/tex/context/base/chem-ini.lua
+++ b/Master/texmf-dist/tex/context/base/chem-ini.lua
@@ -7,73 +7,37 @@ if not modules then modules = { } end modules ['chem-ini'] = {
}
local format = string.format
-local lpegmatch = lpeg.match
-
-local P, R, V, Cc, Cs = lpeg.P, lpeg.R, lpeg.V, lpeg.Cc, lpeg.Cs
+local lpegmatch, patterns = lpeg.match, lpeg.patterns
local trace_molecules = false trackers.register("chemistry.molecules", function(v) trace_molecules = v end)
local report_chemistry = logs.reporter("chemistry")
-local context = context
+local context = context
+local cpatterns = patterns.context
-chemicals = chemicals or { }
-local chemicals = chemicals
+chemistry = chemistry or { }
+local chemistry = chemistry
--[[
-The next code is an adaptation of code from Wolfgang Schuster
-as posted on the mailing list. This version supports nested
-braces and unbraced integers as scripts. We could consider
-spaces as terminals for them but first let collect a bunch
-of input then.
+The next code started out as adaptation of code from Wolfgang Schuster as
+posted on the mailing list. The current version supports nested braces and
+unbraced integers as scripts.
]]--
--- some lpeg, maybe i'll make an syst-lpg module
-
-local lowercase = R("az")
-local uppercase = R("AZ")
-local backslash = P("\\")
-local csname = backslash * P(1) * (1-backslash)^0
-local plus = P("+") / "\\textplus "
-local minus = P("-") / "\\textminus "
-local digit = R("09")
-local sign = plus + minus
-local cardinal = digit^1
-local integer = sign^0 * cardinal
-
-local leftbrace = P("{")
-local rightbrace = P("}")
-local nobrace = 1 - (leftbrace + rightbrace)
-local nested = P { leftbrace * (csname + sign + nobrace + V(1))^0 * rightbrace }
-local any = P(1)
-
-local subscript = P("_")
-local superscript = P("^")
-local somescript = subscript + superscript
-
-local content = Cs(csname + nested + sign + any)
-
--- could be made more efficient
-
-local lowhigh = Cc("\\lohi{%s}{%s}") * subscript * content * superscript * content / format
-local highlow = Cc("\\hilo{%s}{%s}") * superscript * content * subscript * content / format
-local low = Cc("\\low{%s}") * subscript * content / format
-local high = Cc("\\high{%s}") * superscript * content / format
-local justtext = (1 - somescript)^1
-local parser = Cs((csname + lowhigh + highlow + low + high + sign + any)^0)
-
-chemicals.moleculeparser = parser -- can be used to avoid functioncall
+local moleculeparser = cpatterns.scripted
+chemistry.moleculeparser = moleculeparser
-function chemicals.molecule(str)
- return lpegmatch(parser,str)
+function chemistry.molecule(str)
+ return lpegmatch(moleculeparser,str)
end
function commands.molecule(str)
if trace_molecules then
- local rep = lpegmatch(parser,str)
- report_chemistry("molecule %s => %s",str,rep)
+ local rep = lpegmatch(moleculeparser,str)
+ report_chemistry("molecule %a becomes %a",str,rep)
context(rep)
else
- context(lpegmatch(parser,str))
+ context(lpegmatch(moleculeparser,str))
end
end
diff --git a/Master/texmf-dist/tex/context/base/chem-str.lua b/Master/texmf-dist/tex/context/base/chem-str.lua
index fb325ccea9f..311b70b2d1b 100644
--- a/Master/texmf-dist/tex/context/base/chem-str.lua
+++ b/Master/texmf-dist/tex/context/base/chem-str.lua
@@ -1,168 +1,263 @@
if not modules then modules = { } end modules ['chem-str'] = {
version = 1.001,
comment = "companion to chem-str.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ author = "Hans Hagen and Alan Braslau",
copyright = "PRAGMA ADE / ConTeXt Development Team",
license = "see context related readme files"
}
--- This module in incomplete and experimental.
-
--- We can push snippets into an mp instance.
-
-local trace_structure = false trackers.register("chemistry.structure", function(v) trace_structure = v end)
-local trace_textstack = false trackers.register("chemistry.textstack", function(v) trace_textstack = v end)
+-- The original \PPCHTEX\ code was written in pure \TEX\, although later we made
+-- the move from \PICTEX\ to \METAPOST\. The current implementation is a mix between
+-- \TEX\, \LUA\ and \METAPOST. Although the first objective is to get a compatible
+-- but better implementation, later versions might provide more.
+--
+-- Well, the later version has arrived as Alan took it upon him to make the code
+-- deviate even further from the original implementation. The original (early \MKII)
+-- variant operated within the boundaries of \PICTEX\ and as it supported MetaPost as
+-- alternative output. As a consequence it still used a stepwise graphic construction
+-- approach. As we used \TEX\ for parsing, the syntax was more rigid than it is now.
+-- This new variant uses a more mathematical and metapostisch approach. In the process
+-- more rendering variants have been added and alignment has been automated. As a result
+-- the current user interface is slightly different from the old one but hopefully users
+-- will like the added value.
+
+-- directive_strictorder: one might set this to off when associated texts are disordered too
+
+local trace_structure = false trackers .register("chemistry.structure", function(v) trace_structure = v end)
+local trace_metapost = false trackers .register("chemistry.metapost", function(v) trace_metapost = v end)
+local trace_boundingbox = false trackers .register("chemistry.boundingbox", function(v) trace_boundingbox = v end)
+local trace_textstack = false trackers .register("chemistry.textstack", function(v) trace_textstack = v end)
+local directive_strictorder = true directives.register("chemistry.strictorder", function(v) directive_strictorder = v end)
+local directive_strictindex = false directives.register("chemistry.strictindex", function(v) directive_strictindex = v end)
local report_chemistry = logs.reporter("chemistry")
local format, gmatch, match, lower, gsub = string.format, string.gmatch, string.match, string.lower, string.gsub
-local concat, insert, remove = table.concat, table.insert, table.remove
-local processor_tostring = typesetters.processors.tostring
-local lpegmatch = lpeg.match
+local concat, insert, remove, unique, sorted = table.concat, table.insert, table.remove, table.unique, table.sorted
+local processor_tostring = typesetters and typesetters.processors.tostring
local settings_to_array = utilities.parsers.settings_to_array
+local settings_to_array_with_repeat = utilities.parsers.settings_to_array_with_repeat
+local formatters = string.formatters
-local P, R, S, C, Cs, Ct, Cc = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Cs, lpeg.Ct, lpeg.Cc
+local lpegmatch = lpeg.match
+local P, R, S, C, Cs, Ct, Cc, Cmt = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Cs, lpeg.Ct, lpeg.Cc, lpeg.Cmt
-local variables = interfaces.variables
-local context = context
+local variables = interfaces and interfaces.variables
+local context = context
+local formatters = string.formatters
-chemicals = chemicals or { }
-local chemicals = chemicals
+local v_default = variables.default
+local v_small = variables.small
+local v_medium = variables.medium
+local v_big = variables.big
+local v_normal = variables.normal
+local v_fit = variables.fit
+local v_on = variables.on
+local v_none = variables.none
-chemicals.instance = "metafun" -- "ppchtex"
-chemicals.format = "metafun"
-chemicals.structures = 0
+local mpnamedcolor = attributes.colors.mpnamedcolor
+local topoints = number.topoints
+local todimen = string.todimen
-local remapper = {
- ["+"] = "p",
- ["-"] = "m",
-}
+chemistry = chemistry or { }
+local chemistry = chemistry
+
+chemistry.instance = "chemistry"
+chemistry.format = "metafun"
+chemistry.structures = 0
local common_keys = {
- b = "line", eb = "line", db = "line", er = "line", dr = "line", br = "line",
- sb = "line", msb = "line", psb = "line",
- r = "line", pr = "line", mr = "line",
- au = "line", ad = "line",
- rb = "line", mrb = "line", prb = "line",
- rd = "line", mrd = "line", prd = "line",
- sr = "line", msr = "line", psr = "line",
- c = "line", cc = "line", cd = "line", ccd = "line",
- rn = "number", rtn = "number", rbn = "number",
- s = "line", ss = "line", pss = "line", mss = "line",
- mid = "fixed", mids = "fixed", midz = "text",
- z = "text", rz = "text", mrz = "text", prz = "text", crz = "text",
- rt = "text", rtt = "text", rbt = "text", zt = "text", zn = "number",
- mov = "transform", rot = "transform", adj = "transform", dir = "transform", sub = "transform",
+ b = "line",
+ r = "line",
+ sb = "line",
+ sr = "line",
+ rd = "line",
+ rh = "line",
+ rb = "line",
+ rbd = "line",
+ cc = "line",
+ ccd = "line",
+ line = "line",
+ dash = "line",
+ arrow = "line",
+ c = "fixed",
+ cd = "fixed",
+ z = "text",
+ zt = "text",
+ zlt = "text",
+ zrt = "text",
+ rz = "text",
+ rt = "text",
+ lrt = "text",
+ rrt = "text",
+ label = "text",
+ zln = "number",
+ zrn = "number",
+ rn = "number",
+ lrn = "number",
+ rrn = "number",
+ zn = "number",
+ number = "number",
+ mov = "transform",
+ mark = "transform",
+ move = "transform",
+ diff = "transform",
+ off = "transform",
+ adj = "transform",
+ sub = "transform",
}
local front_keys = {
- b = "line", bb= "line",
- sb = "line", msb = "line", psb = "line",
- r = "line", pr = "line", mr = "line",
- z = "text", mrz = "text", prz = "text",
+ bb = "line",
+ eb = "line",
+ rr = "line",
+ lr = "line",
+ lsr = "line",
+ rsr = "line",
+ lrd = "line",
+ rrd = "line",
+ lrh = "line",
+ rrh = "line",
+ lrbd = "line",
+ rrbd = "line",
+ lrb = "line",
+ rrb = "line",
+ lrz = "text",
+ rrz = "text",
+ lsub = "transform",
+ rsub = "transform",
}
local one_keys = {
- sb = "line", db = "line", tb = "line",
- ep = "line", es = "line", ed = "line", et = "line",
- sd = "line", ldd = "line", rdd = "line",
- hb = "line", bb = "line", oe = "line", bd = "line", bw = "line",
- z = "text", cz = "text", zt = "text", zn = "number",
- zbt = "text", zbn = "number", ztt = "text", ztn = "number",
- mov = "transform", sub = "transform", dir = "transform", off = "transform",
+ db = "line",
+ tb = "line",
+ bb = "line",
+ dr = "line",
+ hb = "line",
+ bd = "line",
+ bw = "line",
+ oe = "line",
+ sd = "line",
+ rdb = "line",
+ ldb = "line",
+ ldd = "line",
+ rdd = "line",
+ ep = "line",
+ es = "line",
+ ed = "line",
+ et = "line",
+ cz = "text",
+ rot = "transform",
+ dir = "transform",
+ rm = "transform",
+ mir = "transform",
}
-local front_align = {
- mrz = { { "b","b","b","b","b","b" } },
- prz = { { "t","t","t","t","t","t" } },
+local ring_keys = {
+ db = "line",
+ br = "line",
+ lr = "line",
+ rr = "line",
+ lsr = "line",
+ rsr = "line",
+ lrd = "line",
+ rrd = "line",
+ lrb = "line",
+ rrb = "line",
+ lrh = "line",
+ rrh = "line",
+ lrbd = "line",
+ rrbd = "line",
+ dr = "line",
+ eb = "line",
+ er = "line",
+ ed = "line",
+ au = "line",
+ ad = "line",
+ s = "line",
+ ss = "line",
+ mid = "line",
+ mids = "line",
+ midz = "text",
+ lrz = "text",
+ rrz = "text",
+ crz = "text",
+ rot = "transform",
+ mir = "transform",
+ adj = "transform",
+ lsub = "transform",
+ rsub = "transform",
+ rm = "transform",
}
+-- table.setmetatableindex(front_keys,common_keys)
+-- table.setmetatableindex(one_keys,common_keys)
+-- table.setmetatableindex(ring_keys,common_keys)
+
+-- or (faster but not needed here):
+
+front_keys = table.merged(front_keys,common_keys)
+one_keys = table.merged(one_keys,common_keys)
+ring_keys = table.merged(ring_keys,common_keys)
+
local syntax = {
- one = {
- n = 1, max = 8, keys = one_keys,
- align = {
- z = { { "r", "r_b", "b", "l_b", "l", "l_t", "t", "r_t" } },
---~ z = { { "r", "r", "b", "l", "l", "l", "t", "r" } },
- }
- },
- three = {
- n = 3, max = 3, keys = common_keys,
- align = {
- mrz = { { "r","b","l" }, { "b","l","t" }, { "l","t","r" }, { "t","r","b" } },
- rz = { { "r","l_b","l_t" }, { "b","l_t","r_t" }, { "l","r_t","r_b" }, { "t","r_b","l_b" } },
- prz = { { "r","l","t" }, { "b","t","r" }, { "l","r","b" }, { "t","b","l" } },
- }
- },
- four = {
- n = 4, max = 4, keys = common_keys,
- align = {
- mrz = { { "t","r","b","l" }, { "r","b","l","t" }, { "b","l","t","r" }, { "l","t","r","b" } },
- rz = { { "r_t","r_b","l_b","l_t" }, { "r_b","l_b","l_t","r_t" }, { "l_b","l_t","r_t","r_b" }, { "l_t","r_t","r_b","l_b" } },
- prz = { { "r","b","l","t" }, { "b","l","t","r" }, { "l","t","r","b" }, { "t","r","b","l" } },
- }
- },
- five = {
- n = 5, max = 5, keys = common_keys,
- align = {
- mrz = { { "t","r","b","b","l" }, { "r","b","l","l","t" }, { "b","l","t","r","r" }, { "l","t","r","r","b" } },
- rz = { { "r","r","b","l","t" }, { "b","b","l","t","r" }, { "l","l","t","r","b" }, { "t","t","r","b","l" } },
- prz = { { "r","b","l","t","t" }, { "b","l","t","r","r" }, { "l","t","r","b","b" }, { "t","r","b","l","l" } },
- }
- },
- six = {
- n = 6, max = 6, keys = common_keys,
- align = {
- mrz = { { "t","t","r","b","b","l" }, { "r","b","b","l","t","t" }, { "b","b","l","t","t","r" }, { "l","t","t","r","b","b" } },
- rz = { { "r","r","b","l","l","t" }, { "b","b","l","t","t","r" }, { "l","l","t","r","r","b" }, { "t","t","r","b","b","l" } },
- prz = { { "r","b","l","l","t","r" }, { "b","l","t","t","r","b" }, { "l","t","r","r","b","l" }, { "t","r","b","b","l","t" } },
- }
- },
- eight = {
- n = 8, max = 8, keys = common_keys,
- align = { -- todo
- mrz = { { "t","r","r","b","b","l","l","t" }, { "r","b","b","l","l","t","t","r" }, { "b","l","l","t","t","r","r","b" }, { "l","t","t","r","r","b","b","l" } },
- rz = { { "r","r","b","b","l","l","t","t" }, { "b","b","l","l","t","t","r","r" }, { "l","l","t","t","r","r","b","b" }, { "t","t","r","r","b","b","l","l" } },
- prz = { { "r","b","b","l","l","t","t","r" }, { "b","l","l","t","t","r","r","b" }, { "l","t","t","r","r","b","b","l" }, { "t","r","r","b","b","l","l","t" } },
- }
- },
- five_front = {
- n = -5, max = 5, keys = front_keys, align = front_align,
- },
- six_front = {
- n = -6, max = 6, keys = front_keys, align = front_align,
- },
- pb = { direct = 'chem_pb ;' },
- pe = { direct = 'chem_pe ;' },
- save = { direct = 'chem_save ;' },
- restore = { direct = 'chem_restore ;' },
- space = { direct = 'chem_symbol("\\chemicalsymbol[space]") ;' },
- plus = { direct = 'chem_symbol("\\chemicalsymbol[plus]") ;' },
- minus = { direct = 'chem_symbol("\\chemicalsymbol[minus]") ;' },
- gives = { direct = 'chem_symbol("\\chemicalsymbol[gives]{%s}{%s}") ;', arguments = 2 },
- equilibrium = { direct = 'chem_symbol("\\chemicalsymbol[equilibrium]{%s}{%s}") ;', arguments = 2 },
- mesomeric = { direct = 'chem_symbol("\\chemicalsymbol[mesomeric]{%s}{%s}") ;', arguments = 2 },
- opencomplex = { direct = 'chem_symbol("\\chemicalsymbol[opencomplex]") ;' },
- closecomplex = { direct = 'chem_symbol("\\chemicalsymbol[closecomplex]") ;' },
+ carbon = { max = 4, keys = one_keys, },
+ alkyl = { max = 4, keys = one_keys, },
+ newmanstagger = { max = 6, keys = one_keys, },
+ newmaneclipsed = { max = 6, keys = one_keys, },
+ one = { max = 8, keys = one_keys, },
+ three = { max = 3, keys = ring_keys, },
+ four = { max = 4, keys = ring_keys, },
+ five = { max = 5, keys = ring_keys, },
+ six = { max = 6, keys = ring_keys, },
+ seven = { max = 7, keys = ring_keys, },
+ eight = { max = 8, keys = ring_keys, },
+ nine = { max = 9, keys = ring_keys, },
+ fivefront = { max = 5, keys = front_keys, },
+ sixfront = { max = 6, keys = front_keys, },
+ chair = { max = 6, keys = front_keys, },
+ boat = { max = 6, keys = front_keys, },
+ pb = { direct = 'chem_pb;' },
+ pe = { direct = 'chem_pe;' },
+ save = { direct = 'chem_save;' },
+ restore = { direct = 'chem_restore;' },
+ chem = { direct = formatters['chem_symbol("\\chemicaltext{%s}");'], arguments = 1 },
+ space = { direct = 'chem_symbol("\\chemicalsymbol[space]");' },
+ plus = { direct = 'chem_symbol("\\chemicalsymbol[plus]");' },
+ minus = { direct = 'chem_symbol("\\chemicalsymbol[minus]");' },
+ gives = { direct = formatters['chem_symbol("\\chemicalsymbol[gives]{%s}{%s}");'], arguments = 2 },
+ equilibrium = { direct = formatters['chem_symbol("\\chemicalsymbol[equilibrium]{%s}{%s}");'], arguments = 2 },
+ mesomeric = { direct = formatters['chem_symbol("\\chemicalsymbol[mesomeric]{%s}{%s}");'], arguments = 2 },
+ opencomplex = { direct = 'chem_symbol("\\chemicalsymbol[opencomplex]");' },
+ closecomplex = { direct = 'chem_symbol("\\chemicalsymbol[closecomplex]");' },
+ reset = { direct = 'chem_reset;' },
+ mp = { direct = formatters['%s'], arguments = 1 }, -- backdoor MP code - dangerous!
}
-local definitions = { }
+chemistry.definitions = chemistry.definitions or { }
+local definitions = chemistry.definitions
+
+storage.register("chemistry/definitions",definitions,"chemistry.definitions")
-function chemicals.undefine(name)
+function chemistry.undefine(name)
definitions[lower(name)] = nil
end
-function chemicals.define(name,spec,text)
+function chemistry.define(name,spec,text)
name = lower(name)
local dn = definitions[name]
- if not dn then dn = { } definitions[name] = dn end
+ if not dn then
+ dn = { }
+ definitions[name] = dn
+ end
dn[#dn+1] = {
- spec = settings_to_array(lower(spec)),
- text = settings_to_array(text),
+ spec = settings_to_array_with_repeat(spec,true),
+ text = settings_to_array_with_repeat(text,true),
}
end
-local metacode, variant, keys, bonds, max, txt, textsize, rot, pstack
-local molecule = chemicals.molecule -- or use lpegmatch(chemicals.moleculeparser,...)
+local metacode, variant, keys, max, txt, pstack, sstack, align
+local molecule = chemistry.molecule -- or use lpegmatch(chemistry.moleculeparser,...)
local function fetch(txt)
local st = stack[txt]
@@ -174,305 +269,511 @@ local function fetch(txt)
end
if t then
if trace_textstack then
- report_chemistry("fetching from stack %s slot %s: %s",txt,st.n,t)
+ report_chemistry("fetching from stack %a, slot %a, data %a",txt,st.n,t)
end
st.n = st.n + 1
end
return txt, t
end
-local digit = R("09")/tonumber
+local remapper = {
+ ["+"] = "p",
+ ["-"] = "m",
+}
+
+local dchrs = R("09")
+local sign = S("+-")
+local digit = dchrs / tonumber
+local amount = (sign^-1 * (dchrs^0 * P('.'))^-1 * dchrs^1) / tonumber
+local single = digit
+local range = digit * P("..") * digit
+local set = Ct(digit^2)
local colon = P(":")
local equal = P("=")
local other = 1 - digit - colon - equal
-local remapped = S("+-") / remapper
-local operation = Cs((remapped^0 * other)^1)
-local amount = digit
-local single = digit
+local remapped = sign / remapper
+local operation = Cs(other^1)
local special = (colon * C(other^1)) + Cc("")
-local range = digit * P("..") * digit
-local set = Ct(digit^2)
local text = (equal * C(P(1)^0)) + Cc(false)
local pattern =
- (amount + Cc(1)) *
- operation *
- special * (
+ (amount + Cc(1))
+ * (remapped + Cc(""))
+ * Cs(operation/lower)
+ * Cs(special/lower) * (
range * Cc(false) * text +
Cc(false) * Cc(false) * set * text +
single * Cc(false) * Cc(false) * text +
Cc(false) * Cc(false) * Cc(false) * text
)
---~ local n, operation, index, upto, set, text = lpegmatch(pattern,"RZ1357")
-
---~ print(lpegmatch(pattern,"RZ=x")) 1 RZ false false false x
---~ print(lpegmatch(pattern,"RZ1=x")) 1 RZ 1 false false x
---~ print(lpegmatch(pattern,"RZ1..3=x")) 1 RZ 1 3 false x
---~ print(lpegmatch(pattern,"RZ13=x")) 1 RZ false false table x
-
-local function process(spec,text,n,rulethickness,rulecolor,offset)
- insert(stack,{ spec=spec, text=text, n=n })
+-- local n, operation, index, upto, set, text = lpegmatch(pattern,"RZ1357")
+
+-- print(lpegmatch(pattern,"RZ=x")) -- 1 RZ false false false x
+-- print(lpegmatch(pattern,"RZ1=x")) -- 1 RZ 1 false false x
+-- print(lpegmatch(pattern,"RZ1..3=x")) -- 1 RZ 1 3 false x
+-- print(lpegmatch(pattern,"RZ13=x")) -- 1 RZ false false table x
+
+local f_initialize = 'if unknown context_chem : input mp-chem.mpiv ; fi ;'
+local f_start_structure = formatters['chem_start_structure(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s);']
+local f_set_trace_bounds = formatters['chem_trace_boundingbox := %l ;']
+local f_stop_structure = 'chem_stop_structure;'
+local f_start_component = 'chem_start_component;'
+local f_stop_component = 'chem_stop_component;'
+local f_line = formatters['chem_%s%s(%s,%s,%s,%s,%s);']
+local f_set = formatters['chem_set(%s);']
+local f_number = formatters['chem_%s%s(%s,%s,"\\chemicaltext{%s}");']
+local f_text = f_number
+local f_empty_normal = formatters['chem_%s(%s,%s,"");']
+local f_empty_center = formatters['chem_c%s(%s,%s,"");']
+local f_transform = formatters['chem_%s(%s,%s,%s);']
+
+local prepareMPvariable = commands and commands.prepareMPvariable
+
+local function process(level,spec,text,n,rulethickness,rulecolor,offset,default_variant)
+ insert(stack,{ spec = spec, text = text, n = n })
local txt = #stack
local m = #metacode
+ local saved_rulethickness = rulethickness
+ local saved_rulecolor = rulecolor
+ local saved_align = align
+ local current_variant = default_variant or "six"
for i=1,#spec do
- local s = spec[i]
- local d = definitions[s]
+ local step = spec[i]
+ local s = lower(step)
+ local n = current_variant .. ":" .. s
+ local d = definitions[n]
+ if not d then
+ n = s
+ d = definitions[n]
+ end
if d then
+ if trace_structure then
+ report_chemistry("level %a, step %a, definition %a, snippets %a",level,step,n,#d)
+ end
for i=1,#d do
local di = d[i]
- process(di.spec,di.text,1,rulethickness,rulecolor)
+ current_variant = process(level+1,di.spec,di.text,1,rulethickness,rulecolor,offset,current_variant) -- offset?
end
else
- local rep, operation, special, index, upto, set, text = lpegmatch(pattern,s)
- if operation == "pb" then
+ local factor, osign, operation, special, index, upto, set, text = lpegmatch(pattern,step)
+ if trace_structure then
+ local set = set and concat(set," ") or "-"
+ report_chemistry("level %a, step %a, factor %a, osign %a, operation %a, special %a, index %a, upto %a, set %a, text %a",
+ level,step,factor,osign,operation,special,index,upto,set,text)
+ end
+ if operation == "rulecolor" then
+ local t = text
+ if not t then
+ txt, t = fetch(txt)
+ end
+ if t == v_default or t == v_normal or t == "" then
+ rulecolor = saved_rulecolor
+ elseif t then
+ rulecolor = mpnamedcolor(t)
+ end
+ elseif operation == "rulethickness" then
+ local t = text
+ if not t then
+ txt, t = fetch(txt)
+ end
+ if t == v_default or t == v_normal or t == t_medium or t == "" then
+ rulethickness = saved_rulethickness
+ elseif t == v_small then
+ rulethickness = topoints(1/1.2 * todimen(saved_rulethickness))
+ elseif t == v_big then
+ rulethickness = topoints(1.2 * todimen(saved_rulethickness))
+ elseif t then
+ -- rulethickness = topoints(todimen(t)) -- mp can't handle sp
+ rulethickness = topoints(tonumber(t) * todimen(saved_rulethickness))
+ end
+ elseif operation == "symalign" then
+ local t = text
+ if not t then
+ txt, t = fetch(txt)
+ end
+ if t == v_default or t == v_normal then
+ align = saved_align
+ elseif t and t ~= "" then
+ align = "." .. t
+ end
+ elseif operation == "pb" then
insert(pstack,variant)
m = m + 1 ; metacode[m] = syntax.pb.direct
if keys[special] == "text" and index then
if keys["c"..special] == "text" then -- can be option: auto ...
- m = m + 1 ; metacode[m] = format('chem_c%s(%s,%s,"");',special,bonds,index)
+ m = m + 1 ; metacode[m] = f_empty_center(special,variant,index)
else
- m = m + 1 ; metacode[m] = format('chem_%s(%s,%s,"");',special,bonds,index)
+ m = m + 1 ; metacode[m] = f_empty_normal(special,variant,index)
end
end
+ elseif operation == "pe" then
+ variant = remove(pstack)
+ local ss = syntax[variant]
+ keys, max = ss.keys, ss.max
+ m = m + 1 ; metacode[m] = syntax.pe.direct
+ m = m + 1 ; metacode[m] = f_set(variant)
+ current_variant = variant
elseif operation == "save" then
- insert(pstack,variant)
+ insert(sstack,variant)
m = m + 1 ; metacode[m] = syntax.save.direct
- elseif operation == "pe" or operation == "restore" then
- variant = remove(pstack)
+ elseif operation == "restore" then
+ variant = remove(sstack)
local ss = syntax[variant]
- local prev = bonds or 6
- keys, bonds, max, rot = ss.keys, ss.n, ss.max, 1
- m = m + 1 ; metacode[m] = syntax[operation].direct
- m = m + 1 ; metacode[m] = format("chem_set(%s,%s) ;",prev,bonds)
- elseif operation == "front" then
- if syntax[variant .. "_front"] then
- variant = variant .. "_front"
- local ss = syntax[variant]
- local prev = bonds or 6
- keys, bonds, max, rot = ss.keys, ss.n, ss.max, 1
- m = m + 1 ; metacode[m] = format("chem_set(%s,%s) ;",prev,bonds)
- end
+ keys, max = ss.keys, ss.max
+ m = m + 1 ; metacode[m] = syntax.restore.direct
+ m = m + 1 ; metacode[m] = f_set(variant)
+ current_variant = variant
elseif operation then
local ss = syntax[operation]
+ local what = keys[operation]
+ local ns = 0
+ if set then
+ local sv = syntax[current_variant]
+ local ms = sv and sv.max
+ set = unique(set)
+ ns = #set
+ if directive_strictorder then
+ if what == "line" then
+ set = sorted(set)
+ end
+ if directive_strictindex and ms then
+ for i=ns,1,-1 do
+ local si = set[i]
+ if si > ms then
+ report_chemistry("level %a, operation %a, max nofsteps %a, ignoring %a",level,operation,ms,si)
+ set[i] = nil
+ ns = ns - 1
+ else
+ break
+ end
+ end
+ end
+ else
+ if directive_strictindex and ms then
+ local t, nt = { }, 0
+ for i=1,ns do
+ local si = set[i]
+ if si > ms then
+ report_chemistry("level %a, operation %a, max nofsteps %a, ignoring %a",level,operation,ms,si)
+ set[i] = nil
+ else
+ nt = nt + 1
+ t[nt] = si
+ end
+ end
+ ns = nt
+ set = t
+ end
+ end
+ end
if ss then
local ds = ss.direct
if ds then
local sa = ss.arguments
if sa == 1 then
local one ; txt, one = fetch(txt)
- m = m + 1 ; metacode[m] = format(ds,one or "")
- elseif sa ==2 then
+ m = m + 1 ; metacode[m] = ds(one or "")
+ elseif sa == 2 then
local one ; txt, one = fetch(txt)
local two ; txt, two = fetch(txt)
- m = m + 1 ; metacode[m] = format(ds,one or "",two or "")
+ m = m + 1 ; metacode[m] = ds(one or "",two or "")
else
m = m + 1 ; metacode[m] = ds
end
elseif ss.keys then
- local prev = bonds or 6
- variant, keys, bonds, max, rot = s, ss.keys, ss.n, ss.max, 1
- m = m + 1 ; metacode[m] = format("chem_set(%s,%s) ;",prev,bonds)
+ variant, keys, max = s, ss.keys, ss.max
+ m = m + 1 ; metacode[m] = f_set(variant)
+ current_variant = variant
end
- else
- local what = keys[operation]
- if what == "line" then
- if set then
- for i=1,#set do
- local si = set[i]
- m = m + 1 ; metacode[m] = format("chem_%s(%s,%s,%s,%s,%s);",operation,bonds,si,si,rulethickness,rulecolor)
+ elseif what == "line" then
+ local s = osign
+ if s ~= "" then
+ s = "." .. s
+ end
+ if set then
+ -- condense consecutive numbers in a set to a range
+ local sf, st = set[1]
+ for i=1,ns do
+ if i > 1 and set[i] ~= set[i-1]+1 then
+ m = m + 1 ; metacode[m] = f_line(operation,s,variant,sf,st,rulethickness,rulecolor)
+ sf = set[i]
end
- elseif upto then
- m = m + 1 ; metacode[m] = format("chem_%s(%s,%s,%s,%s,%s);",operation,bonds,index,upto,rulethickness,rulecolor)
- elseif index then
- m = m + 1 ; metacode[m] = format("chem_%s(%s,%s,%s,%s,%s);",operation,bonds,index,index,rulethickness,rulecolor)
- else
- m = m + 1 ; metacode[m] = format("chem_%s(%s,%s,%s,%s,%s);",operation,bonds,1,max,rulethickness,rulecolor)
+ st = set[i]
end
- elseif what == "number" then
- if set then
- for i=1,#set do
- local si = set[i]
- m = m + 1 ; metacode[m] = format('chem_%s(%s,%s,"\\chemicaltext{%s}");',operation,bonds,si,si)
- end
- elseif upto then
- for i=index,upto do
- local si = set[i]
- m = m + 1 ; metacode[m] = format('chem_%s(%s,%s,"\\chemicaltext{%s}");',operation,bonds,si,si)
- end
- elseif index then
- m = m + 1 ; metacode[m] = format('chem_%s(%s,%s,"\\chemicaltext{%s}");',operation,bonds,index,index)
- else
- for i=1,max do
- m = m + 1 ; metacode[m] = format('chem_%s(%s,%s,"\\chemicaltext{%s}");',operation,bonds,i,i)
- end
+ m = m + 1 ; metacode[m] = f_line(operation,s,variant,sf,st,rulethickness,rulecolor)
+ elseif upto then
+ m = m + 1 ; metacode[m] = f_line(operation,s,variant,index,upto,rulethickness,rulecolor)
+ elseif index then
+ m = m + 1 ; metacode[m] = f_line(operation,s,variant,index,index,rulethickness,rulecolor)
+ else
+ m = m + 1 ; metacode[m] = f_line(operation,s,variant,1,max,rulethickness,rulecolor)
+ end
+ elseif what == "number" then
+ if set then
+ for i=1,ns do
+ local si = set[i]
+ m = m + 1 ; metacode[m] = f_number(operation,align,variant,si,si)
end
- elseif what == "text" then
- local align = syntax[variant].align
- align = align and align[operation]
- align = align and align[rot]
- if set then
- for i=1,#set do
- local si = set[i]
- local t = text
- if not t then txt, t = fetch(txt) end
- if t then
- local a = align and align[si]
- if a then a = "." .. a else a = "" end
- t = molecule(processor_tostring(t))
- m = m + 1 ; metacode[m] = format('chem_%s%s(%s,%s,"\\chemicaltext{%s}");',operation,a,bonds,si,t)
- end
- end
- elseif upto then
- for i=index,upto do
- local t = text
- if not t then txt, t = fetch(txt) end
- if t then
- local s = align and align[i]
- if s then s = "." .. s else s = "" end
- t = molecule(processor_tostring(t))
- m = m + 1 ; metacode[m] = format('chem_%s%s(%s,%s,"\\chemicaltext{%s}");',operation,s,bonds,i,t)
- end
- end
- elseif index == 0 then
+ elseif upto then
+ for i=index,upto do
+ local si = set[i]
+ m = m + 1 ; metacode[m] = f_number(operation,align,variant,si,si)
+ end
+ elseif index then
+ m = m + 1 ; metacode[m] = f_number(operation,align,variant,index,index)
+ else
+ for i=1,max do
+ m = m + 1 ; metacode[m] = f_number(operation,align,variant,i,i)
+ end
+ end
+ elseif what == "text" then
+ if set then
+ for i=1,ns do
+ local si = set[i]
local t = text
if not t then txt, t = fetch(txt) end
if t then
t = molecule(processor_tostring(t))
- m = m + 1 ; metacode[m] = format('chem_%s_zero("\\chemicaltext{%s}");',operation,t)
+ m = m + 1 ; metacode[m] = f_text(operation,align,variant,si,t)
end
- elseif index then
+ end
+ elseif upto then
+ for i=index,upto do
local t = text
if not t then txt, t = fetch(txt) end
if t then
- local s = align and align[index]
- if s then s = "." .. s else s = "" end
t = molecule(processor_tostring(t))
- m = m + 1 ; metacode[m] = format('chem_%s%s(%s,%s,"\\chemicaltext{%s}");',operation,s,bonds,index,t)
- end
- else
- for i=1,max do
- local t = text
- if not t then txt, t = fetch(txt) end
- if t then
- local s = align and align[i]
- if s then s = "." .. s else s = "" end
- t = molecule(processor_tostring(t))
- m = m + 1 ; metacode[m] = format('chem_%s%s(%s,%s,"\\chemicaltext{%s}");',operation,s,bonds,i,t)
- end
+ m = m + 1 ; metacode[m] = f_text(operation,align,variant,i,t)
end
end
- elseif what == "transform" then
- if index then
- for r=1,rep do
- m = m + 1 ; metacode[m] = format('chem_%s(%s,%s);',operation,bonds,index)
- end
- if operation == "rot" then
- rot = index
+ elseif index == 0 then
+ local t = text
+ if not t then txt, t = fetch(txt) end
+ if t then
+ t = molecule(processor_tostring(t))
+ m = m + 1 ; metacode[m] = f_text(operation,align,variant,index,t)
+ end
+ elseif index then
+ local t = text
+ if not t then txt, t = fetch(txt) end
+ if t then
+ t = molecule(processor_tostring(t))
+ m = m + 1 ; metacode[m] = f_text(operation,align,variant,index,t)
+ end
+ else
+ for i=1,max do
+ local t = text
+ if not t then txt, t = fetch(txt) end
+ if t then
+ t = molecule(processor_tostring(t))
+ m = m + 1 ; metacode[m] = f_text(operation,align,variant,i,t)
end
end
- elseif what == "fixed" then
- m = m + 1 ; metacode[m] = format("chem_%s(%s,%s,%s);",operation,bonds,rulethickness,rulecolor)
end
+ elseif what == "transform" then
+ if osign == "m" then
+ factor = -factor
+ end
+ if set then
+ for i=1,ns do
+ local si = set[i]
+ m = m + 1 ; metacode[m] = f_transform(operation,variant,si,factor)
+ end
+ elseif upto then
+ for i=index,upto do
+ m = m + 1 ; metacode[m] = f_transform(operation,variant,i,factor)
+ end
+ else
+ m = m + 1 ; metacode[m] = f_transform(operation,variant,index or 1,factor)
+ end
+ elseif what == "fixed" then
+ m = m + 1 ; metacode[m] = f_transform(operation,variant,rulethickness,rulecolor)
+ elseif trace_structure then
+ report_chemistry("level %a, ignoring undefined operation %s",level,operation)
end
end
end
end
remove(stack)
+ return current_variant
end
-- the size related values are somewhat special but we want to be
-- compatible
--
--- maybe we should default to fit
---
-- rulethickness in points
-function chemicals.start(settings)
- chemicals.structures = chemicals.structures + 1
- local textsize, rulethickness, rulecolor = settings.size, settings.rulethickness, settings.rulecolor
- local width, height, scale, offset = settings.width or 0, settings.height or 0, settings.scale or "medium", settings.offset or 0
- local l, r, t, b = settings.left or 0, settings.right or 0, settings.top or 0, settings.bottom or 0
- --
- metacode = { "if unknown context_chem : input mp-chem.mpiv ; fi ;" } -- no format anyway
- --
- if scale == variables.small then
- scale = 500
- elseif scale == variables.medium or scale == 0 then
- scale = 625
- elseif scale == variables.big then
- scale = 750
+local function checked(d,factor,unit,scale)
+ if d == v_none then
+ return 0
+ end
+ local n = tonumber(d)
+ if not n then
+ -- assume dimen
+ elseif n >= 10 or n <= -10 then
+ return factor * unit * n / 1000
else
- scale = tonumber(scale)
- if not scale or scale == 0 then
- scale = 750
- elseif scale < 10 then
- scale = 10
- end
+ return factor * unit * n
+ end
+ local n = todimen(d)
+ if n then
+ return scale * n
+ else
+ return v_fit
end
- if width == variables.fit then
- width = true
+end
+
+local function calculated(height,bottom,top,factor,unit,scale)
+ if height == v_none then
+ -- this always wins
+ height = "0pt"
+ bottom = "0pt"
+ top = "0pt"
+ elseif height == v_fit then
+ height = "true"
+ bottom = bottom == v_fit and "true" or topoints(checked(bottom,factor,unit,scale))
+ top = top == v_fit and "true" or topoints(checked(top, factor,unit,scale))
else
- width = tonumber(width) or 0
- if l == 0 then
- if r == 0 then
- l = (width == 0 and 2000) or width/2
- r = l
- elseif width ~= 0 then
- l = width - r
+ height = checked(height,factor,unit,scale)
+ if bottom == v_fit then
+ if top == v_fit then
+ bottom = height / 2
+ top = bottom
+ else
+ top = checked(top,factor,unit,scale)
+ bottom = height - top
end
- elseif r == 0 and width ~= 0 then
- r = width - l
+ elseif top == v_fit then
+ bottom = checked(bottom,factor,unit,scale)
+ top = height - bottom
+ else
+ bottom = checked(bottom,factor,unit,scale)
+ top = checked(top, factor,unit,scale)
+ local ratio = height / (bottom+top)
+ bottom = bottom * ratio
+ top = top * ratio
end
- width = false
+ top = topoints(top)
+ bottom = topoints(bottom)
+ height = topoints(height)
end
- if height == variables.fit then
- height = true
+ return height, bottom, top
+end
+
+function chemistry.start(settings)
+ chemistry.structures = chemistry.structures + 1
+ local unit = settings.unit or 655360
+ local factor = settings.factor or 3
+ local rulethickness = settings.rulethickness or 65536
+ local rulecolor = settings.rulecolor or ""
+ local axiscolor = settings.framecolor or ""
+ local width = settings.width or v_fit
+ local height = settings.height or v_fit
+ local scale = settings.scale or "normal"
+ local rotation = settings.rotation or 0
+ local offset = settings.offset or 0
+ local left = settings.left or v_fit
+ local right = settings.right or v_fit
+ local top = settings.top or v_fit
+ local bottom = settings.bottom or v_fit
+ --
+ metacode = { }
+ --
+ align = settings.symalign or "auto"
+ if trace_structure then
+ report_chemistry("unit %p, factor %s, symalign %s",unit,factor,align)
+ end
+ if align ~= "" then
+ align = "." .. align
+ end
+ if trace_structure then
+ report_chemistry("%s scale %a, rotation %a, width %s, height %s, left %s, right %s, top %s, bottom %s","asked",scale,rotation,width,height,left,right,top,bottom)
+ end
+ if scale == v_small then
+ scale = 1/1.2
+ elseif scale == v_normal or scale == v_medium or scale == 0 then
+ scale = 1
+ elseif scale == v_big then
+ scale = 1.2
else
- height = tonumber(height) or 0
- if t == 0 then
- if b == 0 then
- t = (height == 0 and 2000) or height/2
- b = t
- elseif height ~= 0 then
- t = height - b
- end
- elseif b == 0 and height ~= 0 then
- b = height - t
+ scale = tonumber(scale)
+ if not scale or scale == 0 then
+ scale = 1
+ elseif scale >= 10 then
+ scale = scale / 1000
+ elseif scale < .01 then
+ scale = .01
end
- height = false
end
- scale = 0.75 * scale/625
--
- metacode[#metacode+1] = format("chem_start_structure(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s) ;",
- chemicals.structures,
- l/25, r/25, t/25, b/25, scale,
- tostring(settings.axis == variables.on), tostring(width), tostring(height), tostring(offset)
+ unit = scale * unit
+ --
+ width, left, right = calculated(width, left, right,factor,unit,scale)
+ height, bottom, top = calculated(height,bottom,top, factor,unit,scale)
+ --
+ rotation = tonumber(rotation) or 0
+ --
+ if trace_structure then
+ report_chemistry("%s scale %a, rotation %a, width %s, height %s, left %s, right %s, top %s, bottom %s","used",scale,rotation,width,height,left,right,top,bottom)
+ end
+ metacode[#metacode+1] = f_start_structure(
+ chemistry.structures,
+ left, right, top, bottom,
+ rotation, topoints(unit), factor, topoints(offset),
+ tostring(settings.axis == v_on), topoints(rulethickness), tostring(axiscolor)
)
+ metacode[#metacode+1] = f_set_trace_bounds(trace_boundingbox) ;
--
- variant, keys, bonds, stack, rot, pstack = "six", { }, 6, { }, 1, { }
+ variant, keys, stack, pstack, sstack = "one", { }, { }, { }, { }
end
-function chemicals.stop()
- metacode[#metacode+1] = "chem_stop_structure ;"
- --
+function chemistry.stop()
+ metacode[#metacode+1] = f_stop_structure
local mpcode = concat(metacode,"\n")
- if trace_structure then
+ if trace_metapost then
report_chemistry("metapost code:\n%s", mpcode)
end
- metapost.graphic(chemicals.instance,chemicals.format,mpcode)
+ if metapost.instance(chemistry.instance) then
+ f_initialize = nil
+ end
+ metapost.graphic {
+ instance = chemistry.instance,
+ format = chemistry.format,
+ data = mpcode,
+ definitions = f_initialize,
+ }
+ t_initialize = ""
metacode = nil
end
-function chemicals.component(spec,text,settings)
+function chemistry.component(spec,text,settings)
rulethickness, rulecolor, offset = settings.rulethickness, settings.rulecolor
- local spec = settings_to_array(lower(spec))
- local text = settings_to_array(text)
- metacode[#metacode+1] = "chem_start_component ;"
- process(spec,text,1,rulethickness,rulecolor)
- metacode[#metacode+1] = "chem_stop_component ;"
+ local spec = settings_to_array_with_repeat(spec,true) -- no lower?
+ local text = settings_to_array_with_repeat(text,true)
+-- inspect(spec)
+ metacode[#metacode+1] = f_start_component
+ process(1,spec,text,1,rulethickness,rulecolor) -- offset?
+ metacode[#metacode+1] = f_stop_component
end
+statistics.register("chemical formulas", function()
+ if chemistry.structures > 0 then
+ return format("%s chemical structure formulas",chemistry.structures) -- no timing needed, part of metapost
+ end
+end)
+
+-- interfaces
+
+commands.undefinechemical = chemistry.undefine
+commands.definechemical = chemistry.define
+commands.startchemical = chemistry.start
+commands.stopchemical = chemistry.stop
+commands.chemicalcomponent = chemistry.component
+
+-- todo: top / bottom
+-- maybe add "=" for double and "≡" for triple?
+
local inline = {
["single"] = "\\chemicalsinglebond", ["-"] = "\\chemicalsinglebond",
["double"] = "\\chemicaldoublebond", ["--"] = "\\chemicaldoublebond",
@@ -480,28 +781,20 @@ local inline = {
["gives"] = "\\chemicalgives", ["->"] = "\\chemicalgives",
["equilibrium"] = "\\chemicalequilibrium", ["<->"] = "\\chemicalequilibrium",
["mesomeric"] = "\\chemicalmesomeric", ["<>"] = "\\chemicalmesomeric",
- ["plus"] = "\\chemicalsplus", ["+"] = "\\chemicalsplus",
- ["minus"] = "\\chemicalsminus",
- ["space"] = "\\chemicalsspace",
+ ["plus"] = "\\chemicalplus", ["+"] = "\\chemicalplus",
+ ["minus"] = "\\chemicalminus",
+ ["space"] = "\\chemicalspace",
}
--- todo: top / bottom
-
-function chemicals.inline(spec)
- local spec = settings_to_array(spec)
+function commands.inlinechemical(spec)
+ local spec = settings_to_array_with_repeat(spec,true)
for i=1,#spec do
local s = spec[i]
local inl = inline[lower(s)]
if inl then
- context(inl)
+ context(inl) -- could be a fast context.sprint
else
context.chemicalinline(molecule(s))
end
end
end
-
-statistics.register("chemical formulas", function()
- if chemicals.structures > 0 then
- return format("%s chemical structure formulas",chemicals.structures) -- no timing needed, part of metapost
- end
-end)
diff --git a/Master/texmf-dist/tex/context/base/chem-str.mkiv b/Master/texmf-dist/tex/context/base/chem-str.mkiv
index 1d60a293efc..c28ea21d92a 100644
--- a/Master/texmf-dist/tex/context/base/chem-str.mkiv
+++ b/Master/texmf-dist/tex/context/base/chem-str.mkiv
@@ -2,7 +2,7 @@
%D [ file=chem-ini,
%D version=2009.05.13,
%D subtitle=Chemistry,
-%D author=Hans Hagen,
+%D author=Hans Hagen \& Alan Braslau,
%D date=\currentdate,
%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
%C
@@ -10,8 +10,10 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-%D This module in incomplete and experimental. Eventually this code
-%D will replace \PPCHTEX.
+%D The original \PPCHTEX\ code was written in pure \TEX\, although later we made
+%D the move from \PICTEX\ to \METAPOST\. The current implementation is a mix between
+%D \TEX\, \LUA\ and \METAPOST. Although the first objective is to get a compatible
+%D but better implementation, later versions might provide more,
\writestatus{loading}{ConTeXt Chemistry Macros / Structure}
@@ -26,26 +28,24 @@
% Here we use chemicalformula instead, so no longer a mix:
%
% \startchemicalformula
-% \chemical{H_2}{top}{bottom}
+% \chemical{2H_2}{top}{bottom}
% \chemical{PLUS}{top}{bottom}
-% \chemical{O}{top}{bottom}
+% \chemical{O_2}{top}{bottom}
% \chemical{GIVES}{top}{bottom}
-% \chemical{H_2O}{top}{bottom}
+% \chemical{2H_2O}{top}{bottom}
% \stopchemicalformula
%
% \startchemicalformula
-% \chemical{H_2}
+% \chemical{2H_2}
% \chemical{PLUS}
-% \chemical{O}
+% \chemical{O_2}
% \chemical{GIVES}
-% \chemical{H_2O}
+% \chemical{2H_2O}
% \stopchemicalformula
%
% The inline variant has only one argument:
%
-% \chemical{H_2,PLUS,O,GIVES,H_2O}
-
-% todo: seven | eight | frontsix | fontfive | carbon | newmans | chair
+% \chemical{2H_2,PLUS,O_2,GIVES,2H_2O}
\unprotect
@@ -58,11 +58,28 @@
\let\setupchemicals\setupchemical
-\unexpanded\def\setupchemicalframed
- {\dosingleempty\dosetupchemicalframed}
+%D We use a dedicated framed macro instead of inheriting one. This is both
+%D a historical and practical reason (like shared keys with different meaning
+%D that could clash, e.g.\ align).
+
+\defineMPinstance
+ [chemistry]
+ [\s!format=metafun,
+ %\s!extensions=\v!yes, % Should we add extensions and initializations?
+ %\s!initializations=\v!yes, % Would this give EmWidth, etc.?
+ ]
+
+\startMPdefinitions{chemistry}
+ input mp-chem.mpiv ;
+\stopMPdefinitions
+
+\defineframed
+ [\??chemicalframed]
+ [\c!align=\v!normal,
+ \c!strut=\v!no]
-\def\dosetupchemicalframed
- {\getparameters[\??chemicalframed]}
+\unexpanded\def\setupchemicalframed
+ {\setupframed[\??chemicalframed]}
\unexpanded\def\definechemical % is global (so we don't use the commandhandler)
{\dosingleargument\chem_define}
@@ -71,7 +88,7 @@
{\startnointerference
\edef\currentdefinedchemical{#1}%
\let\chemical\chem_chemical_nested
- \ctxlua{chemicals.undefine("#1")}%
+ \ctxcommand{undefinechemical("#1")}%
#2% flush
\stopnointerference}
@@ -79,7 +96,7 @@
{\dodoubleempty\chem_chemical_nested_indeed}
\def\chem_chemical_nested_indeed[#1][#2]%
- {\ctxlua{chemicals.define("\currentdefinedchemical",\!!bs#1\!!es,\!!bs\detokenize{#2}\!!es)}}
+ {\ctxcommand{definechemical("\currentdefinedchemical",\!!bs#1\!!es,\!!bs\detokenize{#2}\!!es)}}
% chemical symbols
@@ -90,20 +107,15 @@
{\setvalue{\??chemicalsymbol#1}{#2}}
\unexpanded\def\chemicalsymbol[#1]%
- {\csname\??chemicalsymbol\ifcsname\??chemicalsymbol#1\endcsname\s!unknown\else#1\fi\endcsname}
+ {\csname\??chemicalsymbol\ifcsname\??chemicalsymbol#1\endcsname#1\else\s!unknown\fi\endcsname}
-\definechemicalsymbol[\s!unknown][] % empty
+\definechemicalsymbol[\s!unknown][] % \char"FFFD empty
% size (small medium big)
\edef\chemicaltoplocation{t}
\edef\chemicalbotlocation{b}
-% \unexpanded\def\chemicaltext#1% in ppchtex we had a more clever alignment
-% {\usechemicalstyleandcolor\c!style\c!color
-% \strut
-% #1} % maybe also \setstrut
-
\unexpanded\def\chemicaltext#1%
{\mathematics
{\usechemicalstyleandcolor\c!style\c!color
@@ -132,6 +144,7 @@
\def\chem_start[#1][#2]%
{\ifmmode\vcenter\else\vbox\fi
\bgroup
+ \synchronizestrut{\chemicalparameter\c!strut}%
\dontcomplain
\settrue\indisplaychemical
\forgetall
@@ -147,22 +160,28 @@
\fi\fi
\the\everystructurechemical
\setbox\b_chem_result\hbox\bgroup
- \ctxlua{chemicals.start {
- width = "\chemicalparameter\c!width",
- height = "\chemicalparameter\c!height",
- left = \chemicalparameter\c!left,
- right = \chemicalparameter\c!right,
- top = \chemicalparameter\c!top,
- bottom = \chemicalparameter\c!bottom,
- scale = "\chemicalparameter\c!scale",
- axis = "\chemicalparameter\c!axis",
- offset = "\the\dimexpr.25em\relax",
+ \ctxcommand{startchemical {
+ width = "\chemicalparameter\c!width",
+ height = "\chemicalparameter\c!height",
+ left = "\chemicalparameter\c!left",
+ right = "\chemicalparameter\c!right",
+ top = "\chemicalparameter\c!top",
+ bottom = "\chemicalparameter\c!bottom",
+ scale = "\chemicalparameter\c!scale",
+ rotation = "\chemicalparameter\c!rotation",
+ symalign = "\chemicalparameter\c!symalign",
+ axis = "\chemicalparameter\c!axis",
+ framecolor = "\MPcolor{\chemicalparameter\c!framecolor}",
+ rulethickness = \number\dimexpr\chemicalparameter\c!rulethickness\relax,
+ offset = \number\dimexpr\chemicalparameter\c!offset\relax,
+ unit = \number\dimexpr\chemicalparameter\c!unit\relax,
+ factor = \number\chemicalparameter\c!factor,
} }%
\startnointerference}
\unexpanded\def\stopchemical
{\stopnointerference
- \ctxlua{chemicals.stop()}%
+ \ctxcommand{stopchemical()}%
\egroup
\d_chem_width \wd\b_chem_result
\d_chem_height\ht\b_chem_result
@@ -171,15 +190,18 @@
\doifelsenothing{\chemicalparameter\c!frame}\chem_framed_nop\chem_framed_yes
\egroup}
-\def\chem_framed_yes
- {\localframed%
+\unexpanded\def\chem_framed_yes
+ {\localframedwithsettings
[\??chemicalframed]%
- [\c!frame=\chemicalparameter\c!frame,\c!align=\v!normal,\c!strut=\v!no]{\vbox{\box\b_chem_result\vss}}} % remove depth
+ [\c!frame=\chemicalparameter\c!frame,
+ \c!rulethickness=\chemicalparameter\c!rulethickness,
+ \c!framecolor=\chemicalparameter\c!framecolor]%
+ {\vbox{\box\b_chem_result\vss}}} % remove depth
-\def\chem_framed_nop
- {\localframed%
+\unexpanded\def\chem_framed_nop
+ {\directlocalframed
[\??chemicalframed]%
- [\c!align=\v!normal,\c!strut=\v!no]{\vbox{\box\b_chem_result\vss}}} % remove depth
+ {\vbox{\box\b_chem_result\vss}}} % remove depth
\let\startstructurechemical\startchemical
\let\stopstructurechemical \stopchemical
@@ -200,14 +222,14 @@
\def\strc_chem_indeed_three[#1][#2][#3]%
{\writestatus\m!chemicals{hyperlinked chemicals not yet supported}% todo reference, for the moment ignored
- \ctxlua{chemicals.component(\!!bs#2\!!es, \!!bs\detokenize{#3}\!!es, { % maybe also pass first two args this way
+ \ctxcommand{chemicalcomponent(\!!bs#2\!!es, \!!bs\detokenize{#3}\!!es, { % maybe also pass first two args this way
rulethickness = "\the\dimexpr\chemicalparameter\c!rulethickness\relax", % todo: scaled points
rulecolor = "\MPcolor{\chemicalparameter\c!rulecolor}" % we can precalculate this for speedup
} ) }%
\ignorespaces}
\def\strc_chem_indeed_two[#1][#2]%
- {\ctxlua{chemicals.component(\!!bs#1\!!es,\!!bs\detokenize{#2}\!!es, { % maybe also pass first two args this way
+ {\ctxcommand{chemicalcomponent(\!!bs#1\!!es,\!!bs\detokenize{#2}\!!es, { % maybe also pass first two args this way
rulethickness = "\the\dimexpr\chemicalparameter\c!rulethickness\relax", % todo: scaled points
rulecolor = "\MPcolor{\chemicalparameter\c!rulecolor}" % we can precalculate this for speedup
} ) }%
@@ -242,7 +264,7 @@
\global\setfalse\c_chem_some_text
\to \everystructurechemical
-\def\doaddchemicaltexts
+\def\chem_add_texts
{\setbox2\hbox to \d_chem_width{\strut\hss\hbox{\strut\m_chem_mid_text}\hss}%
\setbox4\hbox to \d_chem_width{\strut\hss\hbox{\strut\m_chem_top_text}\hss}%
\setbox6\hbox to \d_chem_width{\strut\hss\hbox{\strut\m_chem_bot_text}\hss}%
@@ -259,7 +281,7 @@
\appendtoks
\ifconditional\c_chem_some_text
- \doaddchemicaltexts
+ \chem_add_texts
\d_chem_width \wd\b_chem_result
\d_chem_height\ht\b_chem_result
\d_chem_depth \dp\b_chem_result
@@ -289,15 +311,15 @@
\def\chem_arrow_construct#1#2#3%
{\enspace
\mathematics{#1%
- {\strut\hbox \!!spread 2\emwidth{\hss\ctxlua{chemicals.inline(\!!bs#2\!!es)}\hss}}% {\strut\hbox \!!spread 2em{\hss#2\hss}}%
- {\strut\hbox \!!spread 2\emwidth{\hss\ctxlua{chemicals.inline(\!!bs#3\!!es)}\hss}}}% {\strut\hbox \!!spread 2em{\hss#3\hss}}}%
+ {\strut\hbox \s!spread 2\emwidth{\hss\ctxcommand{inlinechemical(\!!bs#3\!!es)}\hss}}% {\strut\hbox \s!spread 2em{\hss#3\hss}}}%
+ {\strut\hbox \s!spread 2\emwidth{\hss\ctxcommand{inlinechemical(\!!bs#2\!!es)}\hss}}}% {\strut\hbox \s!spread 2em{\hss#2\hss}}%
\enspace}
% special macros (probably needs some more work)
\def\chem_top_construct#1#2#3#4%
{\begingroup
- \setbox0\hbox{\tx\setstrut\strut#3}%
+ \setbox0\hbox{\setstrut\strut#3}%
\setbox2\hbox{\setstrut\strut\molecule{#4}}%
\setbox0\hbox{\raise\dimexpr\dp0+\ht2\relax\hbox to \wd2{#1\box0#2}}%
% no: \smashbox0
@@ -306,7 +328,7 @@
\def\chem_bottom_construct#1#2#3#4%
{\begingroup
- \setbox0\hbox{\tx\setstrut\strut#3}%
+ \setbox0\hbox{\setstrut\strut#3}%
\setbox2\hbox{\setstrut\strut#4}%
\setbox0\hbox{\lower\dimexpr\dp2+\ht0\relax\hbox to \wd2{#1\box0#2}}%
% no: \smashbox0
@@ -315,12 +337,12 @@
\unexpanded\def\chemicalleft#1#2%
{\begingroup
- \hbox{\llap{\tx\setstrut\strut#1}\setstrut\strut#2}%
+ \hbox{\llap{\setstrut\strut#1}\setstrut\strut#2}%
\endgroup}%
\unexpanded\def\chemicalright#1#2%
{\begingroup
- \hbox{\setstrut\strut#2\rlap{\tx\setstrut\strut#1}}%
+ \hbox{\setstrut\strut#2\rlap{\setstrut\strut#1}}%
\endgroup}%
\unexpanded\def\chemicaltop {\chem_top_construct \hss \hss }
@@ -343,13 +365,28 @@
% \let\chemicalsmashedleft \chemicalleftcentered
% \let\chemicalsmashedright \chemicalrightcentered
-\unexpanded\def\chemicalalignedtext#1#2#3%
+\unexpanded\def\chemicalalignedtext
+ {\ifmmode
+ \expandafter\chem_aligned_text_math
+ \else
+ \expandafter\chem_aligned_text_text
+ \fi}
+
+\def\chem_aligned_text_text#1#2#3%
{\dontleavehmode
\begingroup
\usechemicalstyleandcolor\c!style\c!color
\hbox to \fontcharwd\font`C{\setstrut\strut#1\molecule{#3}#2}%
\endgroup}
+\def\chem_aligned_text_math#1#2#3%
+ {\dontleavehmode
+ \begingroup
+ \scratchcounter\normalmathstyle
+ \usechemicalstyleandcolor\c!style\c!color
+ \hbox to \fontcharwd\font`C{\setstrut\strut#1\mathematics{\tf\triggermathstyle\scratchcounter\molecule{#3}}#2}%
+ \endgroup}
+
\unexpanded\def\chemicalcentered {\chemicalalignedtext\hss \hss }
\unexpanded\def\chemicalleftcentered {\chemicalalignedtext\relax\hss }
\unexpanded\def\chemicalrightcentered{\chemicalalignedtext\hss \relax}
@@ -373,7 +410,15 @@
\unexpanded\def\chemicaloxidationsix {\chemicaloxidation\relax6}
\unexpanded\def\chemicaloxidationseven{\chemicaloxidation\relax7}
+\unexpanded\def\chemicalbar
+ {\hbox \s!spread .5\emwidth \bgroup
+ \hss
+ \vrule \s!height .9\strutht \s!depth .65\strutdp \s!width .1\exheight
+ \hss
+ \egroup}
+
\appendtoks
+ \let|\chemicalbar % \SR{N|NH}
\let \+\chemicaloxidationplus
\let \-\chemicaloxidationminus
\let \[\chemicalforeveropen
@@ -405,32 +450,53 @@
\let\SR\chemicalsmashedright
\to \everychemical
+% Should these also be defined in lower case, so as to be case independent?
+
\appendtoks
\the\everychemical
\to \everystructurechemical
% inline
+% \unexpanded\def\chemical
+% {\ifinformula
+% \expandafter\displaychemical
+% \else
+% \expandafter\inlinechemical
+% \fi}
+
\unexpanded\def\chemical
{\ifinformula
- \expandafter\displaychemical
+ \expandafter\indisplaychemical
\else
\expandafter\inlinechemical
\fi}
+\unexpanded\def\indisplaychemical
+ {\mathstylecommand\displaychemical\inlinechemical\inlinechemical}
+
+\unexpanded\def\inlinechemical#1%
+ {\dontleavehmode
+ \begingroup
+ \scratchcounter\normalmathstyle
+ \usechemicalstyleandcolor\c!style\c!color
+ \hbox{\mathematics{\tf\triggermathstyle\scratchcounter\ctxcommand{inlinechemical(\!!bs#1\!!es)}}}%
+ \endgroup}
+
\unexpanded\def\displaychemical
{\dotriplegroupempty\chem_display}
-\def\chem_display#1#2#3% todo:
- {\the\everychemical \everychemical\emptytoks
+\def\chem_display#1#2#3%
+ {\the\everychemical
+ \everychemical\emptytoks
\quad
\vcenter\bgroup
\usechemicalstyleandcolor\c!style\c!color
\ifthirdargument
\ifsecondargument
- \halign{&\hss##\hss\cr#2\cr\molecule{#1}\cr#3\cr}%
+ \halign{\aligntab\hss\alignmark\alignmark\hss\cr#2\cr\molecule{#1}\cr#3\cr}%
\else
- \halign{&\hss##\hss\cr\molecule{#1}\cr#2\cr}%
+ \halign{\aligntab\hss\alignmark\alignmark\hss \cr\molecule{#1}\cr#2\cr}%
\fi
\else
\hbox{\molecule{#1}}%
@@ -440,30 +506,30 @@
\unexpanded\def\inlinechemical#1%
{\dontleavehmode
- \hbox{\usechemicalstyleandcolor\c!style\c!color\ctxlua{chemicals.inline(\!!bs#1\!!es)}}}
+ \hbox{\usechemicalstyleandcolor\c!style\c!color\ctxcommand{inlinechemical(\!!bs#1\!!es)}}}
\unexpanded\def\chemicalbondrule
- {\hbox{\vrule\!!height.75ex\!!depth-\dimexpr.75ex-\linewidth\relax\!!width1em\relax}}
+ {\hbox{\vrule\s!height.75\exheight\s!depth-\dimexpr.75\exheight-\linewidth\relax\s!width\emwidth\relax}}
\definechemicalsymbol[i:space] [\enspace\quad\enspace]
\definechemicalsymbol[i:plus] [\enspace\mathematics{+}\enspace]
\definechemicalsymbol[i:minus] [\enspace\mathematics{-}\enspace]
\definechemicalsymbol[i:gives] [\enspace\mathematics{\xrightarrow{}{}}\enspace]
-\definechemicalsymbol[i:equilibrium] [\enspace\mathematics{\xrightpverleftarrow{}{}}\enspace]
+\definechemicalsymbol[i:equilibrium] [\enspace\mathematics{\xrightoverleftarrow{}{}}\enspace]
\definechemicalsymbol[i:mesomeric] [\enspace\mathematics{\xleftrightarrow{}{}}\enspace]
\definechemicalsymbol[i:single] [\chemicalbondrule]
-\definechemicalsymbol[i:tripple] [\hbox{\lower.5ex\chemicalbondrule\hskip-1em\raise.5ex\chemicalbondrule}]
-\definechemicalsymbol[i:double] [\hbox{\chemicalbondrule\hskip-1em\lower.5ex\chemicalbondrule\hskip-1em\raise.5ex\chemicalbondrule}]
+\definechemicalsymbol[i:double] [\hbox{\lower.5ex\chemicalbondrule\hskip-1em\raise.5ex\chemicalbondrule}]
+\definechemicalsymbol[i:triple] [\hbox{\chemicalbondrule\hskip-1em\lower.5ex\chemicalbondrule\hskip-1em\raise.5ex\chemicalbondrule}]
\unexpanded\def\chemicalsinglebond {\chemicalsymbol[i:single]}
-\unexpanded\def\chemicaldoublebond {\chemicalsymbol[i:tripple]}
-\unexpanded\def\chemicaltriplebond {\chemicalsymbol[i:double]}
+\unexpanded\def\chemicaldoublebond {\chemicalsymbol[i:double]}
+\unexpanded\def\chemicaltriplebond {\chemicalsymbol[i:triple]}
\unexpanded\def\chemicalgives {\chemicalsymbol[i:gives]}
\unexpanded\def\chemicalmesomeric {\chemicalsymbol[i:mesomeric]}
\unexpanded\def\chemicalequilibrium{\chemicalsymbol[i:equilibrium]}
-\unexpanded\def\chemicalsplus {\chemicalsymbol[i:plus]}
-\unexpanded\def\chemicalsminus {\chemicalsymbol[i:minus]}
-\unexpanded\def\chemicalsspace {\chemicalsymbol[i:space]}
+\unexpanded\def\chemicalplus {\chemicalsymbol[i:plus]}
+\unexpanded\def\chemicalminus {\chemicalsymbol[i:minus]}
+\unexpanded\def\chemicalspace {\chemicalsymbol[i:space]}
\unexpanded\def\chemicalinline #1{#1}
% display
@@ -491,80 +557,162 @@
\setfalse\c_chem_has_bot}
\unexpanded\def\stopchemicalformula
- {\tabskip1em\relax
+ {\tabskip\emwidth\relax
\nointerlineskip
\ifconditional\c_chem_has_top
\ifconditional\c_chem_has_bot
- \halign{&\hss\usechemicalstyleandcolor\c!style\c!color##\hss\cr\the\t_chem_top\cr\the\t_chem_mid\cr\the\t_chem_bot\cr}%
+ \halign{\aligntab\hss\usechemicalstyleandcolor\c!style\c!color\alignmark\alignmark\hss\cr\the\t_chem_top\cr\the\t_chem_mid\cr\the\t_chem_bot\cr}%
\else
- \halign{&\hss\usechemicalstyleandcolor\c!style\c!color##\hss\cr\the\t_chem_top\cr\the\t_chem_mid\cr}%
+ \halign{\aligntab\hss\usechemicalstyleandcolor\c!style\c!color\alignmark\alignmark\hss\cr\the\t_chem_top\cr\the\t_chem_mid\cr}%
\fi
\else
\ifconditional\c_chem_has_bot
- \halign{&\hss\usechemicalstyleandcolor\c!style\c!color##\hss\cr\the\t_chem_mid\cr\the\t_chem_bot\cr}%
+ \halign{\aligntab\hss\usechemicalstyleandcolor\c!style\c!color\alignmark\alignmark\hss\cr\the\t_chem_mid\cr\the\t_chem_bot\cr}%
\else
- \halign{&\hss\usechemicalstyleandcolor\c!style\c!color##\hss\cr\the\t_chem_mid\cr}%
+ \halign{\aligntab\hss\usechemicalstyleandcolor\c!style\c!color\alignmark\alignmark\hss\cr\the\t_chem_mid\cr}%
\fi
\fi
\egroup}
+% for the moment we have a special set
+
+\definechemicalsymbol[d:space] [\enspace\quad\enspace]
+\definechemicalsymbol[d:plus] [\enspace+\enspace]
+\definechemicalsymbol[d:minus] [\enspace-\enspace]
+\definechemicalsymbol[d:gives] [\rightarrowfill] % \chem_arrow_construct\xrightarrow
+\definechemicalsymbol[d:equilibrium] [\rightoverleftarrowfill] % \chem_arrow_construct\xrightoverleftarrow
+\definechemicalsymbol[d:mesomeric] [\leftarrowfill] % \chem_arrow_construct\xleftrightarrow
+\definechemicalsymbol[d:opencomplex] [\mathematics{\Bigg[}] % not yet ok
+\definechemicalsymbol[d:closecomplex][\mathematics{\Bigg]}] % not yet ok
+
+\definechemicalsymbol[d:SPACE] [{\chemicalsymbol[d:space]}]
+\definechemicalsymbol[d:PLUS] [{\chemicalsymbol[d:plus]}]
+\definechemicalsymbol[d:MINUS] [{\chemicalsymbol[d:minus]}]
+\definechemicalsymbol[d:GIVES] [{\chemicalsymbol[d:gives]}]
+\definechemicalsymbol[d:EQUILIBRIUM] [{\chemicalsymbol[d:equilibrium]}]
+\definechemicalsymbol[d:MESOMERIC] [{\chemicalsymbol[d:mesomeric]}]
+\definechemicalsymbol[d:OPENCOMPLEX] [{\chemicalsymbol[d:opencomplex]}]
+\definechemicalsymbol[d:CLOSECOMPLEX][{\chemicalsymbol[d:closecomplex]}]
+
\unexpanded\def\formulachemical
{\relax\dotriplegroupempty\chem_formula}
\def\chem_formula#1#2#3% we could do hboxes and measure
- {\ifcsname\??chemicalsymbol\detokenize{#1}\endcsname
- \t_chem_mid\expandafter{\the\t_chem_mid\chem_formula_mid{#1}{#2}{#3}}%
+ {\ifthirdargument
+ \doifelsenothing{#2}\chem_formula_top_nop{\chem_formula_top_yes{#2}}%
+ \doifelsenothing{#3}\chem_formula_bot_nop{\chem_formula_bot_yes{#3}}%
+ \else\ifsecondargument
+ \chem_formula_top_nop
+ \doifelsenothing{#2}\chem_formula_bot_nop{\chem_formula_bot_yes{#2}}%
\else
- \ifthirdargument
- \doifelsenothing{#2}\chem_formula_top_nop{\chem_formula_top_yes{#2}}%
- \doifelsenothing{#3}\chem_formula_bot_nop{\chem_formula_bot_yes{#3}}%
- \else\ifsecondargument
- \chem_formula_top_nop
- \doifelsenothing{#2}\chem_formula_bot_nop{\chem_formula_bot_yes{#2}}%
- \else
- \chem_formula_top_nop
- \chem_formula_bot_nop
- \fi\fi
- \t_chem_mid\expandafter{\the\t_chem_mid\molecule{#1}&}%
+ \chem_formula_top_nop
+ \chem_formula_bot_nop
+ \fi\fi
+ \ifcsname\??chemicalsymbol d:\detokenize{#1}\endcsname
+ \t_chem_mid\expandafter{\the\t_chem_mid\chemicalsymbol[d:#1]\aligntab}%
+ \else
+ \t_chem_mid\expandafter{\the\t_chem_mid\molecule{#1}\aligntab}%
\fi}
\def\chem_formula_mid#1%
{\csname\??chemicalsymbol\detokenize{#1}\endcsname}
-\def\chem_formula_top_nop {\t_chem_top\expandafter{\the\t_chem_top&}}
-\def\chem_formula_bot_nop {\t_chem_bot\expandafter{\the\t_chem_bot&}}
-\def\chem_formula_top_yes#1{\t_chem_top\expandafter{\the\t_chem_top\chem_formula_top_indeed{#1}&}\settrue\c_chem_has_top}
-\def\chem_formula_bot_yes#1{\t_chem_bot\expandafter{\the\t_chem_bot\chem_formula_bot_indeed{#1}&}\settrue\c_chem_has_bot}
+\def\chem_formula_top_nop {\t_chem_top\expandafter{\the\t_chem_top\aligntab}}
+\def\chem_formula_bot_nop {\t_chem_bot\expandafter{\the\t_chem_bot\aligntab}}
+\def\chem_formula_top_yes#1{\t_chem_top\expandafter{\the\t_chem_top\chem_formula_top_indeed{#1}\aligntab}\settrue\c_chem_has_top}
+\def\chem_formula_bot_yes#1{\t_chem_bot\expandafter{\the\t_chem_bot\chem_formula_bot_indeed{#1}\aligntab}\settrue\c_chem_has_bot}
\def\chem_formula_top_indeed#1{\strut#1}
\def\chem_formula_bot_indeed#1{\strut#1}
+% Experimental: defaults might change.
+
+\definefloat
+ [\v!chemical]
+ [\v!chemicals]
+
+\setuplabeltext
+ [\v!chemical=]
+
+\setupfloat
+ [\v!chemical]
+ [\c!location=\v!here,
+ \c!inner=\hsize.8\textwidth\dontleavehmode, % brr
+ \c!align={\v!flushleft,\v!lohi}]
+
+\setupcaption
+ [\v!chemical]
+ [\c!location=\v!right,
+ \c!distance=\zeropoint,
+ \c!width=.2\textwidth,
+ \c!align=\v!flushright]
+
+% Can be used as for displayed math: \startplaceformula... to display a chemical formula
+% or a chemical structure:
+%
+% \startplacechemical
+% \startchemicalformula
+% \chemical{2H_2}
+% \chemical{PLUS}
+% \chemical{O_2}
+% \chemical{GIVES}
+% \chemical{2H_2O}
+% \stopchemicalformula
+% \stopplacechemical
+
% gone: state option resolution offset (now frame offset) alternative
\setupchemicalframed
[\c!align=\v!normal,
\c!strut=\v!no,
\c!offset=\v!overlay,
- \c!frame=off]
+ \c!frame=\v!off]
+
+\definecolor % private color
+ [chemicalframecolor]
+ [r=.75,g=.85,b=.95]
\setupchemical
[\c!frame=,
- \c!width=0,
- \c!height=0,
- \c!left=0,
- \c!right=0,
- \c!top=0,
- \c!bottom=0,
+ \c!width=\v!fit, % or unitless number, multiplies scale*EmWidth
+ \c!height=\v!fit, % or unitless number, multiplies scale*EmWidth
+ \c!left=\v!fit, % or unitless number, multiplies scale*EmWidth
+ \c!right=\v!fit, % or unitless number, multiplies scale*EmWidth
+ \c!top=\v!fit, % or unitless number, multiplies scale*EmWidth
+ \c!bottom=\v!fit, % or unitless number, multiplies scale*EmWidth
\c!bodyfont=,
- \c!scale=\v!medium,
+ \c!scale=\v!normal, % small, normal or medium, big, or unitless number (multiplies EmWidth)
\c!size=\v!medium,
- \c!textsize=\v!big,
+ \c!textsize=\v!big, % how is textsize used??
\c!axis=\v!off,
\c!style=\rm,
- \c!location=,
+ \c!rotation=0, % unitless number (interpreted as degrees)
+ \c!symalign=\v!auto,
+ \c!location=, % not yet used (was interaction related in mkii)
+ \c!offset=.25em,
+ \c!unit=\emwidth,
+ \c!factor=3,
\c!color=,
- \c!rulethickness=\linewidth,
- \c!rulecolor=,
- \c!factor=1]
+ \c!strut=\v!yes,
+ \c!framecolor=chemicalframecolor,
+ \c!rulethickness=0.6pt, %1.5\linewidth,
+ \c!rulecolor=]
+
+%D Compatibility:
+
+\definechemical[+R] {\chemical[RR]}
+\definechemical[-R] {\chemical[LR]}
+
+\definechemical[CARBON:CB] {\chemical[NEWMANSTAGGER,C,SB]}
+\definechemical[NEWMANSTAGGER:CB] {\chemical[NEWMANSTAGGER,C,SB]}
+\definechemical[NEWMANECLIPSED:CB]{\chemical[NEWMANECLIPSED,C,SB]}
+\definechemical[CARBON:CB1] {\chemical[CARBON,C,SB,Z234,1.5MOV1,MIR0,C,SB,Z234]}
+
+\definechemical[NEWMAN] {\chemical[]}
+\definechemical[STAGGER] {\chemical[NEWMANSTAGGER]}
+\definechemical[ECLIPSE] {\chemical[NEWMANECLIPSED]}
+\definechemical[ECLIPSED] {\chemical[NEWMANECLIPSED]}
+\definechemical[SIX:FRONT] {\chemical[SIXFRONT]}
+\definechemical[FIVE:FRONT] {\chemical[FIVEFRONT]}
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/cldf-bas.lua b/Master/texmf-dist/tex/context/base/cldf-bas.lua
index 30a9265bce4..298b374f045 100644
--- a/Master/texmf-dist/tex/context/base/cldf-bas.lua
+++ b/Master/texmf-dist/tex/context/base/cldf-bas.lua
@@ -1,4 +1,4 @@
-if not modules then modules = { } end modules ['cldf-ini'] = {
+if not modules then modules = { } end modules ['cldf-bas'] = {
version = 1.001,
comment = "companion to cldf-ini.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
@@ -22,6 +22,8 @@ if not modules then modules = { } end modules ['cldf-ini'] = {
-- flush(ctxcatcodes,"}")
-- end
+-- maybe use context.generics
+
local type = type
local format = string.format
local utfchar = utf.char
@@ -32,13 +34,16 @@ local generics = context.generics
local variables = interfaces.variables
local new_rule = nodes.pool.rule
+local texcount = tex.count
function context.char(k) -- used as escape too, so don't change to utf
if type(k) == "table" then
- -- for i=1,#k do
- -- context(format([[\char%s\relax]],k[i]))
- -- end
- context([[\char%s\relax]],concat(k,[[\relax\char]]))
+ local n = #k
+ if n == 1 then
+ context([[\char%s\relax]],k[1])
+ elseif n > 0 then
+ context([[\char%s\relax]],concat(k,[[\relax\char]]))
+ end
elseif k then
context([[\char%s\relax]],k)
end
@@ -66,6 +71,10 @@ function context.egroup()
context("}")
end
+function context.space()
+ context(" ")
+end
+
function context.hrule(w,h,d,dir)
if type(w) == "table" then
context(new_rule(w.width,w.height,w.depth,w.dir))
@@ -98,22 +107,22 @@ context.vrule = context.hrule
-- not yet used ... but will get variant at the tex end as well
-function context.sethboxregister (n) context("\\setbox %s\\hbox",n) end
-function context.setvboxregister (n) context("\\setbox %s\\vbox",n) end
+function context.sethboxregister(n) context([[\setbox %s\hbox]],n) end
+function context.setvboxregister(n) context([[\setbox %s\vbox]],n) end
function context.starthboxregister(n)
if type(n) == "number" then
- context("\\setbox%s\\hbox\\bgroup",n)
+ context([[\setbox%s\hbox{]],n)
else
- context("\\setbox\\%s\\hbox\\bgroup",n)
+ context([[\setbox\%s\hbox{]],n)
end
end
function context.startvboxregister(n)
if type(n) == "number" then
- context("\\setbox%s\\vbox\\bgroup",n)
+ context([[\setbox%s\vbox{]],n)
else
- context("\\setbox\\%s\\vbox\\bgroup",n)
+ context([[\setbox\%s\vbox{]],n)
end
end
@@ -122,19 +131,36 @@ context.stopvboxregister = context.egroup
function context.flushboxregister(n)
if type(n) == "number" then
- context("\\box%s ",n)
+ context([[\box%s ]],n)
else
- context("\\box\\%s",n)
+ context([[\box\%s]],n)
end
end
function context.beginvbox()
- context("\\vbox\\bgroup") -- we can do \bvbox ... \evbox (less tokens)
+ context([[\vbox{]]) -- we can do \bvbox ... \evbox (less tokens)
end
function context.beginhbox()
- context("\\hbox\\bgroup") -- todo: use fast one
+ context([[\hbox{]]) -- todo: use fast one
end
context.endvbox = context.egroup
context.endhbox = context.egroup
+
+local function allocate(name,what,cmd)
+ local a = format("c_syst_last_allocated_%s",what)
+ local n = texcount[a] + 1
+ if n <= texcount.c_syst_max_allocated_register then
+ texcount[a] = n
+ end
+ context("\\global\\expandafter\\%sdef\\csname %s\\endcsname %s\\relax",cmd or what,name,n)
+ return n
+end
+
+function context.newdimen (name) return allocate(name,"dimen") end
+function context.newskip (name) return allocate(name,"skip") end
+function context.newcount (name) return allocate(name,"count") end
+function context.newmuskip(name) return allocate(name,"muskip") end
+function context.newtoks (name) return allocate(name,"toks") end
+function context.newbox (name) return allocate(name,"box","mathchar") end
diff --git a/Master/texmf-dist/tex/context/base/cldf-bas.mkiv b/Master/texmf-dist/tex/context/base/cldf-bas.mkiv
index f2bd05177a1..f8b5b5d6a3c 100644
--- a/Master/texmf-dist/tex/context/base/cldf-bas.mkiv
+++ b/Master/texmf-dist/tex/context/base/cldf-bas.mkiv
@@ -14,5 +14,6 @@
\writestatus{loading}{ConTeXt Lua Documents / Basics}
\registerctxluafile{cldf-bas}{1.001}
+\registerctxluafile{cldf-prs}{1.001}
\endinput
diff --git a/Master/texmf-dist/tex/context/base/cldf-com.lua b/Master/texmf-dist/tex/context/base/cldf-com.lua
index bacbbeafd6a..fa0dbed3e45 100644
--- a/Master/texmf-dist/tex/context/base/cldf-com.lua
+++ b/Master/texmf-dist/tex/context/base/cldf-com.lua
@@ -11,15 +11,14 @@ local context = context
local generics = context.generics -- needs documentation
local variables = interfaces.variables
-generics.starttabulate = "start" .. variables.tabulate -- todo: e!start
-generics.stoptabulate = "stop" .. variables.tabulate -- todo: e!stop
+generics.starttabulate = "starttabulate" -- "start" .. variables.tabulate -- todo: e!start
+generics.stoptabulate = "stoptabulate" -- "stop" .. variables.tabulate -- todo: e!stop
local NC, NR = context.NC, context.NR
local function tabulaterow(how,...)
- local t = { ... }
- for i=1,#t do
- local ti = tostring(t[i])
+ for i=1,select("#",...) do
+ local ti = tostring(select(i,...))
NC()
if how then
context[how](ti)
diff --git a/Master/texmf-dist/tex/context/base/cldf-ini.lua b/Master/texmf-dist/tex/context/base/cldf-ini.lua
index ed86c29234f..4a7d9f025e4 100644
--- a/Master/texmf-dist/tex/context/base/cldf-ini.lua
+++ b/Master/texmf-dist/tex/context/base/cldf-ini.lua
@@ -20,15 +20,19 @@ if not modules then modules = { } end modules ['cldf-ini'] = {
--
-- tex.print == line with endlinechar appended
+-- todo: context("%bold{total: }%s",total)
+-- todo: context.documentvariable("title")
+
local tex = tex
context = context or { }
local context = context
-local format, find, gmatch, gsub = string.format, string.find, string.gmatch, string.gsub
-local next, type, tostring, tonumber, setmetatable = next, type, tostring, tonumber, setmetatable
+local format, gsub, validstring = string.format, string.gsub, string.valid
+local next, type, tostring, tonumber, setmetatable, unpack, select = next, type, tostring, tonumber, setmetatable, unpack, select
local insert, remove, concat = table.insert, table.remove, table.concat
-local lpegmatch, lpegC, lpegS, lpegP, lpegCc = lpeg.match, lpeg.C, lpeg.S, lpeg.P, lpeg.Cc
+local lpegmatch, lpegC, lpegS, lpegP, lpegCc, patterns = lpeg.match, lpeg.C, lpeg.S, lpeg.P, lpeg.Cc, lpeg.patterns
+local formatters = string.formatters -- using formatteds is slower in this case
local texsprint = tex.sprint
local textprint = tex.tprint
@@ -40,12 +44,14 @@ local isnode = node.is_node -- after 0.65 just node.type
local writenode = node.write
local copynodelist = node.copy_list
-local ctxcatcodes = tex.ctxcatcodes
-local prtcatcodes = tex.prtcatcodes
-local texcatcodes = tex.texcatcodes
-local txtcatcodes = tex.txtcatcodes
-local vrbcatcodes = tex.vrbcatcodes
-local xmlcatcodes = tex.xmlcatcodes
+local catcodenumbers = catcodes.numbers
+
+local ctxcatcodes = catcodenumbers.ctxcatcodes
+local prtcatcodes = catcodenumbers.prtcatcodes
+local texcatcodes = catcodenumbers.texcatcodes
+local txtcatcodes = catcodenumbers.txtcatcodes
+local vrbcatcodes = catcodenumbers.vrbcatcodes
+local xmlcatcodes = catcodenumbers.xmlcatcodes
local flush = texsprint
local flushdirect = texprint
@@ -76,7 +82,7 @@ end
local function _flush_f_(n)
local sn = _stack_f_[n]
if not sn then
- report_cld("data with id %s cannot be found on stack",n)
+ report_cld("data with id %a cannot be found on stack",n)
else
local tn = type(sn)
if tn == "function" then
@@ -100,7 +106,7 @@ end
local function _flush_n_(n)
local sn = _stack_n_[n]
if not sn then
- report_cld("data with id %s cannot be found on stack",n)
+ report_cld("data with id %a cannot be found on stack",n)
elseif texcount["@@trialtypesetting"] == 0 then -- @@trialtypesetting is private!
writenode(sn)
_stack_n_[n] = nil
@@ -154,14 +160,8 @@ context.popcatcodes = popcatcodes
-- -- --
---~ local capture = (
---~ space^0 * newline^2 * lpeg.Cc("") / texprint +
---~ space^0 * newline * space^0 * lpeg.Cc(" ") / texsprint +
---~ content / texsprint
---~ )^0
-
-local newline = lpeg.patterns.newline
-local space = lpeg.patterns.spacer
+local newline = patterns.newline
+local space = patterns.spacer
local spacing = newline * space^0
local content = lpegC((1-spacing)^1) -- texsprint
local emptyline = space^0 * newline^2 -- texprint("")
@@ -344,16 +344,18 @@ end
local methodhandler = resolvers.methodhandler
-function context.viafile(data)
+function context.viafile(data,tag)
if data and data ~= "" then
- local filename = resolvers.savers.byscheme("virtual","viafile",data)
+ local filename = resolvers.savers.byscheme("virtual",validstring(tag,"viafile"),data)
-- context.startregime { "utf" }
context.input(filename)
-- context.stopregime()
end
end
--- -- --
+-- -- -- "{" .. ti .. "}" is somewhat slower in a cld-mkiv run than "{",ti,"}"
+
+local containseol = patterns.containseol
local function writer(parent,command,first,...) -- already optimized before call
local t = { first, ... }
@@ -366,7 +368,7 @@ local function writer(parent,command,first,...) -- already optimized before call
if typ == "string" or typ == "number" then
flush(currentcatcodes,ti)
else -- node.write
- report_context("error: invalid use of direct in '%s', only strings and numbers can be flushed directly, not '%s'",command,typ)
+ report_context("error: invalid use of direct in %a, only strings and numbers can be flushed directly, not %a",command,typ)
end
direct = false
elseif ti == nil then
@@ -375,7 +377,7 @@ local function writer(parent,command,first,...) -- already optimized before call
flush(currentcatcodes,"{}")
elseif typ == "string" then
-- is processelines seen ?
- if processlines and find(ti,"[\n\r]") then -- we can check for ti == "\n"
+ if processlines and lpegmatch(containseol,ti) then
flush(currentcatcodes,"{")
local flushlines = parent.__flushlines or flushlines
flushlines(ti)
@@ -410,7 +412,11 @@ local function writer(parent,command,first,...) -- already optimized before call
done = true
end
end
- flush(currentcatcodes,"]")
+ if done then
+ flush(currentcatcodes,"]")
+ else
+ flush(currentcatcodes,"[]")
+ end
elseif tn == 1 then -- some 20% faster than the next loop
local tj = ti[1]
if type(tj) == "function" then
@@ -440,7 +446,7 @@ local function writer(parent,command,first,...) -- already optimized before call
elseif isnode(ti) then -- slow
flush(currentcatcodes,"{\\cldn{",_store_n_(ti),"}}")
else
- report_context("error: '%s' gets a weird argument '%s'",command,tostring(ti))
+ report_context("error: %a gets a weird argument %a",command,ti)
end
end
end
@@ -448,16 +454,20 @@ end
local generics = { } context.generics = generics
local function indexer(parent,k)
- local c = "\\" .. tostring(generics[k] or k)
- local f = function(first,...)
- if first == nil then
- flush(currentcatcodes,c)
- else
- return writer(parent,c,first,...)
+ if type(k) == "string" then
+ local c = "\\" .. tostring(generics[k] or k)
+ local f = function(first,...)
+ if first == nil then
+ flush(currentcatcodes,c)
+ else
+ return writer(parent,c,first,...)
+ end
end
+ parent[k] = f
+ return f
+ else
+ return context -- catch
end
- parent[k] = f
- return f
end
-- Potential optimization: after the first call we know if there will be an
@@ -518,8 +528,8 @@ local function caller(parent,f,a,...)
local typ = type(f)
if typ == "string" then
if a then
- flush(contentcatcodes,format(f,a,...)) -- was currentcatcodes
- elseif processlines and find(f,"[\n\r]") then
+ flush(contentcatcodes,formatters[f](a,...)) -- was currentcatcodes
+ elseif processlines and lpegmatch(containseol,f) then
local flushlines = parent.__flushlines or flushlines
flushlines(f)
else
@@ -538,10 +548,9 @@ local function caller(parent,f,a,...)
if f then
if a ~= nil then
local flushlines = parent.__flushlines or flushlines
- flushlines(f)
- -- ignore ... maybe some day
+ flushlines(a)
else
- flushdirect(currentcatcodes,"\r")
+ flushdirect(currentcatcodes,"\n") -- no \r, else issues with \startlines ... use context.par() otherwise
end
else
if a ~= nil then
@@ -557,7 +566,7 @@ local function caller(parent,f,a,...)
-- writenode(f)
flush(currentcatcodes,"\\cldn{",_store_n_(f),"}")
else
- report_context("error: 'context' gets a weird argument '%s'",tostring(f))
+ report_context("error: %a gets a weird argument %a","context",f)
end
end
end
@@ -592,13 +601,13 @@ end
function context.fprint(catcodes,fmt,first,...)
if type(catcodes) == "number" then
if first then
- flush(catcodes,format(fmt,first,...))
+ flush(catcodes,formatters[fmt](first,...))
else
flush(catcodes,fmt)
end
else
if fmt then
- flush(format(catodes,fmt,first,...))
+ flush(formatters[catcodes](fmt,first,...))
else
flush(catcodes)
end
@@ -607,7 +616,7 @@ end
function tex.fprint(fmt,first,...) -- goodie
if first then
- flush(currentcatcodes,format(fmt,first,...))
+ flush(currentcatcodes,formatters[fmt](first,...))
else
flush(currentcatcodes,fmt)
end
@@ -625,6 +634,11 @@ local currenttrace = nil
local nofwriters = 0
local nofflushes = 0
+local visualizer = lpeg.replacer {
+ { "\n","<>" },
+ { "\r","<>" },
+}
+
statistics.register("traced context", function()
if nofwriters > 0 or nofflushes > 0 then
return format("writers: %s, flushes: %s, maxstack: %s",nofwriters,nofflushes,_n_f_)
@@ -638,7 +652,7 @@ local tracedwriter = function(parent,...) -- also catcodes ?
local t, n = { "w : - : " }, 1
local traced = function(normal,catcodes,...) -- todo: check for catcodes
local s = concat({...})
- s = gsub(s,"\r","<>") -- unlikely
+ s = lpegmatch(visualizer,s)
n = n + 1
t[n] = s
normal(catcodes,...)
@@ -660,17 +674,17 @@ local traced = function(normal,one,two,...)
normal(one,two,...)
local catcodes = type(one) == "number" and one
local arguments = catcodes and { two, ... } or { one, two, ... }
- local collapsed, c = { format("f : %s : ", catcodes or '-') }, 1
+ local collapsed, c = { formatters["f : %s : "](catcodes or '-') }, 1
for i=1,#arguments do
local argument = arguments[i]
local argtype = type(argument)
c = c + 1
if argtype == "string" then
- collapsed[c] = gsub(argument,"\r","<>")
+ collapsed[c] = lpegmatch(visualizer,argument)
elseif argtype == "number" then
collapsed[c] = argument
else
- collapsed[c] = format("<<%s>>",tostring(argument))
+ collapsed[c] = formatters["<<%S>>"](argument)
end
end
currenttrace(concat(collapsed))
@@ -679,11 +693,11 @@ local traced = function(normal,one,two,...)
normal(one)
local argtype = type(one)
if argtype == "string" then
- currenttrace(format("f : - : %s",gsub(one,"\r","<>")))
+ currenttrace(formatters["f : - : %s"](lpegmatch(visualizer,one)))
elseif argtype == "number" then
- currenttrace(format("f : - : %s",one))
+ currenttrace(formatters["f : - : %s"](one))
else
- currenttrace(format("f : - : <<%s>>",tostring(one)))
+ currenttrace(formatters["f : - : <<%S>>"](one))
end
end
end
@@ -769,19 +783,19 @@ function context.runfile(filename)
local ok = dofile(foundname)
if type(ok) == "function" then
if trace_cld then
- report_context("begin of file '%s' (function call)",foundname)
+ report_context("begin of file %a (function call)",foundname)
end
ok()
if trace_cld then
- report_context("end of file '%s' (function call)",foundname)
+ report_context("end of file %a (function call)",foundname)
end
elseif ok then
- report_context("file '%s' is processed and returns true",foundname)
+ report_context("file %a is processed and returns true",foundname)
else
- report_context("file '%s' is processed and returns nothing",foundname)
+ report_context("file %a is processed and returns nothing",foundname)
end
else
- report_context("unknown file '%s'",filename)
+ report_context("unknown file %a",filename)
end
end
@@ -815,6 +829,44 @@ local function caller(parent,...) -- todo: nodes
end
end
+-- local function indexer(parent,k)
+-- local f = function(a,...)
+-- if not a then
+-- return function()
+-- return context[k]()
+-- end
+-- elseif select("#",...) == 0 then
+-- return function()
+-- return context[k](a)
+-- end
+-- elseif a then
+-- local t = { ... }
+-- return function()
+-- return context[k](a,unpack(t))
+-- end
+-- end
+-- end
+-- parent[k] = f
+-- return f
+-- end
+--
+-- local function caller(parent,a,...) -- todo: nodes
+-- if not a then
+-- return function()
+-- return context()
+-- end
+-- elseif select("#",...) == 0 then
+-- return function()
+-- return context(a)
+-- end
+-- elseif a then
+-- local t = { ... }
+-- return function()
+-- return context(a,unpack(t))
+-- end
+-- end
+-- end
+
setmetatable(delayed, { __index = indexer, __call = caller } )
-- context.nested (todo: lines)
@@ -874,6 +926,60 @@ end
setmetatable(verbatim, { __index = indexer, __call = caller } )
+-- formatted
+
+local formatted = { } context.formatted = formatted
+
+-- local function indexer(parent,k)
+-- local command = context[k]
+-- local f = function(fmt,...)
+-- command(formatters[fmt](...))
+-- end
+-- parent[k] = f
+-- return f
+-- end
+
+local function indexer(parent,k)
+ if type(k) == "string" then
+ local c = "\\" .. tostring(generics[k] or k)
+ local f = function(first,second,...)
+ if first == nil then
+ flush(currentcatcodes,c)
+ elseif second then
+ return writer(parent,c,formatters[first](second,...))
+ else
+ return writer(parent,c,first)
+ end
+ end
+ parent[k] = f
+ return f
+ else
+ return context -- catch
+ end
+end
+
+-- local function caller(parent,...)
+-- context.fprint(...)
+-- end
+
+local function caller(parent,catcodes,fmt,first,...)
+ if type(catcodes) == "number" then
+ if first then
+ flush(catcodes,formatters[fmt](first,...))
+ else
+ flush(catcodes,fmt)
+ end
+ else
+ if fmt then
+ flush(formatters[catcodes](fmt,first,...))
+ else
+ flush(catcodes)
+ end
+ end
+end
+
+setmetatable(formatted, { __index = indexer, __call = caller } )
+
-- metafun (this will move to another file)
local metafun = { } context.metafun = metafun
@@ -887,7 +993,7 @@ local function caller(parent,f,a,...)
local typ = type(f)
if typ == "string" then
if a then
- flush(currentcatcodes,mpdrawing,"{",format(f,a,...),"}")
+ flush(currentcatcodes,mpdrawing,"{",formatters[f](a,...),"}")
else
flush(currentcatcodes,mpdrawing,"{",f,"}")
end
@@ -905,10 +1011,10 @@ local function caller(parent,f,a,...)
if f then
flush(currentcatcodes,mpdrawing,"{^^M}")
else
- report_context("warning: 'metafun' gets argument 'false' which is currently unsupported")
+ report_context("warning: %a gets argument 'false' which is currently unsupported","metafun")
end
else
- report_context("error: 'metafun' gets a weird argument '%s'",tostring(f))
+ report_context("error: %a gets a weird argument %a","metafun",tostring(f))
end
end
end
@@ -925,7 +1031,7 @@ function metafun.stop()
end
function metafun.color(name)
- return format([[\MPcolor{%s}]],name)
+ return formatters[ [[\MPcolor{%s}]] ](name)
end
-- metafun.delayed
@@ -955,18 +1061,6 @@ setmetatable(delayed, { __index = indexer, __call = caller } )
-- helpers:
--- we could have faster calls here
-
-function context.concat(t,separator)
- local done = false
- for i=1,#t do
- local ti = t[i]
- if ti ~= "" then
- if done then
- context(separator)
- end
- context(ti)
- done = true
- end
- end
+function context.concat(...)
+ context(concat(...))
end
diff --git a/Master/texmf-dist/tex/context/base/cldf-ini.mkiv b/Master/texmf-dist/tex/context/base/cldf-ini.mkiv
index 4ad31d81ebe..77948e0583f 100644
--- a/Master/texmf-dist/tex/context/base/cldf-ini.mkiv
+++ b/Master/texmf-dist/tex/context/base/cldf-ini.mkiv
@@ -31,12 +31,14 @@
%D
%D Anyway \unknown\ the following are {\em not} user commands:
-\def\cldf#1{\directlua\zerocount{_cldf_(#1)}} % global (functions)
-\def\cldn#1{\directlua\zerocount{_cldn_(#1)}} % global (nodes)
+% \zerocount removes as it's the default
-\normalprotected\def\cldprocessfile#1{\directlua\zerocount{context.runfile("#1")}}
- \def\cldcontext #1{\directlua\zerocount{context(#1)}}
- \def\cldcommand #1{\directlua\zerocount{context.#1}}
- % \def\cldverbatim #1{\directlua\zerocount{context.verbatim.#1}} % maybe make verbatim global
+\def\cldf#1{\directlua{_cldf_(#1)}} % global (functions)
+\def\cldn#1{\directlua{_cldn_(#1)}} % global (nodes)
+
+\normalprotected\def\cldprocessfile#1{\directlua{context.runfile("#1")}}
+ \def\cldcontext #1{\directlua{context(#1)}}
+ \def\cldcommand #1{\directlua{context.#1}}
+ % \def\cldverbatim #1{\directlua{context.verbatim.#1}} % maybe make verbatim global
\endinput
diff --git a/Master/texmf-dist/tex/context/base/cldf-int.lua b/Master/texmf-dist/tex/context/base/cldf-int.lua
index 55db9fa0b9d..6cbfd666ffb 100644
--- a/Master/texmf-dist/tex/context/base/cldf-int.lua
+++ b/Master/texmf-dist/tex/context/base/cldf-int.lua
@@ -1,4 +1,4 @@
-if not modules then modules = { } end modules ['mult-clm'] = {
+if not modules then modules = { } end modules ['cldf-int'] = {
version = 1.001,
comment = "companion to mult-clm.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
@@ -14,9 +14,12 @@ if not modules then modules = { } end modules ['mult-clm'] = {
local format, insert, remove, concat = string.format, table.insert, table.remove, table.concat
local unpack = unpack or table.unpack
-local contextsprint = context.sprint
-local ctxcatcodes = tex.ctxcatcodes
-local vrbcatcodes = tex.vrbcatcodes
+local catcodenumbers = catcodes.numbers
+
+local ctxcatcodes = catcodenumbers.ctxcatcodes
+local vrbcatcodes = catcodenumbers.vrbcatcodes
+
+local contextsprint = context.sprint
local trace_define = false trackers.register("context.define", function(v) trace_define = v end)
diff --git a/Master/texmf-dist/tex/context/base/cldf-prs.lua b/Master/texmf-dist/tex/context/base/cldf-prs.lua
new file mode 100644
index 00000000000..9fbdba0c88a
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/cldf-prs.lua
@@ -0,0 +1,54 @@
+if not modules then modules = { } end modules ['cldf-bas'] = {
+ version = 1.001,
+ comment = "companion to cldf-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local lpegmatch, patterns = lpeg.match, lpeg.patterns
+local P, R, V, Cc, Cs = lpeg.P, lpeg.R, lpeg.V, lpeg.Cc, lpeg.Cs
+local format = string.format
+
+local cpatterns = patterns.context or { }
+patterns.context = cpatterns
+
+local backslash = P("\\")
+local csname = backslash * P(1) * (1-backslash)^0
+local sign = P("+") / "\\textplus "
+ + P("-") / "\\textminus "
+local leftbrace = P("{")
+local rightbrace = P("}")
+local nested = P { leftbrace * (V(1) + (1-rightbrace))^0 * rightbrace }
+local subscript = P("_")
+local superscript = P("^")
+local utf8char = patterns.utf8char
+local cardinal = patterns.cardinal
+
+-- local scripts = P { "start",
+-- start = V("csname") + V("lowfirst") + V("highfirst"),
+-- csname = csname,
+-- content = Cs(V("csname") + nested + sign^-1 * (cardinal + utf8char)),
+-- lowfirst = subscript * ( Cc("\\lohi{%s}{%s}") * V("content") * superscript + Cc("\\low{%s}" ) ) * V("content") / format,
+-- highfirst = superscript * ( Cc("\\hilo{%s}{%s}") * V("content") * subscript + Cc("\\high{%s}") ) * V("content") / format,
+-- }
+
+local scripts = P { "start",
+ start = V("csname") + V("lowfirst") + V("highfirst"),
+ csname = csname,
+ content = Cs(V("csname") + nested + sign^-1 * (cardinal + utf8char)),
+ lowfirst = (subscript /"") * ( Cc("\\lohi{") * V("content") * Cc("}{") * (superscript/"") + Cc("\\low{" ) ) * V("content") * Cc("}"),
+ highfirst = (superscript/"") * ( Cc("\\hilo{") * V("content") * Cc("}{") * (subscript /"") + Cc("\\high{") ) * V("content") * Cc("}"),
+ }
+
+local scripted = Cs((csname + scripts + utf8char)^0)
+
+cpatterns.scripts = scripts
+cpatterns.csname = csname
+cpatterns.scripted = scripted
+cpatterns.nested = nested
+
+-- inspect(scripted)
+-- print(lpegmatch(scripted,"10^-3_x"))
+-- print(lpegmatch(scripted,"10^-a"))
+
diff --git a/Master/texmf-dist/tex/context/base/cldf-ver.lua b/Master/texmf-dist/tex/context/base/cldf-ver.lua
index 237078157bb..b48fd253ac5 100644
--- a/Master/texmf-dist/tex/context/base/cldf-ver.lua
+++ b/Master/texmf-dist/tex/context/base/cldf-ver.lua
@@ -6,6 +6,10 @@ if not modules then modules = { } end modules ['cldf-ver'] = {
license = "see context related readme files"
}
+-- We have better verbatim: context.verbatim so that needs to be looked
+-- into. We can also directly store in buffers although this variant works
+-- better when used mixed with other code (synchronization issue).
+
local concat, tohandle = table.concat, table.tohandle
local find, splitlines = string.find, string.splitlines
local tostring, type = tostring, type
@@ -41,7 +45,7 @@ table .tocontext = t_tocontext
string .tocontext = s_tocontext
boolean.tocontext = b_tocontext
-function tocontext(first,...)
+function context.tocontext(first,...)
local t = type(first)
if t == "string" then
s_tocontext(first,...)
diff --git a/Master/texmf-dist/tex/context/base/colo-ext.mkiv b/Master/texmf-dist/tex/context/base/colo-ext.mkiv
index af6c3830ecc..8878da48522 100644
--- a/Master/texmf-dist/tex/context/base/colo-ext.mkiv
+++ b/Master/texmf-dist/tex/context/base/colo-ext.mkiv
@@ -29,18 +29,10 @@
%D
%D will negate the colors in box zero.
-% \unexpanded\def\negatecolorbox#1%
-% {\setbox#1\hbox
-% {\startnegative % might change
-% \startcolor[\s!white]\vrule\!!height\ht#1\!!depth\dp#1\!!width\wd#1\stopcolor
-% \hskip-\wd#1%
-% \box#1%
-% \stopnegative}}
-
\unexpanded\def\negatecolorbox#1%
{\setbox#1\hbox
{\startnegative % might change
-% \startcolor[\s!white]\vrule\!!height\ht#1\!!depth\dp#1\!!width\wd#1\stopcolor
+ % \startcolor[\s!white]\vrule\s!height\ht#1\s!depth\dp#1\s!width\wd#1\stopcolor
\blackrule[\c!color=\s!white,\c!height=\ht#1,\c!depth=\dp#1,\c!width=\wd#1]%
\hskip-\wd#1%
\box#1%
diff --git a/Master/texmf-dist/tex/context/base/colo-icc.lua b/Master/texmf-dist/tex/context/base/colo-icc.lua
index 904d42143d4..f7ed561c1bf 100644
--- a/Master/texmf-dist/tex/context/base/colo-icc.lua
+++ b/Master/texmf-dist/tex/context/base/colo-icc.lua
@@ -1,4 +1,4 @@
-if not modules then modules = { } end modules ['colo-ini'] = {
+if not modules then modules = { } end modules ['colo-icc'] = {
version = 1.000,
comment = "companion to colo-ini.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
@@ -8,6 +8,7 @@ if not modules then modules = { } end modules ['colo-ini'] = {
local char, byte, gsub, match, format, strip = string.char, string.byte, string.gsub, string.match, string.format, string.strip
local readstring, readnumber = io.readstring, io.readnumber
+local formatters = string.formatters
local colors = attributes and attributes.colors or { } -- when used in mtxrun
@@ -27,11 +28,13 @@ function colors.iccprofile(filename,verbose)
end
end
if fullname == "" then
- return nil, false, format("profile '%s' cannot be found",filename)
+ report_colors("profile %a cannot be found",filename)
+ return nil, false
end
local f = io.open(fullname,"rb")
if not f then
- return nil, false, format("profile '%s'cannot be loaded",fullname)
+ report_colors("profile %a cannot be loaded",fullname)
+ return nil, false
end
local header = {
size = readnumber(f,4),
@@ -99,7 +102,7 @@ function colors.iccprofile(filename,verbose)
}
else
if verbose then
- report_colors("ignoring tag '%s' or type '%s' in profile '%s'",tag,variant,fullname)
+ report_colors("ignoring tag %a or type %a in profile %a",tag,variant,fullname)
end
tags[tag] = nil
end
@@ -112,9 +115,6 @@ function colors.iccprofile(filename,verbose)
header = header,
tags = tags,
}
- return profile, true, format("profile '%s' loaded",fullname)
+ report_colors("profile %a loaded",fullname)
+ return profile, true
end
-
---~ local profile, error, message = colors.iccprofile("ussheetfedcoated.icc")
---~ print(error,message)
---~ table.print(profile)
diff --git a/Master/texmf-dist/tex/context/base/colo-ini.lua b/Master/texmf-dist/tex/context/base/colo-ini.lua
index 747e2116f08..14873393216 100644
--- a/Master/texmf-dist/tex/context/base/colo-ini.lua
+++ b/Master/texmf-dist/tex/context/base/colo-ini.lua
@@ -11,12 +11,14 @@ local concat, insert, remove = table.concat, table.insert, table.remove
local format, gmatch, gsub, lower, match, find = string.format, string.gmatch, string.gsub, string.lower, string.match, string.find
local P, R, C, Cc = lpeg.P, lpeg.R, lpeg.C, lpeg.Cc
local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
+local formatters = string.formatters
local trace_define = false trackers.register("colors.define",function(v) trace_define = v end)
local report_colors = logs.reporter("colors","defining")
-local attributes, context, commands = attributes, context, commands
+local attributes, backends, storage = attributes, backends, storage
+local context, commands = context, commands
local settings_to_hash_strict = utilities.parsers.settings_to_hash_strict
@@ -37,6 +39,8 @@ local attributes_list = attributes.list
local colorvalues = colors.values
local transparencyvalues = transparencies.values
+local texattribute = tex.attribute
+
colors.sets = colors.sets or { } -- sets are mostly used for
local colorsets = colors.sets -- showing lists of defined
local colorset = { } -- colors
@@ -67,12 +71,12 @@ local function definecolor(name, ca, global)
if ca and ca > 0 then
if global then
if trace_define then
- report_colors("define global color '%s' with attribute: %s",name,ca)
+ report_colors("define global color %a with attribute %a",name,ca)
end
context.colordefagc(name,ca)
else
if trace_define then
- report_colors("define local color '%s' with attribute: %s",name,ca)
+ report_colors("define local color %a with attribute %a",name,ca)
end
context.colordefalc(name,ca)
end
@@ -90,12 +94,12 @@ local function inheritcolor(name, ca, global)
if ca and ca ~= "" then
if global then
if trace_define then
- report_colors("inherit global color '%s' with attribute: %s",name,ca)
+ report_colors("inherit global color %a with attribute %a",name,ca)
end
context.colordeffgc(name,ca) -- some day we will set the macro directly
else
if trace_define then
- report_colors("inherit local color '%s' with attribute: %s",name,ca)
+ report_colors("inherit local color %a with attribute %a",name,ca)
end
context.colordefflc(name,ca)
end
@@ -113,12 +117,12 @@ local function definetransparent(name, ta, global)
if ta and ta > 0 then
if global then
if trace_define then
- report_colors("define global transparency '%s' with attribute: %s",name,ta)
+ report_colors("define global transparency %a with attribute %a",name,ta)
end
context.colordefagt(name,ta)
else
if trace_define then
- report_colors("define local transparency '%s' with attribute: %s",name,ta)
+ report_colors("define local transparency %a with attribute %a",name,ta)
end
context.colordefalt(name,ta)
end
@@ -135,12 +139,12 @@ local function inherittransparent(name, ta, global)
if ta and ta ~= "" then
if global then
if trace_define then
- report_colors("inherit global transparency '%s' with attribute: %s",name,ta)
+ report_colors("inherit global transparency %a with attribute %a",name,ta)
end
context.colordeffgt(name,ta)
else
if trace_define then
- report_colors("inherit local transparency '%s' with attribute: %s",name,ta)
+ report_colors("inherit local transparency %a with attribute %a",name,ta)
end
context.colordefflt(name,ta)
end
@@ -177,8 +181,7 @@ local gray_okay, rgb_okay, cmyk_okay, spot_okay, multichannel_okay, forced = tru
function colors.forcesupport(gray,rgb,cmyk,spot,multichannel) -- pdfx driven
gray_okay, rgb_okay, cmyk_okay, spot_okay, multichannel_okay, forced = gray, rgb, cmyk, spot, multichannel, true
- report_colors("supported models: gray=%s, rgb=%s, cmyk=%s, spot=%s", -- multichannel=%s
- tostring(gray), tostring(rgb), tostring(cmyk), tostring(spot)) -- tostring(multichannel)
+ report_colors("supported models: gray %a, rgb %a, cmyk %a, spot %a",gray,rgb,cmyk,spot) -- multichannel=%l multichannel
end
local function forcedmodel(model) -- delayed till the backend but mp directly
@@ -287,7 +290,8 @@ local right = P(")")
local comma = P(",")
local mixnumber = lpegpatterns.number / tonumber
local mixname = C(P(1-left-right-comma)^1)
-local mixcolor = Cc("M") * mixnumber * left * mixname * (comma * mixname)^-1 * right * P(-1)
+----- mixcolor = Cc("M") * mixnumber * left * mixname * (comma * mixname)^-1 * right * P(-1)
+local mixcolor = Cc("M") * mixnumber * left * mixname * (comma * mixname)^0 * right * P(-1) -- one is also ok
local exclamation = P("!")
local pgfnumber = lpegpatterns.digit^0 / function(s) return tonumber(s)/100 end
@@ -422,14 +426,11 @@ function colors.definemultitonecolor(name,multispec,colorspec,selfspec)
max = max + 1
dd[max] = k
pp[max] = v
- nn[max] = format("%s_%1.3g",k,tonumber(v) or 0) -- 0 can't happen
+ nn[max] = formatters["%s_%1.3g"](k,tonumber(v) or 0) -- 0 can't happen
end
if max > 0 then
nn = concat(nn,'_')
local parent = gsub(lower(nn),"[^%d%a%.]+","_")
---~ if max == 2 and (not colorspec or colorspec == "") then
---~ colors.defineduocolor(parent,pp[1],l_color[dd[1]],pp[2],l_color[dd[2]],true,true)
---~ elseif (not colorspec or colorspec == "") then
if not colorspec or colorspec == "" then
local cc = { } for i=1,max do cc[i] = l_color[dd[i]] end
colors.definemixcolor(parent,pp,cc,global,freeze) -- can become local
@@ -441,11 +442,8 @@ function colors.definemultitonecolor(name,multispec,colorspec,selfspec)
end
local cp = attributes_list[a_color][parent]
dd, pp = concat(dd,','), concat(pp,',')
---~ print(name,multispec,colorspec,selfspec)
---~ print(parent,max,cp)
if cp then
do_registerspotcolor(parent, name, cp, "", max, dd, pp)
---~ do_registermultitonecolor(parent, name, cp, "", max, dd, pp) -- done in previous ... check it
definecolor(name, register_color(name, 'spot', parent, max, dd, pp), true)
local t = settings_to_hash_strict(selfspec)
if t and t.a and t.t then
@@ -472,47 +470,46 @@ local function mpcolor(model,ca,ta,default)
model = forcedmodel(model)
if tv then
if model == 2 then
- return format("transparent(%s,%s,(%s,%s,%s))",tv[1],tv[2],cv[3],cv[4],cv[5])
+ return formatters["transparent(%s,%s,(%s,%s,%s))"](tv[1],tv[2],cv[3],cv[4],cv[5])
elseif model == 3 then
- return format("transparent(%s,%s,(%s,%s,%s))",tv[1],tv[2],cv[3],cv[4],cv[5])
+ return formatters["transparent(%s,%s,(%s,%s,%s))"](tv[1],tv[2],cv[3],cv[4],cv[5])
elseif model == 4 then
- return format("transparent(%s,%s,cmyk(%s,%s,%s,%s))",tv[1],tv[2],cv[6],cv[7],cv[8],cv[9])
+ return formatters["transparent(%s,%s,cmyk(%s,%s,%s,%s))"](tv[1],tv[2],cv[6],cv[7],cv[8],cv[9])
elseif model == 5 then
- return format('transparent(%s,%s,multitonecolor("%s",%s,"%s","%s"))',tv[1],tv[2],cv[10],cv[11],cv[12],cv[13])
- else
- return format("transparent(%s,%s,(%s,%s,%s))",tv[1],tv[2],cv[3],cv[4],cv[5])
--- this will become (see ** in meta-ini.mkiv)
---
--- return format("transparent(%s,%s,(%s))",tv[1],tv[2],cv[2])
+ return formatters['transparent(%s,%s,multitonecolor("%s",%s,"%s","%s"))'](tv[1],tv[2],cv[10],cv[11],cv[12],cv[13])
+ else -- see ** in meta-ini.mkiv: return formatters["transparent(%s,%s,(%s))"](tv[1],tv[2],cv[2])
+ return formatters["transparent(%s,%s,(%s,%s,%s))"](tv[1],tv[2],cv[3],cv[4],cv[5])
end
else
if model == 2 then
- return format("(%s,%s,%s)",cv[3],cv[4],cv[5])
+ return formatters["(%s,%s,%s)"](cv[3],cv[4],cv[5])
elseif model == 3 then
- return format("(%s,%s,%s)",cv[3],cv[4],cv[5])
+ return formatters["(%s,%s,%s)"](cv[3],cv[4],cv[5])
elseif model == 4 then
- return format("cmyk(%s,%s,%s,%s)",cv[6],cv[7],cv[8],cv[9])
+ return formatters["cmyk(%s,%s,%s,%s)"](cv[6],cv[7],cv[8],cv[9])
elseif model == 5 then
- return format('multitonecolor("%s",%s,"%s","%s")',cv[10],cv[11],cv[12],cv[13])
- else
- return format("(%s,%s,%s)",cv[3],cv[4],cv[5])
--- this will become (see ** in meta-ini.mkiv)
---
--- return format("%s",(cv[2]))
+ return formatters['multitonecolor("%s",%s,"%s","%s")'](cv[10],cv[11],cv[12],cv[13])
+ else -- see ** in meta-ini.mkiv: return formatters["%s"]((cv[2]))
+ return formatters["(%s,%s,%s)"](cv[3],cv[4],cv[5])
end
end
else
default = default or 0 -- rgb !
- return format("(%s,%s,%s)",default,default,default)
+ return formatters["(%s,%s,%s)"](default,default,default)
end
end
+local function mpnamedcolor(name)
+ return mpcolor(texattribute[a_colorspace],l_color[name] or l_color.black)
+end
+
local function mpoptions(model,ca,ta,default) -- will move to mlib-col
- return format("withcolor %s",mpcolor(model,ca,ta,default))
+ return formatters["withcolor %s"](mpcolor(model,ca,ta,default))
end
-colors.mpcolor = mpcolor
-colors.mpoptions = mpoptions
+colors.mpcolor = mpcolor
+colors.mpnamedcolor = mpnamedcolor
+colors.mpoptions = mpoptions
function colors.formatcolor(ca,separator)
local cv = colorvalues[ca]
@@ -666,83 +663,51 @@ function colors.defineintermediatecolor(name,fraction,c_one,c_two,a_one,a_two,sp
end
end
---~ local function f(one,two,i,fraction_one,fraction_two)
---~ local otf = fraction_one * one[i] + fraction_two * two[i]
---~ if otf > 1 then
---~ otf = 1
---~ end
---~ return otf
---~ end
-
---~ function colors.defineduocolor(name,fraction_one,c_one,fraction_two,c_two,global,freeze)
---~ local one, two = colorvalues[c_one], colorvalues[c_two]
---~ if one and two then
---~ fraction_one = tonumber(fraction_one) or 1
---~ fraction_two = tonumber(fraction_two) or 1
---~ local csone, cstwo = one[1], two[1]
---~ local ca
---~ if csone == 2 then
---~ ca = register_color(name,'gray',f(one,two,2,fraction_one,fraction_two))
---~ elseif csone == 3 then
---~ ca = register_color(name,'rgb', f(one,two,3,fraction_one,fraction_two),
---~ f(one,two,4,fraction_one,fraction_two),
---~ f(one,two,5,fraction_one,fraction_two))
---~ elseif csone == 4 then
---~ ca = register_color(name,'cmyk',f(one,two,6,fraction_one,fraction_two),
---~ f(one,two,7,fraction_one,fraction_two),
---~ f(one,two,8,fraction_one,fraction_two),
---~ f(one,two,9,fraction_one,fraction_two))
---~ else
---~ ca = register_color(name,'gray',f(one,two,2,fraction_one,fraction_two))
---~ end
---~ definecolor(name,ca,global,freeze)
---~ end
---~ end
-
- local function f(i,colors,fraction)
- local otf = 0
- for c=1,#colors do
- otf = otf + (tonumber(fraction[c]) or 1) * colors[c][i]
- end
- if otf > 1 then
- otf = 1
- end
- return otf
+local function f(i,colors,fraction)
+ local otf = 0
+ for c=1,#colors do
+ otf = otf + (tonumber(fraction[c]) or 1) * colors[c][i]
+ end
+ if otf > 1 then
+ otf = 1
end
+ return otf
+end
- function colors.definemixcolor(name,fractions,cs,global,freeze)
- local values = { }
- for i=1,#cs do -- do fraction in here
- local v = colorvalues[cs[i]]
- if not v then
- return
- end
- values[i] = v
- end
- local csone = values[1][1]
- local ca
- if csone == 2 then
- ca = register_color(name,'gray',f(2,values,fractions))
- elseif csone == 3 then
- ca = register_color(name,'rgb', f(3,values,fractions),
- f(4,values,fractions),
- f(5,values,fractions))
- elseif csone == 4 then
- ca = register_color(name,'cmyk',f(6,values,fractions),
- f(7,values,fractions),
- f(8,values,fractions),
- f(9,values,fractions))
- else
- ca = register_color(name,'gray',f(2,values,fractions))
+function colors.definemixcolor(name,fractions,cs,global,freeze)
+ local values = { }
+ for i=1,#cs do -- do fraction in here
+ local v = colorvalues[cs[i]]
+ if not v then
+ return
end
- definecolor(name,ca,global,freeze)
+ values[i] = v
end
+ local csone = values[1][1]
+ local ca
+ if csone == 2 then
+ ca = register_color(name,'gray',f(2,values,fractions))
+ elseif csone == 3 then
+ ca = register_color(name,'rgb', f(3,values,fractions),
+ f(4,values,fractions),
+ f(5,values,fractions))
+ elseif csone == 4 then
+ ca = register_color(name,'cmyk',f(6,values,fractions),
+ f(7,values,fractions),
+ f(8,values,fractions),
+ f(9,values,fractions))
+ else
+ ca = register_color(name,'gray',f(2,values,fractions))
+ end
+ definecolor(name,ca,global,freeze)
+end
-- for the moment downward compatible
local patterns = { "colo-imp-%s.mkiv", "colo-imp-%s.tex", "colo-%s.mkiv", "colo-%s.tex" }
local function action(name,foundname)
+ -- could be one command
context.startreadingfile()
context.startcolorset { name }
context.input(foundname)
@@ -753,7 +718,7 @@ end
local function failure(name)
-- context.showmessage("colors",5,name)
- report_colors("unknown: library '%s'",name)
+ report_colors("unknown library %a",name)
end
function colors.usecolors(name)
@@ -877,3 +842,22 @@ end
-- context.popcatcodes()
-- end
+-- handy
+
+local models = storage.allocate { "all", "gray", "rgb", "cmyk", "spot" }
+
+colors.models = models -- check for usage elsewhere
+
+function colors.spec(name)
+ local l = attributes_list[a_color]
+ local t = colorvalues[l[name]] or colorvalues[l.black]
+ return {
+ model = models[t[1]] or models[1],
+ s = t[2],
+ r = t[3], g = t[4], b = t[5],
+ c = t[6], m = t[7], y = t[8], k = t[9],
+ }
+end
+
+-- inspect(attributes.colors.spec("red"))
+-- inspect(attributes.colors.spec("red socks"))
diff --git a/Master/texmf-dist/tex/context/base/colo-ini.mkiv b/Master/texmf-dist/tex/context/base/colo-ini.mkiv
index 5721bb513bb..7052bf6c9c9 100644
--- a/Master/texmf-dist/tex/context/base/colo-ini.mkiv
+++ b/Master/texmf-dist/tex/context/base/colo-ini.mkiv
@@ -242,8 +242,8 @@
\setfalse\c_colo_convert_gray
\getvalue{\??colorconversions\directcolorsparameter\c!conversion}% could be a nice \ifcsname
% too often:
- \ifconditional\c_colo_rgb_supported \colo_helpers_show_message\m!colors9\v!rgb \fi
- \ifconditional\c_colo_cmyk_supported\colo_helpers_show_message\m!colors9\v!cmyk\fi
+ \ifconditional\c_colo_rgb_supported \colo_helpers_show_message\m!colors{10}\v!rgb \fi
+ \ifconditional\c_colo_cmyk_supported\colo_helpers_show_message\m!colors{10}\v!cmyk\fi
\colo_helpers_set_current_model
\ifproductionrun
\edef\p_pagecolormodel{\directcolorsparameter\c!pagecolormodel}%
@@ -357,16 +357,26 @@
\normalexpanded{\colo_palets_define[#1][\csname\??colorpaletspecification#2\endcsname]}%
\fi}}
-\def\colo_palets_define_one#1#2% get rid of { } in #2
- {\colo_palets_define_two{#1}[#2]}%
+% \def\colo_palets_define_one#1#2% get rid of { } in #2
+% {\colo_palets_define_two{#1}[#2]}%
+
+\def\colo_palets_define_one#1#2% get rid of { }
+ {\doifassignmentelse{#2} % catch empty entries
+ {\colo_palets_define_two{#1}[#2]}
+ {\colo_palets_define_three{#1}{#2}}}
\def\colo_palets_define_two#1[#2=#3]%
{\edef\m_colo_palets_tmp{\ifx\m_colo_palets_tmp\empty\else\m_colo_palets_tmp,\fi#2}%
\colo_palets_define_set{#1}{#2}{#3}}%
+\def\colo_palets_define_three#1#2%
+ {\ifcsname\??colorpaletspecification#2\endcsname
+ \processcommacommand[\csname\??colorpaletspecification#2\endcsname]{\colo_palets_define_one{#1}}%
+ \fi}
+
\let\paletsize\!!zerocount
-\def\getpaletsize[#1]%
+\unexpanded\def\getpaletsize[#1]% only works for valid k=v definitions
{\getcommacommandsize[\csname\??colorpaletspecification#1\endcsname]%
\edef\paletsize{\number\commalistsize}}
@@ -577,6 +587,34 @@
\letvalue{\??colorsetter-}\empty % used?
\letvalue{\??transparencysetter-}\empty % used?
+% new: expandable (see tbl)
+
+\def\colo_helpers_fast_activate
+ {\ifx\currentcolorprefix\empty
+ \expandafter\colo_helpers_fast_activate_nop
+ \else
+ \expandafter\colo_helpers_fast_activate_yes
+ \fi}
+
+\def\colo_helpers_fast_activate_yes#1%
+ {\ifcsname\??colorsetter\currentcolorprefix#1\endcsname
+ \csname\??colorsetter\currentcolorprefix#1\endcsname
+ \csname\??transparencysetter\currentcolorprefix#1\endcsname
+ \else\ifcsname\??colorsetter#1\endcsname
+ \csname\??colorsetter#1\endcsname
+ \csname\??transparencysetter#1\endcsname
+ \fi\fi}
+
+\def\colo_helpers_fast_activate_nop#1%
+ {\ifcsname\??colorsetter#1\endcsname
+ \csname\??colorsetter#1\endcsname
+ \csname\??transparencysetter#1\endcsname
+ \fi}
+
+\let\dofastcoloractivation\colo_helpers_fast_activate
+
+% so far
+
\def\colo_helpers_activate % two-step is not that much faster but less tracing
{\ifx\currentcolorprefix\empty
\expandafter\colo_helpers_activate_nop
@@ -688,6 +726,25 @@
% test {\mycolord OEPS} test
% test {\mycolorx OEPS} test
% \stoptext
+%
+% Beware: if we say:
+%
+% \definecolor[one][two]
+%
+% only color one is actually defined and two is not seen at the
+% \LUA\ end. This means that this doesn't work:
+%
+% \definecolor[ColorA][red]
+% \definecolor[ColorB][.5(ColorA)]
+% \definecolor[ColorC][.5(ColorB,white)]
+%
+% But this does work:
+%
+% \definecolor[ColorA][1.0(red)]
+% \definecolor[ColorB][0.5(ColorA)]
+% \definecolor[ColorC][0.5(ColorB,white)]
+%
+% because the fractional definition results in a new definition.
\unexpanded\def\defineintermediatecolor
{\dotripleempty\colo_basics_define_intermediate}
@@ -699,7 +756,7 @@
{\ctxcommand{defineintermediatecolor("#1","#2",
\thecolorattribute{#3},\thecolorattribute{#4},
\thetransparencyattribute{#3},\thetransparencyattribute{#4},
- "#5",false,\iffreezecolors true\else false\fi)}% not global
+ "#5",false,\v_colo_freeze_state)}% not global
\unexpanded\setvalue{#1}{\colo_helpers_activate{#1}}}
%D Here is a more efficient helper for pgf:
@@ -802,9 +859,19 @@
\def\defaulttextcolor {black}
\def\s!themaintextcolor{themaintextcolor}
+\unexpanded\def\inheritmaintextcolor
+ {\ifx\maintextcolor\empty\else\colo_helpers_activate\maintextcolor\fi}
+
+\unexpanded\def\onlyinheritmaintextcolor
+ {\ifx\maintextcolor\empty
+ \deactivatecolor
+ \else
+ \colo_helpers_activate\maintextcolor
+ \fi}
+
\appendtoks
\deactivatecolor % public?
- \ifx\maintextcolor\empty\else\colo_helpers_activate\maintextcolor\fi
+ \inheritmaintextcolor
\to \everybeforeoutput
\def\colo_helpers_switch_to_maintextcolor#1%
@@ -961,7 +1028,7 @@
% ignores in attribute handler
%
-% \def\forcecolorhack{\vrule\!!width\zeropoint\!!height\zeropoint\!!depth\zeropoint}
+% \def\forcecolorhack{\vrule\s!width\zeropoint\s!height\zeropoint\s!depth\zeropoint}
% \normal added else fails in metafun manual (leaders do a hard scan)
diff --git a/Master/texmf-dist/tex/context/base/colo-run.lua b/Master/texmf-dist/tex/context/base/colo-run.lua
index 4f1916d5ada..27f7c6b12ea 100644
--- a/Master/texmf-dist/tex/context/base/colo-run.lua
+++ b/Master/texmf-dist/tex/context/base/colo-run.lua
@@ -6,8 +6,10 @@ if not modules then modules = { } end modules ['colo-run'] = {
license = "see context related readme files"
}
--- For historic reasons the core has a couple of tracing
--- features. Nowadays these would end up in modules.
+-- For historic reasons the core has a couple of tracing features. Nowadays
+-- these would end up in modules.
+
+local colors, commands, context, utilities = colors, commands, context, utilities
local colors= attributes.colors
diff --git a/Master/texmf-dist/tex/context/base/colo-run.mkiv b/Master/texmf-dist/tex/context/base/colo-run.mkiv
index c330accf3dd..5084fdd351e 100644
--- a/Master/texmf-dist/tex/context/base/colo-run.mkiv
+++ b/Master/texmf-dist/tex/context/base/colo-run.mkiv
@@ -42,9 +42,9 @@
%D Palets
\unexpanded\gdef\showpalet
- {\dodoubleargument\doshowpalet}
+ {\dodoubleargument\colo_show_palet}
-\gdef\doshowpalet[#1][#2]%
+\gdef\colo_show_palet[#1][#2]%
{\ifcsname\??colorpalet#1\endcsname
\doifinsetelse\v!vertical{#2} \colo_palets_show_vertical \colo_palets_show_horizontal [#1][#2]%
\fi}
@@ -59,8 +59,8 @@
\tabskip\zeropoint
\def\colo_palets_show_palet##1%
{\doifinsetelse\v!number{#2}{##1\hskip.5em}{}&
- \color[##1]{\vrule\!!width3em\!!height\strutht\!!depth\strutdp}%
- \graycolor[##1]{\vrule\!!width3em\!!height\strutht\!!depth\strutdp}&
+ \color[##1]{\vrule\s!width3em\s!height\strutht\s!depth\strutdp}%
+ \graycolor[##1]{\vrule\s!width3em\s!height\strutht\s!depth\strutdp}&
\doifinset\v!value{#2}{\hskip.5em\colorvalue{##1}}\crcr}
\halign
{\hss##&\hss##\hss#\cr
@@ -92,11 +92,11 @@
\colo_palets_process[#1]\colo_palets_show_palet}\cr
\doifinset\v!name{#2}{#1\hskip.5em}%
\def\colo_palets_show_palet##1%
- {&\strut\color[##1]{\vrule\!!width\!!widtha\!!height\strutht\!!depth\zeropoint}}%
+ {&\strut\color[##1]{\vrule\s!width\!!widtha\s!height\strutht\s!depth\zeropoint}}%
\colo_palets_process[#1]\colo_palets_show_palet\crcr
\noalign{\vskip-\strutdepth}%
\def\colo_palets_show_palet##1%
- {&\graycolor[##1]{\vrule\!!width\!!widtha\!!height\zeropoint\!!depth\strutdp}}%
+ {&\graycolor[##1]{\vrule\s!width\!!widtha\s!height\zeropoint\s!depth\strutdp}}%
\colo_palets_process[#1]\colo_palets_show_palet\crcr
\doifinset\v!value{#2}
{\def\colo_palets_show_palet##1%
@@ -137,13 +137,13 @@
\def\colo_palets_compare##1%
{\hbox
{\setbox0\hbox
- {#1[##1]{\vrule\!!width\hsize\!!height3ex}}%
+ {#1[##1]{\vrule\s!width\hsize\s!height3ex}}%
\wd0\zeropoint
\box0
\hbox to \hsize
{\def\colo_palets_compare####1%
{\hbox to \!!widtha
- {\hss#1[####1]{\vrule\!!width.5\!!widtha\!!height2.25ex\!!depth-.75ex}\hss}}%
+ {\hss#1[####1]{\vrule\s!width.5\!!widtha\s!height2.25ex\s!depth-.75ex}\hss}}%
\processcommacommand[\getvalue{\??colorpalet#2}]\colo_palets_compare}}
\endgraf}
\processcommacommand[\getvalue{\??colorpalet#2}]\colo_palets_compare}}
@@ -171,8 +171,8 @@
{\halign
{\hss####\hss\cr
\doifinset\v!number{#2}{\strut##1}\cr
- \color[#1:##1]{\vrule\!!width4em\!!height\strutht\!!depth\zeropoint}\cr
- \graycolor[#1:##1]{\vrule\!!width4em\!!height\zeropoint\!!depth\strutdp}\cr
+ \color[#1:##1]{\vrule\s!width4em\s!height\strutht\s!depth\zeropoint}\cr
+ \graycolor[#1:##1]{\vrule\s!width4em\s!height\zeropoint\s!depth\strutdp}\cr
\doifinset\v!value{#2}{\colorvalue{#1:##1}\strut}\crcr}}}}%
\hbox
{\doifinset\v!name{#2}
@@ -195,8 +195,8 @@
\def\colo_groups_show_group##1%
{\doifcolor{#1:##1}
{\doifinset\v!number{#2}{##1\hskip.5em}&
- \color[#1:##1]{\vrule\!!width2.5em\!!height\strutht\!!depth\strutdp}%
- \graycolor[#1:##1]{\vrule\!!width2.5em\!!height\strutht\!!depth\strutdp}&
+ \color[#1:##1]{\vrule\s!width2.5em\s!height\strutht\s!depth\strutdp}%
+ \graycolor[#1:##1]{\vrule\s!width2.5em\s!height\strutht\s!depth\strutdp}&
\doifinset\v!value{#2}{\hskip.5em\colorvalue{#1:##1}}\crcr}}%
\halign
{\hss##&\hss##\hss#\hss\cr
@@ -228,11 +228,11 @@
\def\colo_groups_compare_step#1#2#3%
{\hbox to \hsize
{\setbox0\hbox
- {#1[#2:#3]{\vrule\!!width\hsize\!!height3ex}}%
+ {#1[#2:#3]{\vrule\s!width\hsize\s!height3ex}}%
\wd0\zeropoint
\box0
\hbox to \hsize
- {\hss\dorecurse\!!counta{#1[#2:\recurselevel]{\vrule\!!width.5\!!widtha\!!height2.25ex\!!depth-.75ex}\hss}}}
+ {\hss\dorecurse\!!counta{#1[#2:\recurselevel]{\vrule\s!width.5\!!widtha\s!height2.25ex\s!depth-.75ex}\hss}}}
\endgraf}
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/cont-log.mkiv b/Master/texmf-dist/tex/context/base/cont-log.mkiv
index 67647920dbc..5d41331434c 100644
--- a/Master/texmf-dist/tex/context/base/cont-log.mkiv
+++ b/Master/texmf-dist/tex/context/base/cont-log.mkiv
@@ -118,7 +118,7 @@
\logofont}
\def\syst_logos_meta_hyphen % there is no hyphenchar in this font
- {\discretionary{\vrule\!!height.33em\!!depth-.27em\!!width.33em}{}{}}
+ {\discretionary{\vrule\s!height.33em\s!depth-.27em\s!width.33em}{}{}}
\unexpanded\def\MetaFont
{\dontleavehmode
@@ -270,4 +270,12 @@
\unexpanded\def\MPII{MpII}
\unexpanded\def\MPIV{MpIV}
+\appendtoks
+ \def\ConTeXt {ConTeXt}%
+ \def\MetaPost{MetaPost}%
+ \def\MetaFont{MetaFont}%
+ \def\MetaFun {MetaFun}%
+ \def\TeX {TeX}%
+\to \everysimplifycommands
+
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/cont-new.mkii b/Master/texmf-dist/tex/context/base/cont-new.mkii
index b4958762f1a..b2df7931aea 100644
--- a/Master/texmf-dist/tex/context/base/cont-new.mkii
+++ b/Master/texmf-dist/tex/context/base/cont-new.mkii
@@ -11,7 +11,7 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-\newcontextversion{2012.05.30 11:26}
+\newcontextversion{2013.03.29 01:31}
%D This file is loaded at runtime, thereby providing an
%D excellent place for hacks, patches, extensions and new
diff --git a/Master/texmf-dist/tex/context/base/cont-new.mkiv b/Master/texmf-dist/tex/context/base/cont-new.mkiv
index 5a28f8e29ff..530058fc92f 100644
--- a/Master/texmf-dist/tex/context/base/cont-new.mkiv
+++ b/Master/texmf-dist/tex/context/base/cont-new.mkiv
@@ -11,515 +11,72 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-\newcontextversion{2012.05.30 11:26}
+\newcontextversion{2013.04.07 14:05}
-%D This file is loaded at runtime, thereby providing an
-%D excellent place for hacks, patches, extensions and new
-%D features.
+%D This file is loaded at runtime, thereby providing an excellent place for
+%D hacks, patches, extensions and new features.
\unprotect
\writestatus\m!system{beware: some patches loaded from cont-new.mkiv}
-\def\dividedsize#1#2#3% size gap n
- {\dimexpr
- \ifnum\dimexpr#1\relax>\plusone
- (\dimexpr#1\relax-\numexpr#3-1\relax\dimexpr#2\relax)/#3\else#1%
- \fi
- \relax}
-
-\def\singlewidened #1{\hbox spread 1em{\hss#1\hss}}
-\def\complexwidened[#1]#2{\hbox spread #1{\hss#2\hss}}
+% \attribute152\zerocount : marks ... lots of sweeps so best early in list
-\definecomplexorsimple\widened
-
-\let\active\activecatcode % for a while (tikz)
-
-% todo
-%
-% \def\definelocation{\dodoubleargument\dodefinelocation}
-% \def\dodefinelocation[#1][#2]{\setvalue{loc:#1}{#2}}
-%
-% \definelocation[lt] [\v!left\v!top]
-% \definelocation[tl] [\v!left\v!top]
-% \definelocation[\v!top\v!left][\v!left\v!top]
-%
-% \def\getlocation#1{\executeifdefined{loc:#1}{#1}}
-
-% \let\cs\getvalue % no, we want \cs to be czech
-
-% experimental so this may change
-
-\def\startdescriptions
- {\dosingleempty\dostartdescriptions}
-
-\def\dostartdescriptions[#1]%
- {\begingroup
- \def\item{\getvalue{#1}}%
- \let\dostoppairdescription \donothing
- \let\@@description \dostartpairdescription
- \let\@@startsomedescription\dostartsomedescription}
+%D Maybe:
-\def\stopdescriptions
- {\dostoppairdescription
- \endgroup}
+\unexpanded\def\tightvbox{\dowithnextbox{\dp\nextbox\zeropoint\box\nextbox}\vbox}
+\unexpanded\def\tightvtop{\dowithnextbox{\ht\nextbox\zeropoint\box\nextbox}\vtop}
-\def\dostartpairdescription[#1][#2]%
- {\dostoppairdescription
- \def\dostoppairdescription{\@@stopdescription{#1}}%
- \bgroup
- \def\currentdescription{#1}%
- \doifelse{\descriptionparameter{\s!do\c!state}}\v!start
- {\@@makedescription{#1}[#2]{}}
- {\@@makedescription{#1}[#2]}}
+%D Maybe:
-\def\dostartsomedescription% #1[#2]#3%
- {\bgroup
- \@@makedescription} % {#1}[#2]{#3}}
-
-% \starttext
-%
-% \definedescription[test]
-%
-% \startdescriptions
-% \test{Foo} Bar bar bar
-% \test{Foo} Bar bar bar
-% \test{Foo} Bar bar bar
-% \stopdescriptions
-%
-% \startdescriptions[test]
-% \item{Foo} Bar bar bar
-% \item{Foo} Bar bar bar
-% \item{Foo} Bar bar bar
-% \stopdescriptions
+% \startluacode
+% function context.loadfile(filename)
+% context(string.strip(io.loaddata(resolvers.findfile(filename))))
+% end
+% \stopluacode
%
-% \startdescriptions
-% \starttest{Foo} Bar bar bar \stoptest
-% \starttest{Foo} Bar bar bar \stoptest
-% \starttest{Foo} Bar bar bar \stoptest
-% \stopdescriptions
-%
-% \startdescriptions[test]
-% \item{Foo} Bar bar bar
-% \item{Foo} Bar bar bar
-% \item{Foo} Bar bar bar
-% \stopdescriptions
-%
-% \stoptext
-
-% this will be activated when
-%
-% \newinsert\thispageinsert % <- installinsertion
-%
-% \def\flushatthispage
-% {\bgroup
-% \dowithnextbox{\insert\thispageinsert{\box\nextbox}\egroup}%
-% \hbox}
-%
-% \appendtoks
-% \ifvoid\thispageinsert\else\hbox{\smashedbox\thispageinsert}\fi
-% \to \everyshipout
-
-% \definemarkedpage[nobackgrounds]
-% \markpage[nobackgrounds]
-% \doifmarkedpageelse{nobackgrounds}
-
-% Just a simple and fast hanger, for usage in macros.
-
-\def\setuphanging
- {\dodoubleempty\getparameters[\??ha]}
-
-\setuphanging
- [\c!distance=.5em]
-
-\def\starthanging
- {\noindent\bgroup
- \dowithnextbox
- {\setbox\nextbox\hbox{\flushnextbox\hskip\@@hadistance}%
- \hangindent\nextboxwd
- \hangafter\plusone
- \flushnextbox\ignorespaces}
- \hbox}
-
-\def\stophanging
- {\endgraf
- \egroup}
+% \edef\tufte{\cldcommand{loadfile("tufte.tex")}}
-% experimental
-
-\def\stophangaround
- {\endgraf
- \egroup}
-
-\def\starthangaround
- {\noindent\bgroup
- \dowithnextbox
- {\ifdim\nextboxht>\strutht\setbox\nextbox\tbox{\flushnextbox}\fi
- \setbox\nextbox\hbox{\flushnextbox\hskip\@@hadistance}%
- \getboxheight\scratchdimen\of\box\nextbox
- \getnoflines\scratchdimen
- \nextboxht\strutht
- \nextboxdp\strutdp
- \hangindent\nextboxwd
- \hangafter-\noflines
- \llap{\flushnextbox}\ignorespaces}
- \hbox}
-
-\def\modevalue#1#2#3%
- {\@EA\ifx\csname\@mode@\systemmodeprefix#1\endcsname\endcsname\enabledmode#2\else#2\fi}
-
-\def\systemmodevalue#1%
- {\modevalue{\systemmodeprefix#1}}
-
-% new, still to be improved
-%
-% \dorecurse{10}
-% {\input thuan
-% \placefigure{}{\framed[height=1.5cm]{test}}
-% \placefloatplaceholder}
-
-\def\placefloatplaceholder
- {\ifroomforfloat \else
- \scratchdimen\pagegoal
- \advance\scratchdimen-\pagetotal
- \advance\scratchdimen-3\lineheight
- \ifdim\scratchdimen>\zeropoint
- \startlinecorrection[blank]
- \mhbox{\inframed{\labeltexts{placeholder}{\lastcaptiontag}}}%
- \stoplinecorrection
- \else
- \allowbreak
- \fi
- \fi}
-
-\setuplabeltext
- [placeholder={, moved}]
-
-% move to support module, and then use context(...)
-
-\startluacode
- function commands.percentageof(str,dim)
- local n = str:match("^(.*)%%$")
- context.sprint(tex.ctxcatcodes,(n and (tonumber(n)/100)*dim .. "sp") or str)
- end
-\stopluacode
-
-\gdef\setpercentdimen#1#2%
- {#1=\ctxcommand{percentageof("#2",\number#1)}\relax}
-
-% \scratchdimen=100pt \setpercentdimen\scratchdimen{10\letterpercent} \the\scratchdimen
-% \scratchdimen=100pt \setpercentdimen\scratchdimen{5pt} \the\scratchdimen
-
-\bgroup \permitcircumflexescape
-
-\obeylines % don't remove %'s !
-
-\gdef\collapsedspace#1%
- {\ifx#1^^M%
- \expandafter\collapsedspace
- \else
- \space
- \expandafter#1%
- \fi}
-
-\gdef\collapsespaces
- {\prependtoksonce\relax\to\everyeof%
- \ignorelines%
- \ignoretabs%
- \let\obeyedspace\collapsedspace%
- \obeyspaces}
-
-\egroup
-
-\def\inlinedbox
- {\bgroup
- \dowithnextbox
- {\scratchdimen\nextboxht
- \advance\scratchdimen\nextboxdp
- \advance\scratchdimen-\lineheight
- \divide\scratchdimen\plustwo
- \advance\scratchdimen\strutdepth
- \setbox\nextbox\hbox{\lower\scratchdimen\flushnextbox}%
- \nextboxht\strutht
- \nextboxdp\strutdp
- \flushnextbox
- \egroup}%
- \hbox}
-
-\def\dimenratio#1#2% etex only
- {\withoutpt\the\dimexpr2\dimexpr(#1)/\dimexpr(#2)/32768\relax\relax}
-
-\def\doxprecurse#1#2%
- {\ifnum#1=\zerocount % no \ifcase
- \expandafter\gobblethreearguments
- \else
- #2\expandafter\expandafter\expandafter\doxprecurse\expandafter
- \fi\expandafter{\the\numexpr#1-1\relax}{#2}}
-
-\def\buttonframed{\dodoubleempty\localframed[\??bt]} % goodie
-
-\unexpanded\def\asciistr#1{\dontleavehmode{\defconvertedargument\ascii{#1}\verbatimfont\ascii}}
-
-\def\shapefill{\vskip\zeropoint\!!plus\lineheight\!!minus\lineheight\relax}
-
-% \ruledhbox
-% {\startignorespaces
-% \def\oeps{a}
-% \startignorespaces
-% \def\oeps{a}
-% \stopignorespaces
-% \def\oeps{a}
-% \stopignorespaces
-% \oeps}
+%D Needs some work:
-\newsignal\boissignal
-\newcount \boislevel
+\unexpanded\def\startgridcorrection
+ {\dosingleempty\spac_grid_correction_start}
-\long\def\startignorespaces
- {\advance\boislevel\plusone
- \ifcase\boislevel\or \ifhmode
- \hskip\boissignal
- \fi \fi
- \ignorespaces}
-
-\long\def\stopignorespaces
- {\ifcase\boislevel\or \ifhmode
- \doloop
- {\ifdim\lastskip=\zeropoint
- \exitloop
- \else\ifdim\lastskip=\boissignal
- \unskip
- \exitloop
- \else
- \unskip
- \fi\fi}%
- \fi \fi
- \advance\boislevel\minusone}
-
-\def\minimalhbox#1#%
- {\dowithnextbox
- {\bgroup
- \setbox\scratchbox\hbox#1{\hss}%
- \ifdim\nextboxwd<\wd\scratchbox\nextboxwd\wd\scratchbox\fi
- \flushnextbox
- \egroup}
- \hbox}
-
-\def\gobbleuntilempty#1\empty{}
-
-\def\dodimchoice#1#2#3%
- {\ifdim#1#2%
- #3\@EA\gobbleuntilempty
- \else
- \@EA\dodimchoice
- \fi{#1}}
-
-\def\donumchoice#1#2#3%
- {\ifnum#1#2%
- #3\@EA\gobbleuntilempty
- \else
- \@EA\dodimchoice
- \fi{#1}}
-
-\def\dimchoice#1#2{\dodimchoice{#1}#2{=#1}{#1}\empty}
-\def\numchoice#1#2{\donumchoice{#1}#2{=#1}{#1}\empty}
-
-% \the\dimexpr(\dimchoice {7pt}{{<10pt}{8pt}{<12pt}{9pt}{<15pt}{10pt}{=11pt}{12pt}})
-% \the\dimexpr(\dimchoice{11pt}{{<10pt}{8pt}{<12pt}{9pt}{<15pt}{10pt}{=11pt}{12pt}})
-% \the\dimexpr(\dimchoice{14pt}{{<10pt}{8pt}{<12pt}{9pt}{<15pt}{10pt}{=11pt}{12pt}})
-
-\def\tabulaterule % to be redone, not correct
- {\dotabulaterule
- {\hrule\!!height.5\scratchdimen\!!depth.5\scratchdimen\relax
- \doifvalue{\??tt\currenttabulate\c!distance}\v!grid
- {\kern-\scratchdimen}}} % experimental tm-prikkels
-% so far
-
-% between alignment lines certain rules apply, and even a
-% simple test can mess up a table, which is why we have a
-% special test facility
-%
-% \ruledvbox
-% {\starttabulate[|l|p|]
-% \NC 1test \NC test \NC \NR
-% \tableifelse{\doifelse{a}{a}}{\NC Xtest \NC test \NC \NR}{}%
-% \stoptabulate}
-
-\long\def\tableifelse#1%
- {\tablenoalign
- {#1%
- {\aftergroup \firstoftwoarguments}%
- {\aftergroup\secondoftwoarguments}}}
-
-\long \def\tableiftextelse#1{\tableifelse{\doiftextelse{#1}}}
-
-\def\tightvbox{\dowithnextbox{\nextboxdp\zeropoint\flushnextbox}\vbox}
-\def\tightvtop{\dowithnextbox{\nextboxht\zeropoint\flushnextbox}\vtop}
-
-% what is this stupid macro meant for:
-
-\def\hyphenationpoint
- {\hskip\zeropoint}
-
-\def\hyphenated#1%
- {\bgroup
- \!!counta\zerocount
- \def\hyphenated##1{\advance\!!counta\plusone}%
- \handletokens#1\with\hyphenated
- \!!countb\plusone
- \def\hyphenated##1%
- {##1%
- \advance\!!countb\plusone\relax
- \ifnum\!!countb>2 \ifnum\!!countb<\!!counta
- \hyphenationpoint
- \fi\fi}%
- \handletokens#1\with\hyphenated
- \egroup}
-
-\def\obeysupersubletters
- {\let\super\normalsuper
- \let\suber\normalsuber
- \let\normalsuper\letterhat
- \let\normalsuber\letterunderscore
- \enablesupersub}
-
-\def\obeysupersubmath
- {\let\normalsuper\letterhat
- \let\normalsuber\letterunderscore
- \enablesupersub}
-
-\def\startgridcorrection
- {\dosingleempty\dostartgridcorrection}
-
-\def\dostartgridcorrection[#1]%
+\def\spac_grid_correction_start[#1]%
{\ifgridsnapping
\snaptogrid[#1]\vbox\bgroup
\else
\startbaselinecorrection
\fi}
-\def\stopgridcorrection
+\unexpanded\def\stopgridcorrection
{\ifgridsnapping
\egroup
\else
\stopbaselinecorrection
\fi}
-
-\def\checkgridsnapping
+
+\unexpanded\def\checkgridsnapping
{\lineskip\ifgridsnapping\zeropoint\else\normallineskip\fi}
-
-\def\startplaatsen
- {\dosingleempty\dostartplaatsen}
-\def\dostartplaatsen[#1]% tzt n*links etc
- {\endgraf
- \noindent\bgroup
- \setlocalhsize
- \hbox to \localhsize\bgroup
- \doifnot{#1}\v!left\hss
- \def\stopplaatsen
- {\unskip\unskip\unskip
- \doifnot{#1}\v!right\hss
- \egroup
- \egroup
- \endgraf}%
- \gobblespacetokens}
+%D Probably obsolete:
-% \startplaatsen[links] bla \stopplaatsen
-
-\def\startcolumnmakeup % don't change
+\unexpanded\def\startcolumnmakeup % don't change
{\bgroup
- \getrawnoflines\textheight % teksthoogte kan topskip hebben, dus raw
- \scratchdimen\noflines\lineheight
- \advance\scratchdimen-\lineheight
- \advance\scratchdimen\topskip
- \setbox\scratchbox
- \ifcase\showgridstate\vbox\else\ruledvbox\fi to \scratchdimen\bgroup
- \forgetall} % ! don't change
+ \getrawnoflines\textheight % raw as we cna have topskip
+ \setbox\scratchbox\vbox to \dimexpr\noflines\lineheight-\lineheight+\topskip\relax
+ \bgroup
+ \forgetall}
-\def\stopcolumnmakeup
+\unexpanded\def\stopcolumnmakeup
{\egroup
\dp\scratchbox\zeropoint
\wd\scratchbox\textwidth
\box\scratchbox
\egroup
\page_otr_command_synchronize_hsize}
-
-\long\def\startexternalfigure
- {\dotripleempty\dostartexternalfigure}
-
-\long\def\dostartexternalfigure[#1][#2][#3]#4\stopexternalfigure
- {\gdef\figuredescription{#4}%
- \externalfigure[#1][#2][#3]%
- \globallet\figuredescription\empty}
-
-\let\figuredescription\empty
-
-% incomplete, will be a special case of float placement
-
-\def\startfixed{\dosingleempty\dostartfixed}
-
-\def\dostartfixed[#1]%
- {\expanded{\dowithnextbox{\noexpand\dodofixed{\ifhmode0\else1\fi}{#1}}}%
- \vbox\bgroup
- \setlocalhsize}
-
-\def\stopfixed
- {\egroup}
-
-\def\dodofixed#1#2%
- {\ifcase#1\relax
- \processaction
- [#2]
- [ \v!high=>\bbox {\flushnextbox},
- \v!low=>\tbox {\flushnextbox},
- \v!middle=>\vcenter{\flushnextbox},
- \v!lohi=>\vcenter{\flushnextbox},
- \s!unknown=>\tbox {\flushnextbox},
- \s!default=>\tbox {\flushnextbox}]%
- \else
- \startbaselinecorrection
- \noindent\flushnextbox
- \stopbaselinecorrection
- \fi}
-
-% \startitemize
-%
-% \item \externalfigure[koe][height=2cm]
-% \item \externalfigure[koe][height=2cm]
-% \item \externalfigure[koe][height=2cm]
-% \item \externalfigure[koe][height=2cm]
-%
-% \page
-%
-% \item \startfixed \externalfigure[koe][height=2cm]\stopfixed
-% \item \startfixed[high]\externalfigure[koe][height=2cm]\stopfixed
-% \item \startfixed[low] \externalfigure[koe][height=2cm]\stopfixed
-% \item \startfixed[lohi]\externalfigure[koe][height=2cm]\stopfixed
-%
-% \page
-%
-% \item test \startfixed \externalfigure[koe][height=2cm]\stopfixed
-% \item test \startfixed[high]\externalfigure[koe][height=2cm]\stopfixed
-% \item test \startfixed[low] \externalfigure[koe][height=2cm]\stopfixed
-% \item test \startfixed[lohi]\externalfigure[koe][height=2cm]\stopfixed
-%
-% \page
-%
-% \item test \par \startfixed \externalfigure[koe][height=2cm]\stopfixed
-% \item test \par \startfixed[high]\externalfigure[koe][height=2cm]\stopfixed
-% \item test \par \startfixed[low] \externalfigure[koe][height=2cm]\stopfixed
-% \item test \par \startfixed[lohi]\externalfigure[koe][height=2cm]\stopfixed
-%
-% \stopitemize
-
-\def\obeyfollowingtoken{{}} % end \cs scanning
-
-% potential new defaults:
-%
-% \setbreakpoints[compound]
-% till we fixed all styles:
+%D Till we fixed all styles:
\let\\=\crlf
diff --git a/Master/texmf-dist/tex/context/base/cont-nop.mkiv b/Master/texmf-dist/tex/context/base/cont-nop.mkiv
new file mode 100644
index 00000000000..c8188503e85
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/cont-nop.mkiv
@@ -0,0 +1,22 @@
+%D \module
+%D [ file=cont-nop,
+%D version=2012.06.01,
+%D title=\CONTEXT\ Miscellaneous Macros,
+%D subtitle=Startup Dummy,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\unprotect
+
+\writestatus\m!system{loading dummy replacement for jobname}
+
+\protect
+
+\finishjob
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/cont-yes.mkiv b/Master/texmf-dist/tex/context/base/cont-yes.mkiv
new file mode 100644
index 00000000000..5eae3eecb77
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/cont-yes.mkiv
@@ -0,0 +1,91 @@
+%D \module
+%D [ file=cont-yes,
+%D version=2012.06.01,
+%D title=\CONTEXT\ Miscellaneous Macros,
+%D subtitle=Startup Stub,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% At some point I will reconsider the \starttext .. \stoptext
+% wraping as we can assume proper styling. It's a left-over from
+% mkii that we need to get rid of.
+
+\startluacode
+
+ -- When a style is loaded there is a good change that we never enter
+ -- this code.
+
+ local report = logs.reporter("system")
+
+ environment.initializefilenames() -- todo: check if we really need to pre-prep the filename
+
+ local arguments = environment.arguments
+ local suffix = environment.suffix
+ local filename = environment.filename
+
+ if suffix == "xml" or arguments.forcexml then
+
+ -- Maybe we should move the preamble parsing here as it
+ -- can be part of (any) loaded (sub) file. The \starttext
+ -- wrapping might go away.
+
+ report("processing as xml: %s",filename)
+
+ context.starttext()
+ context.xmlprocess("main",filename,"")
+ context.stoptext()
+
+ elseif suffix == "cld" or arguments.forcecld then
+
+ report("processing as cld: %s",filename)
+
+ context.runfile(filename)
+
+ elseif suffix == "lua" or arguments.forcelua then
+
+ -- The wrapping might go away. Why is is it there in the
+ -- first place.
+
+ report("processing as lua: %s",filename)
+
+ context.starttext()
+ context.ctxlua(string.format('dofile("%s")',filename))
+ context.stoptext()
+
+ elseif suffix == "mp" or arguments.forcemp then
+
+ report("processing as metapost: %s",filename)
+
+ context.starttext()
+ context.processMPfigurefile(filename)
+ context.stoptext()
+
+ -- elseif suffix == "prep" then
+ --
+ -- -- Why do we wrap here. Because it can be xml? Let's get rid
+ -- -- of prepping in general.
+ --
+ -- context.starttext()
+ -- context.input(filename)
+ -- context.stoptext()
+
+ else
+
+ -- \writestatus{system}{processing as tex}
+ -- We have a regular tex file so no \starttext yet as we can
+ -- load fonts.
+
+ context.input(filename)
+
+ end
+
+ context.finishjob()
+
+\stopluacode
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/context-base.lmx b/Master/texmf-dist/tex/context/base/context-base.lmx
index 09817463b94..482d43e8866 100644
--- a/Master/texmf-dist/tex/context/base/context-base.lmx
+++ b/Master/texmf-dist/tex/context/base/context-base.lmx
@@ -2,6 +2,8 @@
+
+
-
-