summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Hagen <pragma@wxs.nl>2020-06-25 12:13:32 +0200
committerContext Git Mirror Bot <phg@phi-gamma.net>2020-06-25 12:13:32 +0200
commit2e657baa195eb8a5011a0f08eeb32bd3396ea1bf (patch)
tree183b7c9ce7a4f897c57743d6bbfe31ab0db42495
parent56c53b52bfa815946a62fdb28ee432b5d849b9c9 (diff)
downloadcontext-2e657baa195eb8a5011a0f08eeb32bd3396ea1bf.tar.gz
2020-06-25 10:58:00
-rw-r--r--doc/context/documents/general/manuals/cld-mkiv.pdfbin798293 -> 804105 bytes
-rw-r--r--doc/context/documents/general/manuals/luametatex.pdfbin1232904 -> 1232871 bytes
-rw-r--r--doc/context/sources/general/manuals/cld/cld-introduction.tex61
-rw-r--r--doc/context/sources/general/manuals/cld/cld-luafunctions.tex22
-rw-r--r--doc/context/sources/general/manuals/cld/cld-macros.tex6
-rw-r--r--doc/context/sources/general/manuals/cld/cld-mkiv.tex8
-rw-r--r--doc/context/sources/general/manuals/cld/cld-scanners.tex1046
-rw-r--r--doc/context/sources/general/manuals/cld/cld-specialcommands.tex4
-rw-r--r--doc/context/sources/general/manuals/cld/cld-variables.tex340
-rw-r--r--scripts/context/lua/mtxrun.lua49
-rw-r--r--scripts/context/stubs/mswin/mtxrun.lua49
-rw-r--r--scripts/context/stubs/unix/mtxrun49
-rw-r--r--scripts/context/stubs/win64/mtxrun.lua49
-rw-r--r--tex/context/base/mkii/cont-new.mkii2
-rw-r--r--tex/context/base/mkii/context.mkii2
-rw-r--r--tex/context/base/mkiv/anch-pos.lua1104
-rw-r--r--tex/context/base/mkiv/back-res.lua1
-rw-r--r--tex/context/base/mkiv/buff-ini.lua37
-rw-r--r--tex/context/base/mkiv/buff-ver.lua2
-rw-r--r--tex/context/base/mkiv/buff-ver.mkiv4
-rw-r--r--tex/context/base/mkiv/cldf-ini.lua508
-rw-r--r--tex/context/base/mkiv/cldf-int.lua28
-rw-r--r--tex/context/base/mkiv/cldf-lmt.lua144
-rw-r--r--tex/context/base/mkiv/cldf-scn.lua53
-rw-r--r--tex/context/base/mkiv/colo-ini.mkxl4
-rw-r--r--tex/context/base/mkiv/cont-new.mkiv2
-rw-r--r--tex/context/base/mkiv/context.mkiv2
-rw-r--r--tex/context/base/mkiv/context.mkxl2
-rw-r--r--tex/context/base/mkiv/file-mod.lua6
-rw-r--r--tex/context/base/mkiv/font-ctx.lua612
-rw-r--r--tex/context/base/mkiv/grph-chk.lua10
-rw-r--r--tex/context/base/mkiv/lpdf-ini.lua21
-rw-r--r--tex/context/base/mkiv/luat-ini.mkiv14
-rw-r--r--tex/context/base/mkiv/luat-usr.lua17
-rw-r--r--tex/context/base/mkiv/publ-aut.lua6
-rw-r--r--tex/context/base/mkiv/status-files.pdfbin27756 -> 27704 bytes
-rw-r--r--tex/context/base/mkiv/status-lua.pdfbin253681 -> 254484 bytes
-rw-r--r--tex/context/base/mkiv/strc-itm.mklx42
-rw-r--r--tex/context/base/mkiv/strc-itm.mkvi42
-rw-r--r--tex/context/base/mkiv/syst-aux.mkxl6
-rw-r--r--tex/context/base/mkiv/syst-lua.lua10
-rw-r--r--tex/context/base/mkiv/toks-ini.lua4
-rw-r--r--tex/context/base/mkiv/toks-scn.lua211
-rw-r--r--tex/context/base/mkiv/util-str.lua86
-rw-r--r--tex/generic/context/luatex/luatex-fonts-merged.lua45
45 files changed, 3095 insertions, 1615 deletions
diff --git a/doc/context/documents/general/manuals/cld-mkiv.pdf b/doc/context/documents/general/manuals/cld-mkiv.pdf
index bac02979f..63f1c36dc 100644
--- a/doc/context/documents/general/manuals/cld-mkiv.pdf
+++ b/doc/context/documents/general/manuals/cld-mkiv.pdf
Binary files differ
diff --git a/doc/context/documents/general/manuals/luametatex.pdf b/doc/context/documents/general/manuals/luametatex.pdf
index bd3333189..9c9f1c5bd 100644
--- a/doc/context/documents/general/manuals/luametatex.pdf
+++ b/doc/context/documents/general/manuals/luametatex.pdf
Binary files differ
diff --git a/doc/context/sources/general/manuals/cld/cld-introduction.tex b/doc/context/sources/general/manuals/cld/cld-introduction.tex
index 82fcb8007..a1a74cde4 100644
--- a/doc/context/sources/general/manuals/cld/cld-introduction.tex
+++ b/doc/context/sources/general/manuals/cld/cld-introduction.tex
@@ -26,6 +26,67 @@ that is available at the \TEX\ end, or you can use \LUA\ code to do the work, or
you can use a combination. So, from now on, in \CONTEXT\ you can code your style
and document source in (a mixture of) \TEX, \XML, \METAPOST\ and in \LUA.
+% \CONTEXT\ being a \TEX\ macro package quite some action happens at the \TEX\ end;
+% although we do a lot in \LUA, there is no need to abandon the macro language. If
+% I wanted a typesetting system written in procedural language I'd already come up
+% with one but I have no need for it and \TEX\ is more fun anyway. But the fact
+% that we mix these conceptual different languages means that we need ways to
+% communicate between them. The possibilities to communicate and switch between
+% \TEX, \LUA, and of course \METAPOST\ have evolved over time. It started with just
+% \type {\directlua} but we now can use tokens scanners that permit nice
+% interfaces. So, as a consequence the interfaces in \CONTEXT\ also evolved,
+% although mostly deep down out of sight of users: \CONTEXT\ always tries to offer
+% abstract interfaces that as designed in a way that permits upward compatible
+% upgrades.
+
+% Going from \LUA\ to \TEX\ is mostly done with the \type {context} command. The
+% most low level approach would be to use the \type {tex.print} functions but using
+% the \type {context} interface is often better. Going from \TEX\ to \LUA\ is done
+% with \type {\ctxlua} and friends, btu again, you can decide to go low level with
+% \type {\directlua}. Indeed, there is no need to use these interfaces and quite
+% often we see users use low level calls in combination with macros that pass
+% arguments and there's nothing wrong with that. We see no reason to block or
+% overload them.
+
+% In these internet times it is no problem to find comments on code and coding
+% practices (of course not seldom by people who themselves produce code that
+% deserves a lot of comment but get away with it). The same is true for complaints
+% about bugs that not always are put in the perspective of the total amount of well
+% working code or experiments; on the average \TEX\ systems behave quite well and
+% have not that many bugs, but some low level features they can be confusing. We
+% don't impose a coding style in user files but we do so in the core, but that only
+% hampers ourselves.
+
+% Another issue is complaints about manuals or lack of documentation, again, often
+% by people who themselves never produced something that those who they complain
+% about can use, but, that said, lack of documentation has the benefit that one can
+% learn by playing around. There are plenty of examples to learn from, also in the
+% over ten thousand pages of \CONTEXT\ documentation and articles. And of course
+% there is the test suite which has examples. Some users even like to look into the
+% source code to learn some tricks. Now, the internet is not always the friendly
+% and tolerant environment that its marketing suggests and one can run into
+% patronizing comments on how to do thing, but: we don't (and cannot) enforce best
+% practices.
+
+% However, when you define \LUA\ functions you should {\em not} overload existing
+% functions without knowing what you deal with, simply because the whole \CONTEXT\
+% ecosystem could be affected. Don't expect support when you do so. The same is
+% true for \TEX\ macros and even more so for primitives. Although there is some
+% protection going on we think the system should be as open as possible, so little
+% is hidden for the user. \footnote {In the core code and modules that come with
+% \CONTEXT\ we are rather rigourous. There we have patterns that need to be
+% followed. Hacking around and patching at will is not an option there. In the
+% rather open system that a macro package provides it is no problem to quickly mess
+% up the lot with bad code.}
+
+% The reason for mentioning this is that we do see users come up with (often
+% surprising) solutions and we invite them to keep playing around, even with low
+% level code. When writing a document, playing around can be a nice distraction.
+% But, using a high level interface has some benefits too. It gives a bit of
+% protection against bad interactions with other code. It also often involves less
+% coding. Performance might be better although that is not always a real issue as
+% there are plenty of ways to make a \TEX\ system slow anyway.
+
In the following chapters I will introduce typesetting in \LUA, but as we rely on
\CONTEXT\ it is unavoidable that some regular \CONTEXT\ code shows up. The fact
that you can ignore backslashes does not mean that you can do without knowledge
diff --git a/doc/context/sources/general/manuals/cld/cld-luafunctions.tex b/doc/context/sources/general/manuals/cld/cld-luafunctions.tex
index b2760e05b..c48b852fb 100644
--- a/doc/context/sources/general/manuals/cld/cld-luafunctions.tex
+++ b/doc/context/sources/general/manuals/cld/cld-luafunctions.tex
@@ -2306,20 +2306,22 @@ one provided by \LUATEX\ as it is more precise:
os.gettimeofday()
\stoptyping
-There is also a more extensive variant:
-
-\starttyping
-os.times()
-\stoptyping
-
-This one is platform dependent and returns a table with \type {utime} (use time),
-\type {stime} (system time), \type {cutime} (children user time), and \type
-{cstime} (children system time).
+% % This one is gone in luametatex:
+%
+% There is also a more extensive variant:
+%
+% \starttyping
+% os.times()
+% \stoptyping
+%
+% This one is platform dependent and returns a table with \type {utime} (use time),
+% \type {stime} (system time), \type {cutime} (children user time), and \type
+% {cstime} (children system time).
\stopsummary
\ShowLuaExampleThree {os} {gettimeofday} {}
-\ShowLuaExampleTwo {os} {times} {}
+%ShowLuaExampleTwo {os} {times} {}
\startsummary[title={runtime}]
diff --git a/doc/context/sources/general/manuals/cld/cld-macros.tex b/doc/context/sources/general/manuals/cld/cld-macros.tex
index a177db9f8..7b6f578e7 100644
--- a/doc/context/sources/general/manuals/cld/cld-macros.tex
+++ b/doc/context/sources/general/manuals/cld/cld-macros.tex
@@ -128,9 +128,9 @@ local function startmore(opt_1)
context.startnarrower()
end
-local function stopmore(opt_1)
+local function stopmore()
context.stopnarrower()
- context("stop more, options: %s",interfaces.tolist(opt_1))
+ context("stop more")
context.stopnarrower()
end
@@ -175,7 +175,7 @@ If needed you can access the body of a macro. Take for instance:
\typebuffer \getbuffer
-The following example demonsttaies how we can look inside these macros. You need
+The following example demonstrates how we can look inside these macros. You need
to be aware of the fact that the whole blob of \LUA\ codes is finished before we
return to \TEX, so when we pipe the meaning of \type {TestB} back to \TEX\ it
only gets expanded afterwards. We can use a function to get back to \LUA. It's
diff --git a/doc/context/sources/general/manuals/cld/cld-mkiv.tex b/doc/context/sources/general/manuals/cld/cld-mkiv.tex
index 5c35fa4e7..9267732fa 100644
--- a/doc/context/sources/general/manuals/cld/cld-mkiv.tex
+++ b/doc/context/sources/general/manuals/cld/cld-mkiv.tex
@@ -74,6 +74,8 @@
\component cld-logging
\component cld-luafunctions
\component cld-ctxfunctions
+ \component cld-scanners
+ \component cld-variables
\component cld-callbacks
\component cld-backendcode
\component cld-goodies
@@ -84,8 +86,8 @@
\component cld-files
\stopbodymatter
-% \startbackmatter
-% \component cld-index
-% \stopbackmatter
+\startbackmatter
+ \component cld-index
+\stopbackmatter
\stopproduct
diff --git a/doc/context/sources/general/manuals/cld/cld-scanners.tex b/doc/context/sources/general/manuals/cld/cld-scanners.tex
new file mode 100644
index 000000000..e0dfc30b0
--- /dev/null
+++ b/doc/context/sources/general/manuals/cld/cld-scanners.tex
@@ -0,0 +1,1046 @@
+% language=uk
+
+\startcomponent cld-ctxscanners
+
+\environment cld-environment
+
+\startchapter[title={Scanners}]
+
+\startsection[title={Introduction}]
+
+\index {implementors}
+\index {scanners}
+
+Here we discuss methods to define macros that directly interface with the \LUA\
+side. It involves all kind of scanners. There are actually more than we discuss
+here but some are meant for low level usage. What is describe here has been used
+for ages and works quite well.
+
+{\em We don't discuss some of the more obscure options here. Some are there just
+because we need them as part of bootstrapping or initializing code and are of no
+real use to users.}
+
+\stopsection
+
+\startsection[title={A teaser first}]
+
+Most of this chapter is examples and you learn \TEX\ (and \LUA) best by just
+playing around. The nice thing about \TEX\ is that it's all about visual output,
+so that's why in the next examples we just typeset some of what we just scanned.
+Of course in practice the \type {actions} will be more complex.
+
+\unexpanded\def\showmeaning#1%
+ {\begingroup
+ \dontleavehmode
+ \ttbf\string #1\space
+ \tttf\meaning#1%
+ \endgroup}
+
+\startbuffer[definition]
+\startluacode
+ interfaces.implement {
+ name = "MyMacroA",
+ public = true,
+ arguments = "string",
+ actions = function(s)
+ context("(%s)",s)
+ end,
+ }
+\stopluacode
+\stopbuffer
+
+\startbuffer[usage]
+\MyMacroA{123}
+\MyMacroA{abc}
+\edef\temp{\MyMacroA{abc}}
+\stopbuffer
+
+\typebuffer[definition] \getbuffer[definition]
+
+By default a macro gets defined in the \type {\clf_} namespace but the \type
+{public} option makes it visible. This default indicates that it is actually a
+low level mechanism in origin. More often than not these interfaces are used like
+this:
+
+\starttyping
+\def\MyMacro#1{... \clf_MyMacroA{#1} ...}
+\stoptyping
+
+When we look at the meaning of \type {\MyMacroA} we get:
+
+\blank \showmeaning\MyMacroA \blank
+
+And when we apply this macro as:
+
+\typebuffer[usage]
+
+We get
+
+\blank \getbuffer[usage] \blank
+
+The meaning of \type {\temp} is:
+
+\blank \showmeaning\temp \blank
+
+We can also define the macro to be protected (\type {\unexpanded}) in \CONTEXT\
+speak). We can overload existing scanners but unless we specify the \type
+{overload} option, we get a warning on the console.
+
+\startbuffer[definition]
+\startluacode
+ interfaces.implement {
+ name = "MyMacroA",
+ public = true,
+-- overload = true,
+ protected = true,
+ arguments = "string",
+ actions = function(s)
+ context("[%s]",s)
+ end,
+ }
+\stopluacode
+\stopbuffer
+
+\typebuffer[definition] \getbuffer[definition]
+
+This time we get:
+
+\getbuffer[usage]
+
+The meaning of \type {\temp} is:
+
+\blank \showmeaning\temp \blank
+
+\stopsection
+
+\startsection[title={Basic data types}]
+
+\index {implementors+arguments}
+
+It is actually possible to write very advanced scanners but unless you're in for
+obscurity the limited subset discussed here is normally enough. The \CONTEXT\
+user interface is rather predictable, unless you want to show off with weird
+additional interfaces, for instance by using delimiters other than curly braces
+and brackets, or by using separators other than commas.
+
+\startbuffer[definition]
+\startluacode
+ interfaces.implement {
+ name = "MyMacroB",
+ public = true,
+ arguments = { "string", "integer", "boolean", "dimen" },
+ actions = function(s,i,b,d)
+ context("<%s> <%i> <%l> <%p>",s,i,b,d)
+ end,
+ }
+\stopluacode
+\stopbuffer
+
+\typebuffer[definition] \getbuffer[definition]
+
+This time we grab four arguments, each of a different type:
+
+\startbuffer[usage]
+\MyMacroB{foo} 123 true 45.67pt
+
+\def\temp {oof}
+\scratchcounter 321
+\scratchdimen 76.54pt
+
+\MyMacroB\temp \scratchcounter false \scratchdimen
+\stopbuffer
+
+\typebuffer[usage]
+
+The above usage gives:
+
+\getbuffer[usage]
+
+As you can see, registers can be used as well, and the \type {\temp} macro is
+also accepted as argument. The integer and dimen arguments scan standard \TEX\
+values. If you want a \LUA\ number you can specify that as well. As our first
+example showed, when there is one argument you don't need an array to specify
+it.
+
+\startbuffer[definition]
+\startluacode
+ interfaces.implement {
+ name = "MyMacroC",
+ public = true,
+ arguments = "number",
+ actions = function(f)
+ context("<%.2f>",f)
+ end,
+ }
+\stopluacode
+\stopbuffer
+
+\typebuffer[definition] \getbuffer[definition]
+
+\startbuffer[usage]
+\MyMacroC 1.23
+\MyMacroC 1.23E4
+\MyMacroC -1.23E4
+\MyMacroC 0x1234
+\stopbuffer
+
+As you can see, hexadecimal numbers are also accepted:
+
+\typebuffer[usage]
+
+The above usage gives:
+
+\getbuffer[usage]
+
+\stopsection
+
+\startsection[title={Tables}]
+
+\index {implementors+tables}
+
+A list can be grabbed too. The individual items are separated by spaces and
+items can be bound by braces.
+
+\startbuffer[definition]
+\startluacode
+ interfaces.implement {
+ name = "MyMacroD",
+ public = true,
+ arguments = "list",
+ actions = function(t)
+ context("< % + t >",t)
+ end,
+ }
+\stopluacode
+\stopbuffer
+
+\typebuffer[definition] \getbuffer[definition]
+
+\startbuffer[usage]
+\MyMacroD { 1 2 3 4 {5 6} }
+\stopbuffer
+
+The macro call:
+
+\typebuffer[usage]
+
+results in:
+
+\getbuffer[usage]
+
+Often in \LUA\ scripts tables are uses all over the place. Picking up a table is
+also supported by the implementer.
+
+\startbuffer[definition]
+\startluacode
+ interfaces.implement {
+ name = "MyMacroE",
+ public = true,
+ arguments = {
+ {
+ { "bar", "integer" },
+ { "foo", "dimen" },
+ }
+ },
+ actions = function(t)
+ context("<foo : %p> <bar : %i>",t.foo,t.bar)
+ end,
+ }
+\stopluacode
+\stopbuffer
+
+\typebuffer[definition] \getbuffer[definition]
+
+\startbuffer[usage]
+\MyMacroE {
+ foo 12pt
+ bar 34
+}
+\stopbuffer
+
+Watch out, we don't use equal signs and commas here:
+
+\typebuffer[usage]
+
+We get:
+
+\getbuffer[usage]
+
+All the above can be combined:
+
+\startbuffer[definition]
+\startluacode
+ interfaces.implement {
+ name = "MyMacroF",
+ public = true,
+ arguments = {
+ "string",
+ {
+ { "bar", "integer" },
+ { "foo", "dimen" },
+ },
+ {
+ { "one", "string" },
+ { "two", "string" },
+ },
+ },
+ actions = function(s,t1,t2)
+ context("<%s> <%p> <%i> <%s> <%s>",s,t1.foo,t1.bar,t2.one,t2.two)
+ end,
+ }
+\stopluacode
+\stopbuffer
+
+\typebuffer[definition] \getbuffer[definition]
+
+\startbuffer[usage]
+\MyMacroF
+ {oeps}
+ { foo 12pt bar 34 }
+ { one {x} two {y} }
+\stopbuffer
+
+The following call:
+
+\typebuffer[usage]
+
+Results in one string and two table arguments.
+
+\getbuffer[usage]
+
+You can nest tables, as in:
+
+\startbuffer[definition]
+\startluacode
+ interfaces.implement {
+ name = "MyMacroG",
+ public = true,
+ arguments = {
+ "string",
+ "string",
+ {
+ { "data", "string" },
+ { "tab", "string" },
+ { "method", "string" },
+ { "foo", {
+ { "method", "integer" },
+ { "compact", "number" },
+ { "nature" },
+ { "*" }, -- any key
+ } },
+ { "compact", "string", "tonumber" },
+ { "nature", "boolean" },
+ { "escape" },
+ },
+ "boolean",
+ },
+ actions = function(s1, s2, t, b)
+ context("<%s> <%s>",s1,s2)
+ context("<%s> <%s> <%s>",t.data,t.tab,t.compact)
+ context("<%i> <%s> <%s>",t.foo.method,t.foo.nature,t.foo.whatever)
+ context("<%l>",b)
+ end,
+ }
+\stopluacode
+\stopbuffer
+
+\typebuffer[definition] \getbuffer[definition]
+
+\startbuffer[usage]
+\MyMacroG
+ {s1}
+ {s2}
+ {
+ data {d}
+ tab {t}
+ compact {12.34}
+ foo { method 1 nature {n} whatever {w} }
+ }
+ true
+\relax
+\stopbuffer
+
+Although the \type {\relax} is not really needed in the next calls, I often use
+it to indicate that we're done:
+
+\typebuffer[usage]
+
+This typesets:
+
+\getbuffer[usage]
+
+\stopsection
+
+\startsection[title=Expansion]
+
+\index {implementors+expansion}
+
+When working with scanners it is important to realize that we have to do with an
+expansion engine. When \TEX\ picks up a token, it can be done as-is, that is the
+raw token, but it can also expand that token first (which can be recursive) and
+then pick up the first token that results from that. Sometimes you want that
+expansion, for instance when you pick up keywords, sometimes you don't.
+
+Expansion effects are most noticeable when we pickup a \quote {string} kind of
+value. In the implementor we have two methods for that: \type {string} and \type
+{argument}. The argument method has an expandable form (the default) and one
+that doesn't expand. Take this:
+
+\startbuffer[definition]
+\startluacode
+ interfaces.implement {
+ name = "MyMacroH",
+ public = true,
+ arguments = {
+ "string",
+ "argument",
+ "argumentasis",
+ },
+ actions = function(a,b,c)
+ context.type(a or "-") context.quad()
+ context.type(b or "-") context.quad()
+ context.type(c or "-") context.crlf()
+ end,
+ }
+\stopluacode
+\stopbuffer
+
+\typebuffer[definition] \getbuffer[definition]
+
+Now take this input:
+
+\startbuffer[usage]
+\def\a{A} \def\b{B} \def\c{C}
+\MyMacroH{a}{b}{c}
+\MyMacroH{a\a}{b\b}{c\c}
+\MyMacroH\a\b\c\relax
+\MyMacroH\a xx\relax
+\stopbuffer
+
+\typebuffer[usage]
+
+We we use the string method we need a \type {\relax} (or some spacer) to end
+scanning of the string when we don't use curly braces. The last line is
+actually kind of tricky because the macro expects two arguments after
+scanning the first string.
+
+\blank {\getbuffer[usage]} \blank
+
+\startbuffer[definition]
+\startluacode
+ interfaces.implement {
+ name = "MyMacroI",
+ public = true,
+ arguments = {
+ "argument",
+ "argumentasis",
+ },
+ actions = function(a,b,c)
+ context.type(a or "-") context.quad()
+ context.type(b or "-") context.quad()
+ context.type(c or "-") context.crlf()
+ end,
+ }
+\stopluacode
+\stopbuffer
+
+Here is a variant:
+
+\typebuffer[definition] \getbuffer[definition]
+
+\startbuffer[usage]
+\def\a{A} \def\b{B}
+\MyMacroI{a}{b}
+\MyMacroI{a\a}{b\b}
+\MyMacroI\a\b\relax
+\stopbuffer
+
+With:
+
+\typebuffer[usage]
+
+we get:
+
+\blank {\getbuffer[usage]} \blank
+
+\stopsection
+
+\startsection[title=Boxes]
+
+\index {implementors+boxes}
+
+You can pick up a box too. The value returned is a list node:
+
+\startbuffer[definition]
+\startluacode
+ interfaces.implement {
+ name = "MyMacroJ",
+ public = true,
+ arguments = "box",
+ actions = function(b)
+ context(b)
+ end,
+ }
+\stopluacode
+\stopbuffer
+
+\typebuffer[definition] \getbuffer[definition]
+
+The usual box specifiers are supported:
+
+\startbuffer[usage]
+\MyMacroJ \hbox {\strut Test 1}
+\MyMacroJ \hbox to 4cm {\strut Test 2}
+\stopbuffer
+
+So, with:
+
+\typebuffer[usage]
+
+we get:
+
+\blank {\forgetall\dontcomplain\getbuffer[usage]} \blank
+
+There are three variants that don't need the box operator \type {hbox}, \type
+{vbox} and \type {vtop}:
+
+\startbuffer[definition]
+\startluacode
+ interfaces.implement {
+ name = "MyMacroL",
+ public = true,
+ arguments = {
+ "hbox",
+ "vbox",
+ },
+ actions = function(h,v)
+ context(h)
+ context(v)
+ end,
+ }
+\stopluacode
+\stopbuffer
+
+\typebuffer[definition] \getbuffer[definition]
+
+Again, the usual box specifiers are supported:
+
+\startbuffer[usage]
+\MyMacroL {\strut Test 1h} to 10mm {\vfill Test 1v\vfill}
+\MyMacroL spread 1cm {\strut Test 2h} to 15mm {\vfill Test 2v\vfill}
+\stopbuffer
+
+This:
+
+\typebuffer[usage]
+
+gives:
+
+\blank {\forgetall\dontcomplain\showboxes \getbuffer[usage]} \blank
+
+\stopsection
+
+\startsection[title=Like \CONTEXT]
+
+\index {implementors+hashes}
+\index {implementors+arrays}
+
+The previously discussed scanners don't use equal signs and commas as separators,
+but you can enforce that regime in the following way:
+
+
+\startbuffer[definition]
+\startluacode
+ interfaces.implement {
+ name = "MyMacroN",
+ public = true,
+ arguments = {
+ "hash",
+ "array",
+ },
+ actions = function(h, a)
+ context.totable(h)
+ context.quad()
+ context.totable(a)
+ end,
+ }
+\stopluacode
+\stopbuffer
+
+\typebuffer[definition] \getbuffer[definition]
+
+\startbuffer[usage]
+\MyMacroN
+ [ a = 1, b = 2 ]
+ [ 3, 4, 5, {6 7} ]
+\stopbuffer
+
+This:
+
+\typebuffer[usage]
+
+gives:
+
+\blank {\getbuffer[usage]} \blank
+
+\stopsection
+
+\startsection[title=Verbatim]
+
+\index {implementors+verbatim}
+
+There are a couple of rarely used scanners (there are more of course but these
+are pretty low level and not really used directly using implementors).
+
+\startbuffer[definition]
+\startluacode
+ interfaces.implement {
+ name = "MyMacroO",
+ public = true,
+ arguments = "verbatim",
+ actions = function(v)
+ context.type(v)
+ end,
+ }
+\stopluacode
+\stopbuffer
+
+\typebuffer[definition] \getbuffer[definition]
+
+\startbuffer[usage]
+\MyMacroO{this is \something verbatim}
+\stopbuffer
+
+There is no expansion applied in:
+
+\typebuffer[usage]
+
+so we get what we input:
+
+\blank {\getbuffer[usage]} \blank
+
+\stopsection
+
+\startsection[title=Macros]
+
+\index {implementors+macros}
+
+We can pick up a control sequence without bothering what it actually
+represents:
+
+\startbuffer[definition]
+\startluacode
+ interfaces.implement {
+ name = "MyMacroP",
+ public = true,
+ arguments = "csname",
+ actions = function(c)
+ context("{\\ttbf name:} {\\tttf %s}",c)
+ end,
+ }
+\stopluacode
+\stopbuffer
+
+\typebuffer[definition] \getbuffer[definition]
+
+\startbuffer[usage]
+\MyMacroP\framed
+\stopbuffer
+
+The next control sequence is picked up and its name without the leading
+escape character is returned:
+
+\typebuffer[usage]
+
+So here we get:
+
+\blank {\getbuffer[usage]} \blank
+
+\stopsection
+
+\startsection[title={Token lists}]
+
+\index {implementors+token lists}
+
+If you have no clue what tokens are in the perspective of \TEX, you can skip this
+section. We can grab a token list in two ways. The most \LUA ish way is to grab
+it as a table:
+
+\startbuffer[definition]
+\startluacode
+ interfaces.implement {
+ name = "MyMacroQ",
+ public = true,
+ arguments = "toks",
+ actions = function(t)
+ context("%S : ",t)
+ context.sprint(t)
+ context.crlf()
+ end,
+ }
+\stopluacode
+\stopbuffer
+
+\typebuffer[definition] \getbuffer[definition]
+
+\startbuffer[usage]
+\MyMacroQ{this is a {\bf token} list}
+\MyMacroQ{this is a \inframed{token} list}
+\stopbuffer
+
+\typebuffer[usage]
+
+The above sample code gives us:
+
+\blank {\getbuffer[usage]} \blank
+
+An alternative is to keep the list a user data object:
+
+\startbuffer[definition]
+\startluacode
+ interfaces.implement {
+ name = "MyMacroR",
+ public = true,
+ arguments = "tokenlist",
+ actions = function(t)
+ context("%S : ",t)
+ context.sprint(t)
+ context.crlf()
+ end,
+ }
+\stopluacode
+\stopbuffer
+
+\typebuffer[definition] \getbuffer[definition]
+
+\startbuffer[usage]
+\MyMacroR{this is a {\bf token} list}
+\MyMacroR{this is a \inframed{token} list}
+\stopbuffer
+
+\typebuffer[usage]
+
+Now we get:
+
+\blank {\getbuffer[usage]} \blank
+
+\stopsection
+
+\startsection[title={Actions}]
+
+\index {implementors+actions}
+
+The plural \type {actions} suggests that there can be more than one and indeed
+that is the case. The next example shows a sequence of actions that are applied.
+The first one gets the arguments passes.
+
+\startbuffer[definition]
+\startluacode
+ interfaces.implement {
+ name = "MyMacroS",
+ public = true,
+ arguments = "string",
+ actions = { characters.upper, context },
+ }
+\stopluacode
+\stopbuffer
+
+\typebuffer[definition] \getbuffer[definition]
+
+\startbuffer[usage]
+\MyMacroS{uppercase}
+\stopbuffer
+
+\typebuffer[usage]
+
+Gives: \inlinebuffer[usage]
+
+You can pass default arguments too. That way you can have multiple macros using
+the same action. Here's how to do that:
+
+\startbuffer[definition]
+\startluacode
+ local function MyMacro(a,b,sign)
+ if sign then
+ context("$%i + %i = %i$",a,b,a+b)
+ else
+ context("$%i - %i = %i$",a,b,a-b)
+ end
+ end
+
+ interfaces.implement {
+ name = "MyMacroPlus",
+ public = true,
+ arguments = { "integer", "integer", true },
+ actions = MyMacro,
+ }
+
+ interfaces.implement {
+ name = "MyMacroMinus",
+ public = true,
+ arguments = { "integer", "integer", false },
+ actions = MyMacro,
+ }
+\stopluacode
+\stopbuffer
+
+\typebuffer[definition] \getbuffer[definition]
+
+So,
+
+\startbuffer[usage]
+\MyMacroPlus 654 321 \crlf
+\MyMacroMinus 654 321 \crlf
+\stopbuffer
+
+\typebuffer[usage]
+
+Gives:
+
+\getbuffer[usage]
+
+
+\stopsection
+
+\startsection[title={Embedded \LUA\ code}]
+
+When you mix \TEX\ and \LUA, you can put the \LUA\ code in a \TEX\ file, for
+instance a style. In the previous sections we used this approach:
+
+\starttyping
+\startluacode
+ -- lua code
+\stopluacode
+\stoptyping
+
+This method is both reliable and efficient but you need to keep into mind that
+macros get expanded. In the next code, the second line will give an error when
+you have not defined \type {\foo} as expandable macro. When it is unexpandable it
+will get passed as it is and \LUA\ will see a \type {\f} as an escaped character.
+So, when you want a macro be passes as macro, you need to do it as in the third
+line. The fact that there is a comment trigger (\type {--}) doesn't help here.
+
+\starttyping
+\startluacode
+ context("foo")
+ -- context("\foo")
+ context("\\bar")
+\stopluacode
+\stoptyping
+
+When you use \type {\ctxlua} the same is true but there you also need to keep an
+eye on special characters. For instance a percent sign is then interpreted in the
+\TEX\ way and because all becomes one line, a \type {--} somewhere in the middle
+will make the rest of the line comment:
+
+\starttyping
+\ctxlua {
+ context("foo")
+ % context("\foo")
+ -- context("\\bar")
+}
+\stoptyping
+
+Here, the second line goes away (\TEX\ comment) and the third line obscures all
+that follows. You can use \type {\letterpercent} to smuggle a percent sign in a
+\type {\ctxlua} call. Special characters like a hash symbol also need to be
+passed by name. Normally curly braces are no problem because \LUA\ also likes
+them properly nested.
+
+When things become too messy and complex you can always put the code in an
+external file and load that one (e.g. with \type {require}.
+
+In the examples in this chapter we put the function in the table, but for long
+ones you might want to do this:
+
+\starttyping
+\startluacode
+ local function MyMacro(s)
+ -- lots of code
+ end
+
+ interfaces.implement {
+ name = "MyMacro",
+ public = true,
+ arguments = "string",
+ actions = MyMacro,
+ }
+\stopluacode
+\stoptyping
+
+It is a common mistake not to define variables and functions as local. If you
+define them global for sure there will become a time when this bites you.
+
+\stopsection
+
+\stopchapter
+
+\stopcomponent
+
+% conditional : true|false|0=true|!0=false : too weird for users
+% bracketed : maybe, but first I need a use case
+% bracketedasis : maybe, but first I need a use case
+% optional : maybe, but first I need a use case
+
+\startluacode
+
+ local function Grabbed(t)
+ context(t)
+ end
+
+ interfaces.implement {
+ name = "GrabC",
+ public = true,
+ actions = Grabbed,
+ arguments = "bracketed",
+ }
+ interfaces.implement {
+ name = "GrabD",
+ public = true,
+ actions = Grabbed,
+ arguments = "bracketedasis",
+ }
+ interfaces.implement {
+ name = "GrabE",
+ public = true,
+ actions = Grabbed,
+ arguments = "optional",
+ }
+\stopluacode
+
+\GrabC [foo {\red okay C} bar] \par
+\GrabC \par
+\GrabD [foo {\red okay D} bar] \par
+\GrabE [foo {\red okay E} bar] \par
+\GrabE \par
+
+% once stable:
+
+\startluacode
+ local random = math.random
+ local randomseed = math.randomseed
+
+ local scan_word = tokens.scanners.word
+ local scan_integer = tokens.scanners.integer
+ local scan_dimen = tokens.scanners.dimen
+ local scan_number = tokens.scanners.float
+
+ local scan_integer = tokens.scanners.luainteger
+ local scan_cardinal = tokens.scanners.luacardinal
+ local scan_number = tokens.scanners.luanumber
+
+ local I = 0
+ local D = 0
+ local F = 0
+
+ interfaces.implement {
+ name = "TestInteger",
+ public = true,
+ actions = function(b) if b then return I else I = scan_integer() end end,
+ valuetype = "count",
+ }
+
+ interfaces.implement {
+ name = "TestDimension",
+ public = true,
+ actions = function(b) if b then return D else D = scan_dimen() end end,
+ valuetype = "dimen",
+ }
+
+ interfaces.implement {
+ name = "TestFloat",
+ public = true,
+ actions = function(b)
+ if b then
+ context("%q",F)
+ else
+ F = scan_number()
+ end
+ end,
+ valuetype = "none",
+ }
+
+ interfaces.implement {
+ name = "TestThis",
+ public = true,
+ actions = function(b)
+ if b then
+ return random(scan_integer(),scan_integer())
+ else
+ randomseed(scan_integer(true))
+ end
+ end,
+ valuetype = "count",
+ }
+
+\stopluacode
+
+{\tttf [set:\TestInteger 808714][get: \the\TestInteger ]}\par % [get: \number\TestInteger ]}\par
+{\tttf [set:\TestDimension 12.34pt][get: \the\TestDimension]}\par % [get: \number\TestDimension]}\par
+{\tttf [set:\TestFloat 12.34567890e99][get: \the\TestFloat ]}\par % [get: \number\TestFloat ]}\par
+
+{\tttf \TestThis 123 \dorecurse{10}{\the \TestThis 1 10 \space}}\par
+{\tttf \TestThis 123 \dorecurse{10}{\the \TestThis 1 10 \space}}\par
+{\tttf \TestThis 456 \dorecurse{10}{\the \TestThis 1 10 \space}}\par
+{\tttf \dorecurse{10}{\the \TestThis 1 10 \space}}\par
+
+\TestFloat .1e20\relax
+\TestFloat -0x1.693d8e8943f17p+332\relax
+\TestFloat 0x1.693d8e8943f17p+332\relax
+
+\TestFloat 123.345E67\relax
+
+{\tttf [\the\TestFloat]}
+
+% maybe some day:
+
+% \startluacode
+% local t1 = token.get_next()
+% local t2 = token.get_next()
+% local t3 = token.get_next()
+% local t4 = token.get_next()
+% -- watch out, we flush in sequence
+% token.put_next { t1, t2 }
+% -- but this one gets pushed in front
+% token.put_next ( t3, t4 )
+% \stopluacode
+% abcd
+
+% \ctxlua{whatever = { } whatever.bf = token.get_next()}\bf
+
+\startluacode
+ local t_bf = whatever and whatever.bf or token.create("bf")
+ local put = token.put_next
+
+ interfaces.implement {
+ name = "whateverbfone",
+ public = true,
+ actions = function()
+ put(t_bf)
+ end
+ }
+
+ local ctx_whateverbfxxx = context.whateverbfxxx
+
+ interfaces.implement {
+ name = "whateverbftwo",
+ public = true,
+ actions = function()
+ ctx_whateverbfxxx(false)
+ end
+ }
+
+ interfaces.implement {
+ name = "whateverbfthree",
+ public = true,
+ actions = context.core.cs.whateverbfxxx
+ }
+
+\stopluacode
+
+\let\whateverbfxxx\bf
+
+\dontleavehmode{xxx: \whateverbfxxx xxx}\quad
+\dontleavehmode{one: \whateverbfone one}\quad
+\dontleavehmode{two: \whateverbftwo two}\quad
+\dontleavehmode{two: \whateverbfthree three}\par
diff --git a/doc/context/sources/general/manuals/cld/cld-specialcommands.tex b/doc/context/sources/general/manuals/cld/cld-specialcommands.tex
index 37ecf45c6..510c820f9 100644
--- a/doc/context/sources/general/manuals/cld/cld-specialcommands.tex
+++ b/doc/context/sources/general/manuals/cld/cld-specialcommands.tex
@@ -237,14 +237,14 @@ context.stepwise(function()
end)
\stopluacode
\stoptext
-\starttyping
+\stoptyping
Instead of the \type {testpage} function you can also play directly with
registers, like:
\starttyping
if tex.pagegtotal + tex.count.lineheight > tex.pagetotal then
-\starttyping
+\stoptyping
but often an already defined helper does a better job. Of course you will
probably never need this kind of hacks anyway, if only because much more is going
diff --git a/doc/context/sources/general/manuals/cld/cld-variables.tex b/doc/context/sources/general/manuals/cld/cld-variables.tex
new file mode 100644
index 000000000..c9afbd44c
--- /dev/null
+++ b/doc/context/sources/general/manuals/cld/cld-variables.tex
@@ -0,0 +1,340 @@
+% language=uk
+
+\startcomponent cld-variables
+
+\environment cld-environment
+
+\startchapter[title={Variables}]
+
+\startsection[title={Introduction}]
+
+\index {variables}
+
+Sometimes a bit of experimenting and exploring the boundaries of the \TEX|-|\LUA\
+interfaces results in new mechanisms. To what extent they are really useful is
+hard to say but we just keep them around. Some are described here. This is, at
+least for the moment, a \LMTX\ specific chapter.
+
+\stopsection
+
+\startsection[title={Simple tables}]
+
+\index {variables+grouped tables}
+
+The basic \TEX\ data types are counters (integers), dimensions (kind of floating
+point variables with typographic dimensions), token lists, node lists (boxes),
+fonts, and so on, but no data organized in tables. The first mechanism that we
+discuss is one that obeys grouping. In that respect is behaves like regular
+registers.
+
+\startbuffer
+\newhashedtable\somehashtable
+
+\somehashtable{ foo = 123, bar = "foo" }
+[123 = \the\somehashtable{foo}]
+[foo = \the\somehashtable{bar}]
+
+\bgroup
+\somehashtable{ foo = 456, bar = "oof" }
+[456 = \the\somehashtable{foo}]
+[oof = \the\somehashtable{bar}]
+\egroup
+
+[123 = \the\somehashtable{foo}]
+[foo = \the\somehashtable{bar}]
+
+\bgroup
+\global\somehashtable{ foo = 456 }
+ \somehashtable{ bar = "oof" }
+[456 = \the\somehashtable{foo}]
+[oof = \the\somehashtable{bar}]
+\egroup
+
+[456 = \the\somehashtable{foo}]
+[foo = \the\somehashtable{bar}]
+\stopbuffer
+
+\typebuffer
+
+We define a hashed table, one with keys and values. The definition is global.
+We can then assign values to this table where the assignments themselves are
+hash tables. The above code generates:
+
+\getbuffer
+
+As you can see, the \type {\global} prefix makes the value persistent outside the
+group. You can mix local and global assignments.
+
+Instead of a hashed table, you can have an indexed table. This time the keys are
+numbers.
+
+\startbuffer
+\newindexedtable\someindextable
+
+\someindextable{ 123, "foo" }
+[123 = \the\someindextable 1]
+[foo = \the\someindextable 2]
+
+\bgroup
+\someindextable{ 456, "oof" }
+[456 = \the\someindextable 1]
+[oof = \the\someindextable 2]
+\egroup
+
+[123 = \the\someindextable 1]
+[foo = \the\someindextable 2]
+
+\bgroup
+\global\someindextable{ [1] = 456 }
+ \someindextable{ [2] = "oof" }
+[456 = \the\someindextable 1]
+[oof = \the\someindextable 2]
+\egroup
+
+[456 = \the\someindextable 1]
+[foo = \the\someindextable 2]
+\stopbuffer
+
+\typebuffer
+
+The outcome is the same as before:
+
+\getbuffer
+
+At the \LUA\ end you can access these tables too:
+
+\startbuffer
+\startluacode
+context("[hashed : bar = %s]",context.hashedtables.somehashtable.bar)
+context("[indexed : 2 = %s]", context.indexedtables.someindextable[2])
+\stopluacode
+\stopbuffer
+
+\typebuffer
+
+Indeed we get:
+
+\getbuffer
+
+\stopsection
+
+\startsection[title={Data tables}]
+
+\index {variables+data tables}
+
+In \LUA, tables can be more complex than in the previous section. When you need
+more complex tables, it is likely that your grouping needs are also different,
+which is why we have another mechanism. This mechanism is build on top of another
+model: data values. There are 64K integer registers in any modern \TEX\ engine
+and normally that is more than enough. However, in addition in \LUAMETATEX\ we
+have a variant integer storage unit, one that is lightweight and where the amount
+is limited by the size of the hash table. It was added as part of the low level
+cleanup up of the \LUA\ token interface (a bit more abstraction). Here is an
+example of its usage:
+
+\startbuffer
+\dorecurse {100} {
+ \setdatavalue{#1}{#1}
+}
+
+\start \tttf \darkred \raggedright \dorecurse {100} {
+ #1=\scratchcounter\getdatavalue{#1}\the\scratchcounter
+} \par \stop \blank
+
+\start \tttf \darkgreen \raggedright \dorecurse {100} {
+ #1=\thedatavalue{#1}%
+} \par \stop \blank
+\stopbuffer
+
+\typebuffer
+
+\getbuffer
+
+We define hundred values which are a simple numeric macros. Here we use two
+auxiliary macros because we prefer to use a dedicated namespace for these
+variables. However, there are also primitives that deal with these data values:
+
+\startbuffer[usage]
+\setdatavalue{my-data}{12345}%
+\letdatacode \MyData 67890
+\thedatavalue{my-data} \the\MyData
+\stopbuffer
+
+\typebuffer[usage]
+
+gives: \inlinebuffer[usage]
+
+But, when more is needed than simple integers, tables come into view. This interface
+is different from the simple one and involves more commands. The next examples show
+about all:
+
+\startbuffer
+\newluatable\testtable
+\setluatable\testtable{ foo = 123, bar = "456", oof = "rab" }
+% \inspectluatable\testtable
+\darkcyan
+foo = \getfromluatable\testtable{foo}\par
+bar = \getfromluatable\testtable{bar}\par
+oof = \getfromluatable\testtable{oof}\par
+\bgroup
+ \useluatable\testtable
+ \setluatable\testtable{ foo = 123123, bar = "456456" }
+ % \inspectluatable\testtable
+ \darkmagenta
+ foo = \getfromluatable\testtable{foo}\par
+ bar = \getfromluatable\testtable{bar}\par
+ oof = \getfromluatable\testtable{oof}\par
+ \startluacode
+ local t = context.luatables.get("testtable")
+ context("<%s %s %s>",t.foo,t.bar,t.oof)
+ \stopluacode \par
+\egroup
+\darkyellow
+foo = \getfromluatable\testtable{foo}\par
+bar = \getfromluatable\testtable{bar}\par
+oof = \getfromluatable\testtable{oof}\par
+\startluacode
+ local t = context.luatables.get("testtable")
+ context("<%s %s %s>",t.foo,t.bar,t.oof)
+\stopluacode \par
+% \inspectluatable\testtable
+\stopbuffer
+
+\typebuffer
+
+The tables are semi|-|local: \type {\newluatable} creates a table and \type
+{\useluatable} will create a local copy that is discarded when the group ends.
+
+\startpacked
+\tttf \getbuffer
+\stoppacked
+
+Hashed and indexed tables can be used mixed, but there are additional accessors
+for indexed tables because there we expect numbers.
+
+\startbuffer
+\newluatable\moretable
+\setluatable\moretable{ 1, "foo" }
+\darkcyan
+[1] = \getfromluatable\moretable{1}\par
+[2] = \idxfromluatable\moretable 2 \par
+\bgroup
+ \useluatable\moretable
+ \setluatable\moretable{ foo = 123123, bar = "456456" }
+ \darkmagenta
+ [1] = \getfromluatable\moretable{1}\par
+ [2] = \idxfromluatable\moretable 2 \par
+ \startluacode
+ local t = context.luatables.get("moretable")
+ context("<%s %s>",t[1],t[2])
+ \stopluacode \par
+\egroup
+\darkyellow
+[1] = \getfromluatable\moretable{1}\par
+[2] = \idxfromluatable\moretable 2 \par
+\startluacode
+ local t = context.luatables.get("moretable")
+ context("<%s %s>",t[1],t[2])
+\stopluacode \par
+\stopbuffer
+
+\typebuffer
+
+\startpacked
+\tttf \getbuffer
+\stoppacked
+
+You can create more complex (nested) tables that you can handle at the \LUA\
+end in the usual way. Basically any \LUA\ that makes a table can go between
+the curly braces.
+
+\stopsection
+
+\startsection[title=Named variables]
+
+\index {variables+named}
+\index {variables+integers}
+\index {variables+cardinals}
+\index {variables+floats}
+\index {integers}
+\index {cardinals}
+\index {floats}
+
+Just because it can be done, and maybe it even has it use, we offer additional
+numbers, stored and accessible by name. The different types all live in their
+own namespace:
+
+\startbuffer[definition]
+\luainteger bar 123456
+\luafloat bar 123.456e12
+\luainteger gnu = 0xFFFF
+\stopbuffer
+
+\startbuffer[usage]
+{\darkcyan \the\luainteger bar}
+{\darkmagenta\the\luafloat bar}
+{\darkyellow \the\luainteger gnu}
+\stopbuffer
+
+\typebuffer[definition,usage] \getbuffer[definition]
+
+These serialize like: \getbuffer[usage]\removeunwantedspaces , and when not set they
+default to zero. There is an extra type, cardinal:
+
+\startbuffer
+\luainteger a 0x7FFFFFFFFFFFFFFF
+\luainteger b -0x7FFFFFFFFFFFFFFF
+\luacardinal c 0xFFFFFFFFFFFFFFFF
+\stopbuffer
+
+\typebuffer \getbuffer
+
+We cheat a bit behind the screens because it is actually a double but we scan
+it as positive integer and serialize it as such.
+
+\startbuffer
+[\the \luainteger a\relax]\par
+[\the \luainteger b\relax]\par
+[\the \luacardinal c\relax]\par
+\stopbuffer
+
+\typebuffer \getbuffer
+
+You have access to the numbers at the \LUA\ end, as in:
+
+\startbuffer
+\luainteger one 123 \luafloat two 456.678
+\luaexpr{interfaces.numbers.one/1000 + interfaces.numbers.two/10000}
+\stopbuffer
+
+\typebuffer
+
+There are \type {integers}, \type {cardinals} and \type {floats} but the \type
+{numbers} one is the most generic as it tries to resolve it from one of these
+namespaces, so we get: [\inlinebuffer\space\space]. There is also a related
+expression command:
+
+\startbuffer
+(?: \luaexpression {n.one/1000 + n.two/10000})
+(f: \luaexpression float {n.one/1000 + n.two/10000})
+(i: \luaexpression integer {n.one/1000 + n.two/10000})
+(c: \luaexpression cardinal {n.one/1000 + n.two/10000})
+(l: \luaexpression lua {n.one/1000 + n.two/10000})
+\stopbuffer
+
+\typebuffer
+
+It typesets this (watch the \type {lua} variant, which is a precise
+roundtrip serialization method):
+
+\startlines
+\tttf \getbuffer
+\stoplines
+
+The \type {n} table is just a shortcut to \type {interfaces.numbers}.
+
+\stopsection
+
+\stopchapter
+
+\stopcomponent
diff --git a/scripts/context/lua/mtxrun.lua b/scripts/context/lua/mtxrun.lua
index 74cb62938..f0b9b7cd2 100644
--- a/scripts/context/lua/mtxrun.lua
+++ b/scripts/context/lua/mtxrun.lua
@@ -6563,7 +6563,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["util-str"] = package.loaded["util-str"] or true
--- original size: 45153, stripped down to: 22734
+-- original size: 43947, stripped down to: 22741
if not modules then modules={} end modules ['util-str']={
version=1.001,
@@ -7219,33 +7219,36 @@ local format_extension=function(extensions,f,name)
local extension=extensions[name] or "tostring(%s)"
local f=tonumber(f) or 1
local w=find(extension,"%.%.%.")
- if w then
- if f==0 then
+ if f==0 then
+ if w then
extension=gsub(extension,"%.%.%.","")
- return extension
- elseif f==1 then
+ end
+ return extension
+ elseif f==1 then
+ if w then
extension=gsub(extension,"%.%.%.","%%s")
- n=n+1
- local a="a"..n
- return format(extension,a,a)
- elseif f<0 then
+ end
+ n=n+1
+ local a="a"..n
+ return format(extension,a,a)
+ elseif f<0 then
+ if w then
+ extension=gsub(extension,"%.%.%.","")
+ return extension
+ else
local a="a"..(n+f+1)
return format(extension,a,a)
- else
- extension=gsub(extension,"%.%.%.",rep("%%s,",f-1).."%%s")
- local t={}
- for i=1,f do
- n=n+1
- t[i]="a"..n
- end
- return format(extension,unpack(t))
end
else
- extension=gsub(extension,"%%s",function()
+ if w then
+ extension=gsub(extension,"%.%.%.",rep("%%s,",f-1).."%%s")
+ end
+ local t={}
+ for i=1,f do
n=n+1
- return "a"..n
- end)
- return extension
+ t[i]="a"..n
+ end
+ return format(extension,unpack(t))
end
end
local builder=Cs { "start",
@@ -26169,8 +26172,8 @@ end -- of closure
-- used libraries : l-bit32.lua l-lua.lua l-macro.lua l-sandbox.lua l-package.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-gzip.lua l-md5.lua l-sha.lua l-url.lua l-dir.lua l-boolean.lua l-unicode.lua l-math.lua util-str.lua util-tab.lua util-fil.lua util-sac.lua util-sto.lua util-prs.lua util-fmt.lua util-soc-imp-reset.lua util-soc-imp-socket.lua util-soc-imp-copas.lua util-soc-imp-ltn12.lua util-soc-imp-mime.lua util-soc-imp-url.lua util-soc-imp-headers.lua util-soc-imp-tp.lua util-soc-imp-http.lua util-soc-imp-ftp.lua util-soc-imp-smtp.lua trac-set.lua trac-log.lua trac-inf.lua trac-pro.lua util-lua.lua util-deb.lua util-tpl.lua util-sbx.lua util-mrg.lua util-env.lua luat-env.lua util-zip.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 libs-ini.lua luat-sta.lua luat-fmt.lua
-- skipped libraries : -
--- original bytes : 1040906
--- stripped bytes : 411386
+-- original bytes : 1039700
+-- stripped bytes : 410173
-- end library merge
diff --git a/scripts/context/stubs/mswin/mtxrun.lua b/scripts/context/stubs/mswin/mtxrun.lua
index 74cb62938..f0b9b7cd2 100644
--- a/scripts/context/stubs/mswin/mtxrun.lua
+++ b/scripts/context/stubs/mswin/mtxrun.lua
@@ -6563,7 +6563,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["util-str"] = package.loaded["util-str"] or true
--- original size: 45153, stripped down to: 22734
+-- original size: 43947, stripped down to: 22741
if not modules then modules={} end modules ['util-str']={
version=1.001,
@@ -7219,33 +7219,36 @@ local format_extension=function(extensions,f,name)
local extension=extensions[name] or "tostring(%s)"
local f=tonumber(f) or 1
local w=find(extension,"%.%.%.")
- if w then
- if f==0 then
+ if f==0 then
+ if w then
extension=gsub(extension,"%.%.%.","")
- return extension
- elseif f==1 then
+ end
+ return extension
+ elseif f==1 then
+ if w then
extension=gsub(extension,"%.%.%.","%%s")
- n=n+1
- local a="a"..n
- return format(extension,a,a)
- elseif f<0 then
+ end
+ n=n+1
+ local a="a"..n
+ return format(extension,a,a)
+ elseif f<0 then
+ if w then
+ extension=gsub(extension,"%.%.%.","")
+ return extension
+ else
local a="a"..(n+f+1)
return format(extension,a,a)
- else
- extension=gsub(extension,"%.%.%.",rep("%%s,",f-1).."%%s")
- local t={}
- for i=1,f do
- n=n+1
- t[i]="a"..n
- end
- return format(extension,unpack(t))
end
else
- extension=gsub(extension,"%%s",function()
+ if w then
+ extension=gsub(extension,"%.%.%.",rep("%%s,",f-1).."%%s")
+ end
+ local t={}
+ for i=1,f do
n=n+1
- return "a"..n
- end)
- return extension
+ t[i]="a"..n
+ end
+ return format(extension,unpack(t))
end
end
local builder=Cs { "start",
@@ -26169,8 +26172,8 @@ end -- of closure
-- used libraries : l-bit32.lua l-lua.lua l-macro.lua l-sandbox.lua l-package.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-gzip.lua l-md5.lua l-sha.lua l-url.lua l-dir.lua l-boolean.lua l-unicode.lua l-math.lua util-str.lua util-tab.lua util-fil.lua util-sac.lua util-sto.lua util-prs.lua util-fmt.lua util-soc-imp-reset.lua util-soc-imp-socket.lua util-soc-imp-copas.lua util-soc-imp-ltn12.lua util-soc-imp-mime.lua util-soc-imp-url.lua util-soc-imp-headers.lua util-soc-imp-tp.lua util-soc-imp-http.lua util-soc-imp-ftp.lua util-soc-imp-smtp.lua trac-set.lua trac-log.lua trac-inf.lua trac-pro.lua util-lua.lua util-deb.lua util-tpl.lua util-sbx.lua util-mrg.lua util-env.lua luat-env.lua util-zip.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 libs-ini.lua luat-sta.lua luat-fmt.lua
-- skipped libraries : -
--- original bytes : 1040906
--- stripped bytes : 411386
+-- original bytes : 1039700
+-- stripped bytes : 410173
-- end library merge
diff --git a/scripts/context/stubs/unix/mtxrun b/scripts/context/stubs/unix/mtxrun
index 74cb62938..f0b9b7cd2 100644
--- a/scripts/context/stubs/unix/mtxrun
+++ b/scripts/context/stubs/unix/mtxrun
@@ -6563,7 +6563,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["util-str"] = package.loaded["util-str"] or true
--- original size: 45153, stripped down to: 22734
+-- original size: 43947, stripped down to: 22741
if not modules then modules={} end modules ['util-str']={
version=1.001,
@@ -7219,33 +7219,36 @@ local format_extension=function(extensions,f,name)
local extension=extensions[name] or "tostring(%s)"
local f=tonumber(f) or 1
local w=find(extension,"%.%.%.")
- if w then
- if f==0 then
+ if f==0 then
+ if w then
extension=gsub(extension,"%.%.%.","")
- return extension
- elseif f==1 then
+ end
+ return extension
+ elseif f==1 then
+ if w then
extension=gsub(extension,"%.%.%.","%%s")
- n=n+1
- local a="a"..n
- return format(extension,a,a)
- elseif f<0 then
+ end
+ n=n+1
+ local a="a"..n
+ return format(extension,a,a)
+ elseif f<0 then
+ if w then
+ extension=gsub(extension,"%.%.%.","")
+ return extension
+ else
local a="a"..(n+f+1)
return format(extension,a,a)
- else
- extension=gsub(extension,"%.%.%.",rep("%%s,",f-1).."%%s")
- local t={}
- for i=1,f do
- n=n+1
- t[i]="a"..n
- end
- return format(extension,unpack(t))
end
else
- extension=gsub(extension,"%%s",function()
+ if w then
+ extension=gsub(extension,"%.%.%.",rep("%%s,",f-1).."%%s")
+ end
+ local t={}
+ for i=1,f do
n=n+1
- return "a"..n
- end)
- return extension
+ t[i]="a"..n
+ end
+ return format(extension,unpack(t))
end
end
local builder=Cs { "start",
@@ -26169,8 +26172,8 @@ end -- of closure
-- used libraries : l-bit32.lua l-lua.lua l-macro.lua l-sandbox.lua l-package.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-gzip.lua l-md5.lua l-sha.lua l-url.lua l-dir.lua l-boolean.lua l-unicode.lua l-math.lua util-str.lua util-tab.lua util-fil.lua util-sac.lua util-sto.lua util-prs.lua util-fmt.lua util-soc-imp-reset.lua util-soc-imp-socket.lua util-soc-imp-copas.lua util-soc-imp-ltn12.lua util-soc-imp-mime.lua util-soc-imp-url.lua util-soc-imp-headers.lua util-soc-imp-tp.lua util-soc-imp-http.lua util-soc-imp-ftp.lua util-soc-imp-smtp.lua trac-set.lua trac-log.lua trac-inf.lua trac-pro.lua util-lua.lua util-deb.lua util-tpl.lua util-sbx.lua util-mrg.lua util-env.lua luat-env.lua util-zip.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 libs-ini.lua luat-sta.lua luat-fmt.lua
-- skipped libraries : -
--- original bytes : 1040906
--- stripped bytes : 411386
+-- original bytes : 1039700
+-- stripped bytes : 410173
-- end library merge
diff --git a/scripts/context/stubs/win64/mtxrun.lua b/scripts/context/stubs/win64/mtxrun.lua
index 74cb62938..f0b9b7cd2 100644
--- a/scripts/context/stubs/win64/mtxrun.lua
+++ b/scripts/context/stubs/win64/mtxrun.lua
@@ -6563,7 +6563,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["util-str"] = package.loaded["util-str"] or true
--- original size: 45153, stripped down to: 22734
+-- original size: 43947, stripped down to: 22741
if not modules then modules={} end modules ['util-str']={
version=1.001,
@@ -7219,33 +7219,36 @@ local format_extension=function(extensions,f,name)
local extension=extensions[name] or "tostring(%s)"
local f=tonumber(f) or 1
local w=find(extension,"%.%.%.")
- if w then
- if f==0 then
+ if f==0 then
+ if w then
extension=gsub(extension,"%.%.%.","")
- return extension
- elseif f==1 then
+ end
+ return extension
+ elseif f==1 then
+ if w then
extension=gsub(extension,"%.%.%.","%%s")
- n=n+1
- local a="a"..n
- return format(extension,a,a)
- elseif f<0 then
+ end
+ n=n+1
+ local a="a"..n
+ return format(extension,a,a)
+ elseif f<0 then
+ if w then
+ extension=gsub(extension,"%.%.%.","")
+ return extension
+ else
local a="a"..(n+f+1)
return format(extension,a,a)
- else
- extension=gsub(extension,"%.%.%.",rep("%%s,",f-1).."%%s")
- local t={}
- for i=1,f do
- n=n+1
- t[i]="a"..n
- end
- return format(extension,unpack(t))
end
else
- extension=gsub(extension,"%%s",function()
+ if w then
+ extension=gsub(extension,"%.%.%.",rep("%%s,",f-1).."%%s")
+ end
+ local t={}
+ for i=1,f do
n=n+1
- return "a"..n
- end)
- return extension
+ t[i]="a"..n
+ end
+ return format(extension,unpack(t))
end
end
local builder=Cs { "start",
@@ -26169,8 +26172,8 @@ end -- of closure
-- used libraries : l-bit32.lua l-lua.lua l-macro.lua l-sandbox.lua l-package.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-gzip.lua l-md5.lua l-sha.lua l-url.lua l-dir.lua l-boolean.lua l-unicode.lua l-math.lua util-str.lua util-tab.lua util-fil.lua util-sac.lua util-sto.lua util-prs.lua util-fmt.lua util-soc-imp-reset.lua util-soc-imp-socket.lua util-soc-imp-copas.lua util-soc-imp-ltn12.lua util-soc-imp-mime.lua util-soc-imp-url.lua util-soc-imp-headers.lua util-soc-imp-tp.lua util-soc-imp-http.lua util-soc-imp-ftp.lua util-soc-imp-smtp.lua trac-set.lua trac-log.lua trac-inf.lua trac-pro.lua util-lua.lua util-deb.lua util-tpl.lua util-sbx.lua util-mrg.lua util-env.lua luat-env.lua util-zip.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 libs-ini.lua luat-sta.lua luat-fmt.lua
-- skipped libraries : -
--- original bytes : 1040906
--- stripped bytes : 411386
+-- original bytes : 1039700
+-- stripped bytes : 410173
-- end library merge
diff --git a/tex/context/base/mkii/cont-new.mkii b/tex/context/base/mkii/cont-new.mkii
index 242fe472a..380edf717 100644
--- a/tex/context/base/mkii/cont-new.mkii
+++ b/tex/context/base/mkii/cont-new.mkii
@@ -11,7 +11,7 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-\newcontextversion{2020.06.20 13:33}
+\newcontextversion{2020.06.25 10:55}
%D This file is loaded at runtime, thereby providing an
%D excellent place for hacks, patches, extensions and new
diff --git a/tex/context/base/mkii/context.mkii b/tex/context/base/mkii/context.mkii
index bbe1f8fca..0cf1b1e6c 100644
--- a/tex/context/base/mkii/context.mkii
+++ b/tex/context/base/mkii/context.mkii
@@ -20,7 +20,7 @@
%D your styles an modules.
\edef\contextformat {\jobname}
-\edef\contextversion{2020.06.20 13:33}
+\edef\contextversion{2020.06.25 10:55}
%D For those who want to use this:
diff --git a/tex/context/base/mkiv/anch-pos.lua b/tex/context/base/mkiv/anch-pos.lua
index 2788c9d1a..da95eeb1a 100644
--- a/tex/context/base/mkiv/anch-pos.lua
+++ b/tex/context/base/mkiv/anch-pos.lua
@@ -13,16 +13,19 @@ more efficient.</p>
--ldx]]--
-- plus (extra) is obsolete but we will keep it for a while
-
+--
-- 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
-
--- this is one of the first modules using scanners and we need to replace
--- it by implement and friends
-
+--
+-- this is one of the first modules using scanners and we need to replace it by
+-- implement and friends
+--
-- we could have namespaces, like p, page, region, columnarea, textarea but then
-- we need virtual table accessors as well as have tag/id accessors ... we don't
-- save much here (at least not now)
+--
+-- This was the last module that got rid of directly setting scanners, with a little
+-- performance degradation but not that noticeable.
local tostring, next, setmetatable, tonumber = tostring, next, setmetatable, tonumber
local sort = table.sort
@@ -38,8 +41,7 @@ local scanstring = scanners.string
local scaninteger = scanners.integer
local scandimen = scanners.dimen
-local compilescanner = tokens.compile
-local scanners = interfaces.scanners
+local implement = interfaces.implement
local commands = commands
local context = context
@@ -124,9 +126,9 @@ local nofregular = 0
local nofspecial = 0
local splitter = lpeg.splitat(":",true)
-local pagedata = { }
-local columndata = setmetatableindex("table") -- per page
-local freedata = setmetatableindex("table") -- per page
+local pagedata = { }
+local columndata = setmetatableindex("table") -- per page
+local freedata = setmetatableindex("table") -- per page
local function initializer()
tobesaved = jobpositions.tobesaved
@@ -376,19 +378,22 @@ jobpositions.set = set
jobpositions.setspec = setspec
jobpositions.get = get
-scanners.dosaveposition = compilescanner {
+implement {
+ name = "dosaveposition",
+ arguments = { "string", "integer", "dimen", "dimen" },
actions = setall, -- name p x y
- arguments = { "string", "integer", "dimen", "dimen" }
}
-scanners.dosavepositionwhd = compilescanner { -- somehow fails
+implement {
+ name = "dosavepositionwhd",
+ arguments = { "string", "integer", "dimen", "dimen", "dimen", "dimen", "dimen" },
actions = setall, -- name p x y w h d
- arguments = { "string", "integer", "dimen", "dimen", "dimen", "dimen", "dimen" }
}
-scanners.dosavepositionplus = compilescanner {
+implement {
+ name = "dosavepositionplus",
+ arguments = { "string", "integer", "dimen", "dimen", "dimen", "dimen", "dimen", "string" },
actions = setall, -- name p x y w h d extra
- arguments = { "string", "integer", "dimen", "dimen", "dimen", "dimen", "dimen", "string" }
}
-- will become private table (could also become attribute driven but too nasty
@@ -424,29 +429,41 @@ end
jobpositions.b_column = b_column
jobpositions.e_column = e_column
-scanners.bposcolumn = function() -- tag
- local tag = scanstring()
- insert(columns,tag)
- column = tag
-end
+implement {
+ name = "bposcolumn",
+ arguments = "string",
+ actions = function(tag)
+ insert(columns,tag)
+ column = tag
+ end
+}
-scanners.bposcolumnregistered = function() -- tag
- local tag = scanstring()
- insert(columns,tag)
- column = tag
- ctx_latelua { action = b_column, tag = tag }
-end
+implement {
+ name = "bposcolumnregistered",
+ arguments = "string",
+ actions = function(tag)
+ insert(columns,tag)
+ column = tag
+ ctx_latelua { action = b_column, tag = tag }
+ end
+}
-scanners.eposcolumn = function()
- remove(columns)
- column = columns[#columns]
-end
+implement {
+ name = "eposcolumn",
+ actions = function()
+ remove(columns)
+ column = columns[#columns]
+ end
+}
-scanners.eposcolumnregistered = function()
- ctx_latelua { action = e_column }
- remove(columns)
- column = columns[#columns]
-end
+implement {
+ name = "eposcolumnregistered",
+ actions = function()
+ ctx_latelua { action = e_column }
+ remove(columns)
+ column = columns[#columns]
+ end
+}
-- regions
@@ -551,167 +568,181 @@ end
local nofparagraphs = 0
-scanners.parpos = function()
- nofparagraphs = nofparagraphs + 1
- texsetcount("global","c_anch_positions_paragraph",nofparagraphs)
- local box = getbox("strutbox")
- local w, h, d = getwhd(box)
- local t = {
- p = true,
- c = true,
- r = true,
- x = true,
- y = true,
- h = h,
- d = d,
- hs = texget("hsize"), -- never 0
- }
- local leftskip = texget("leftskip",false)
- local rightskip = texget("rightskip",false)
- local hangindent = texget("hangindent")
- local hangafter = texget("hangafter")
- local parindent = texget("parindent")
- local parshape = texget("parshape")
- if leftskip ~= 0 then
- t.ls = leftskip
- end
- if rightskip ~= 0 then
- t.rs = rightskip
- end
- if hangindent ~= 0 then
- t.hi = hangindent
- end
- if hangafter ~= 1 and hangafter ~= 0 then -- can not be zero .. so it needs to be 1 if zero
- t.ha = hangafter
- end
- if parindent ~= 0 then
- t.pi = parindent
- end
- if parshape and #parshape > 0 then
- t.ps = parshape
+implement {
+ name = "parpos",
+ actions = function()
+ nofparagraphs = nofparagraphs + 1
+ texsetcount("global","c_anch_positions_paragraph",nofparagraphs)
+ local box = getbox("strutbox")
+ local w, h, d = getwhd(box)
+ local t = {
+ p = true,
+ c = true,
+ r = true,
+ x = true,
+ y = true,
+ h = h,
+ d = d,
+ hs = texget("hsize"), -- never 0
+ }
+ local leftskip = texget("leftskip",false)
+ local rightskip = texget("rightskip",false)
+ local hangindent = texget("hangindent")
+ local hangafter = texget("hangafter")
+ local parindent = texget("parindent")
+ local parshape = texget("parshape")
+ if leftskip ~= 0 then
+ t.ls = leftskip
+ end
+ if rightskip ~= 0 then
+ t.rs = rightskip
+ end
+ if hangindent ~= 0 then
+ t.hi = hangindent
+ end
+ if hangafter ~= 1 and hangafter ~= 0 then -- can not be zero .. so it needs to be 1 if zero
+ t.ha = hangafter
+ end
+ if parindent ~= 0 then
+ t.pi = parindent
+ end
+ if parshape and #parshape > 0 then
+ t.ps = parshape
+ end
+ local name = f_p_tag(nofparagraphs)
+ tobesaved[name] = t
+ ctx_latelua { action = enhance, specification = t }
end
- local name = f_p_tag(nofparagraphs)
- tobesaved[name] = t
- ctx_latelua { action = enhance, specification = t }
-end
+}
-scanners.dosetposition = function() -- name
- local name = scanstring()
- local spec = {
- p = true,
- c = column,
- r = true,
- x = true,
- y = true,
- n = nofparagraphs > 0 and nofparagraphs or nil,
- r2l = texgetcount("inlinelefttoright") == 1 or nil,
- }
- tobesaved[name] = spec
- ctx_latelua { action = enhance, specification = spec }
-end
+implement {
+ name = "dosetposition",
+ arguments = "string",
+ actions = function(name)
+ local spec = {
+ p = true,
+ c = column,
+ r = true,
+ x = true,
+ y = true,
+ n = nofparagraphs > 0 and nofparagraphs or nil,
+ r2l = texgetcount("inlinelefttoright") == 1 or nil,
+ }
+ tobesaved[name] = spec
+ ctx_latelua { action = enhance, specification = spec }
+ end
+}
-scanners.dosetpositionwhd = function() -- name w h d extra
- local name = scanstring()
- local w = scandimen()
- local h = scandimen()
- local d = scandimen()
- local spec = {
- p = true,
- c = column,
- r = true,
- x = true,
- y = true,
- w = w ~= 0 and w or nil,
- h = h ~= 0 and h or nil,
- d = d ~= 0 and d or nil,
- n = nofparagraphs > 0 and nofparagraphs or nil,
- r2l = texgetcount("inlinelefttoright") == 1 or nil,
- }
- tobesaved[name] = spec
- ctx_latelua { action = enhance, specification = spec }
-end
+implement {
+ name = "dosetpositionwhd",
+ arguments = { "string", "dimen", "dimen", "dimen" },
+ actions = function(name,w,h,d)
+ local spec = {
+ p = true,
+ c = column,
+ r = true,
+ x = true,
+ y = true,
+ w = w ~= 0 and w or nil,
+ h = h ~= 0 and h or nil,
+ d = d ~= 0 and d or nil,
+ n = nofparagraphs > 0 and nofparagraphs or nil,
+ r2l = texgetcount("inlinelefttoright") == 1 or nil,
+ }
+ tobesaved[name] = spec
+ ctx_latelua { action = enhance, specification = spec }
+ end
+}
-scanners.dosetpositionbox = function() -- name box
- local name = scanstring()
- local box = getbox(scaninteger())
- local w, h, d = getwhd(box)
- local spec = {
- p = true,
- c = column,
- r = true,
- x = true,
- y = true,
- w = w ~= 0 and w or nil,
- h = h ~= 0 and h or nil,
- d = d ~= 0 and d or nil,
- n = nofparagraphs > 0 and nofparagraphs or nil,
- r2l = texgetcount("inlinelefttoright") == 1 or nil,
- }
- tobesaved[name] = spec
- ctx_latelua { action = enhance, specification = spec }
-end
+implement {
+ name = "dosetpositionbox",
+ arguments = { "string", "integer" },
+ actions = function(name,n)
+ local box = getbox(n)
+ local w, h, d = getwhd(box)
+ local spec = {
+ p = true,
+ c = column,
+ r = true,
+ x = true,
+ y = true,
+ w = w ~= 0 and w or nil,
+ h = h ~= 0 and h or nil,
+ d = d ~= 0 and d or nil,
+ n = nofparagraphs > 0 and nofparagraphs or nil,
+ r2l = texgetcount("inlinelefttoright") == 1 or nil,
+ }
+ tobesaved[name] = spec
+ ctx_latelua { action = enhance, specification = spec }
+ end
+}
-scanners.dosetpositionplus = function() -- name w h d extra
- local name = scanstring()
- local w = scandimen()
- local h = scandimen()
- local d = scandimen()
- local spec = {
- p = true,
- c = column,
- r = true,
- x = true,
- y = true,
- w = w ~= 0 and w or nil,
- h = h ~= 0 and h or nil,
- d = d ~= 0 and d or nil,
- n = nofparagraphs > 0 and nofparagraphs or nil,
- e = scanstring(),
- r2l = texgetcount("inlinelefttoright") == 1 or nil,
- }
- tobesaved[name] = spec
- ctx_latelua { action = enhance, specification = spec }
-end
+implement {
+ name = "dosetpositionplus",
+ arguments = { "string", "dimen", "dimen", "dimen" },
+ actions = function(name,w,h,d)
+ local spec = {
+ p = true,
+ c = column,
+ r = true,
+ x = true,
+ y = true,
+ w = w ~= 0 and w or nil,
+ h = h ~= 0 and h or nil,
+ d = d ~= 0 and d or nil,
+ n = nofparagraphs > 0 and nofparagraphs or nil,
+ e = scanstring(),
+ r2l = texgetcount("inlinelefttoright") == 1 or nil,
+ }
+ tobesaved[name] = spec
+ ctx_latelua { action = enhance, specification = spec }
+ end
+}
-scanners.dosetpositionstrut = function() -- name
- local name = scanstring()
- local box = getbox("strutbox")
- local w, h, d = getwhd(box)
- local spec = {
- p = true,
- c = column,
- r = true,
- x = true,
- y = true,
- h = h ~= 0 and h or nil,
- d = d ~= 0 and d or nil,
- n = nofparagraphs > 0 and nofparagraphs or nil,
- r2l = texgetcount("inlinelefttoright") == 1 or nil,
- }
- tobesaved[name] = spec
- ctx_latelua { action = enhance, specification = spec }
-end
+implement {
+ name = "dosetpositionstrut",
+ arguments = "string",
+ actions = function(name)
+ local box = getbox("strutbox")
+ local w, h, d = getwhd(box)
+ local spec = {
+ p = true,
+ c = column,
+ r = true,
+ x = true,
+ y = true,
+ h = h ~= 0 and h or nil,
+ d = d ~= 0 and d or nil,
+ n = nofparagraphs > 0 and nofparagraphs or nil,
+ r2l = texgetcount("inlinelefttoright") == 1 or nil,
+ }
+ tobesaved[name] = spec
+ ctx_latelua { action = enhance, specification = spec }
+ end
+}
-scanners.dosetpositionstrutkind = function() -- name
- local name = scanstring()
- local kind = scaninteger()
- local box = getbox("strutbox")
- local w, h, d = getwhd(box)
- local spec = {
- k = kind,
- p = true,
- c = column,
- r = true,
- x = true,
- y = true,
- h = h ~= 0 and h or nil,
- d = d ~= 0 and d or nil,
- n = nofparagraphs > 0 and nofparagraphs or nil,
- r2l = texgetcount("inlinelefttoright") == 1 or nil,
- }
- tobesaved[name] = spec
- ctx_latelua { action = enhance, specification = spec }
-end
+implement {
+ name = "dosetpositionstrutkind",
+ arguments = { "string", "integer" },
+ actions = function(name,kind)
+ local box = getbox("strutbox")
+ local w, h, d = getwhd(box)
+ local spec = {
+ k = kind,
+ p = true,
+ c = column,
+ r = true,
+ x = true,
+ y = true,
+ h = h ~= 0 and h or nil,
+ d = d ~= 0 and d or nil,
+ n = nofparagraphs > 0 and nofparagraphs or nil,
+ r2l = texgetcount("inlinelefttoright") == 1 or nil,
+ }
+ tobesaved[name] = spec
+ ctx_latelua { action = enhance, specification = spec }
+ end
+}
function jobpositions.getreserved(tag,n)
if tag == v_column then
@@ -990,166 +1021,222 @@ jobpositions.columnofpos = columnofpos
-- interface
-scanners.replacepospxywhd = function() -- name page x y w h d
- collected[scanstring()] = {
- p = scaninteger(),
- x = scandimen(),
- y = scandimen(),
- w = scandimen(),
- h = scandimen(),
- d = scandimen(),
- }
-end
+implement {
+ name = "replacepospxywhd",
+ arguments = { "string", "integer", "dimen", "dimen", "dimen", "dimen", "dimen" },
+ actions = function(name,page,x,y,w,h,d)
+ collected[name] = {
+ p = page,
+ x = x,
+ y = y,
+ w = w,
+ h = h,
+ d = d,
+ }
+ end
+}
-scanners.copyposition = function() -- target source
- collected[scanstring()] = collected[scanstring()]
-end
+implement {
+ name = "copyposition",
+ arguments = "2 strings",
+ actions = function(target,source)
+ collected[target] = collected[source]
+ end
+}
-scanners.MPp = function() -- name
- local jpi = collected[scanstring()]
- if jpi then
- local p = jpi.p
- if p and p ~= true then
- context(p)
- return
+implement {
+ name = "MPp",
+ arguments = "string",
+ actions = function(name)
+ local jpi = collected[name]
+ if jpi then
+ local p = jpi.p
+ if p and p ~= true then
+ context(p)
+ return
+ end
end
+ context('0')
end
- context('0')
-end
+}
-scanners.MPx = function() -- name
- local jpi = collected[scanstring()]
- if jpi then
- local x = jpi.x
- if x and x ~= true and x ~= 0 then
- context("%.5Fpt",x*pt)
- return
+implement {
+ name = "MPx",
+ arguments = "string",
+ actions = function(name)
+ local jpi = collected[name]
+ if jpi then
+ local x = jpi.x
+ if x and x ~= true and x ~= 0 then
+ context("%.5Fpt",x*pt)
+ return
+ end
end
+ context('0pt')
end
- context('0pt')
-end
+}
-scanners.MPy = function() -- name
- local jpi = collected[scanstring()]
- if jpi then
- local y = jpi.y
- if y and y ~= true and y ~= 0 then
- context("%.5Fpt",y*pt)
- return
+implement {
+ name = "MPy",
+ arguments = "string",
+ actions = function(name)
+ local jpi = collected[name]
+ if jpi then
+ local y = jpi.y
+ if y and y ~= true and y ~= 0 then
+ context("%.5Fpt",y*pt)
+ return
+ end
end
+ context('0pt')
end
- context('0pt')
-end
+}
-scanners.MPw = function() -- name
- local jpi = collected[scanstring()]
- if jpi then
- local w = jpi.w
- if w and w ~= 0 then
- context("%.5Fpt",w*pt)
- return
+implement {
+ name = "MPw",
+ arguments = "string",
+ actions = function(name)
+ local jpi = collected[name]
+ if jpi then
+ local w = jpi.w
+ if w and w ~= 0 then
+ context("%.5Fpt",w*pt)
+ return
+ end
end
+ context('0pt')
end
- context('0pt')
-end
+}
-scanners.MPh = function() -- name
- local jpi = collected[scanstring()]
- if jpi then
- local h = jpi.h
- if h and h ~= 0 then
- context("%.5Fpt",h*pt)
- return
+implement {
+ name = "MPh",
+ arguments = "string",
+ actions = function(name)
+ local jpi = collected[name]
+ if jpi then
+ local h = jpi.h
+ if h and h ~= 0 then
+ context("%.5Fpt",h*pt)
+ return
+ end
end
+ context('0pt')
end
- context('0pt')
-end
+}
-scanners.MPd = function() -- name
- local jpi = collected[scanstring()]
- if jpi then
- local d = jpi.d
- if d and d ~= 0 then
- context("%.5Fpt",d*pt)
- return
+implement {
+ name = "MPd",
+ arguments = "string",
+ actions = function(name)
+ local jpi = collected[name]
+ if jpi then
+ local d = jpi.d
+ if d and d ~= 0 then
+ context("%.5Fpt",d*pt)
+ return
+ end
end
+ context('0pt')
end
- context('0pt')
-end
+}
-scanners.MPxy = function() -- name
- local jpi = collected[scanstring()]
- if jpi then
- context('(%.5Fpt,%.5Fpt)',
- jpi.x*pt,
- jpi.y*pt
- )
- else
- context('(0,0)')
+implement {
+ name = "MPxy",
+ arguments = "string",
+ actions = function(name)
+ local jpi = collected[name]
+ if jpi then
+ context('(%.5Fpt,%.5Fpt)',
+ jpi.x*pt,
+ jpi.y*pt
+ )
+ else
+ context('(0,0)')
+ end
end
-end
+}
-scanners.MPwhd = function() -- name
- local jpi = collected[scanstring()]
- if jpi then
- local w = jpi.w or 0
- local h = jpi.h or 0
- local d = jpi.d or 0
- if w ~= 0 or h ~= 0 or d ~= 0 then
- context("%.5Fpt,%.5Fpt,%.5Fpt",w*pt,h*pt,d*pt)
- return
+implement {
+ name = "MPwhd",
+ arguments = "string",
+ actions = function(name)
+ local jpi = collected[name]
+ if jpi then
+ local w = jpi.w or 0
+ local h = jpi.h or 0
+ local d = jpi.d or 0
+ if w ~= 0 or h ~= 0 or d ~= 0 then
+ context("%.5Fpt,%.5Fpt,%.5Fpt",w*pt,h*pt,d*pt)
+ return
+ end
end
+ context('0pt,0pt,0pt')
end
- context('0pt,0pt,0pt')
-end
+}
-scanners.MPll = function() -- name
- local jpi = collected[scanstring()]
- if jpi then
- context('(%.5Fpt,%.5Fpt)',
- jpi.x *pt,
- (jpi.y-jpi.d)*pt
- )
- else
- context('(0,0)') -- for mp only
+implement {
+ name = "MPll",
+ arguments = "string",
+ actions = function(name)
+ local jpi = collected[name]
+ if jpi then
+ context('(%.5Fpt,%.5Fpt)',
+ jpi.x *pt,
+ (jpi.y-jpi.d)*pt
+ )
+ else
+ context('(0,0)') -- for mp only
+ end
end
-end
+}
-scanners.MPlr = function() -- name
- local jpi = collected[scanstring()]
- if jpi then
- context('(%.5Fpt,%.5Fpt)',
- (jpi.x + jpi.w)*pt,
- (jpi.y - jpi.d)*pt
- )
- else
- context('(0,0)') -- for mp only
+implement {
+ name = "MPlr",
+ arguments = "string",
+ actions = function(name)
+ local jpi = collected[name]
+ if jpi then
+ context('(%.5Fpt,%.5Fpt)',
+ (jpi.x + jpi.w)*pt,
+ (jpi.y - jpi.d)*pt
+ )
+ else
+ context('(0,0)') -- for mp only
+ end
end
-end
+}
-scanners.MPur = function() -- name
- local jpi = collected[scanstring()]
- if jpi then
- context('(%.5Fpt,%.5Fpt)',
- (jpi.x + jpi.w)*pt,
- (jpi.y + jpi.h)*pt
- )
- else
- context('(0,0)') -- for mp only
+implement {
+ name = "MPur",
+ arguments = "string",
+ actions = function(name)
+ local jpi = collected[name]
+ if jpi then
+ context('(%.5Fpt,%.5Fpt)',
+ (jpi.x + jpi.w)*pt,
+ (jpi.y + jpi.h)*pt
+ )
+ else
+ context('(0,0)') -- for mp only
+ end
end
-end
+}
-scanners.MPul = function() -- name
- local jpi = collected[scanstring()]
- if jpi then
- context('(%.5Fpt,%.5Fpt)',
- jpi.x *pt,
- (jpi.y + jpi.h)*pt
- )
- else
- context('(0,0)') -- for mp only
+implement {
+ name = "MPul",
+ arguments = "string",
+ actions = function(name)
+ local jpi = collected[name]
+ if jpi then
+ context('(%.5Fpt,%.5Fpt)',
+ jpi.x *pt,
+ (jpi.y + jpi.h)*pt
+ )
+ else
+ context('(0,0)') -- for mp only
+ end
end
-end
+}
local function MPpos(id)
local jpi = collected[id]
@@ -1170,53 +1257,67 @@ local function MPpos(id)
context('0,0,0,0,0,0') -- for mp only
end
-scanners.MPpos = function() -- name
- MPpos(scanstring())
-end
+implement {
+ name = "MPpos",
+ arguments = "string",
+ actions = MPpos
+}
-scanners.MPn = function() -- name
- local jpi = collected[scanstring()]
- if jpi then
- local n = jpi.n
- if n then
- context(n)
- return
+implement {
+ name = "MPn",
+ arguments = "string",
+ actions = function(name)
+ local jpi = collected[name]
+ if jpi then
+ local n = jpi.n
+ if n then
+ context(n)
+ return
+ end
end
+ context(0)
end
- context(0)
-end
+}
-scanners.MPc = function() -- name
- local jpi = collected[scanstring()]
- if jpi then
- local c = jpi.c
- if c and c ~= true then
- context(c)
- return
+implement {
+ name = "MPc",
+ arguments = "string",
+ actions = function(name)
+ local jpi = collected[name]
+ if jpi then
+ local c = jpi.c
+ if c and c ~= true then
+ context(c)
+ return
+ end
end
+ context('0') -- okay ?
end
- context('0') -- okay ?
-end
+}
-scanners.MPr = function() -- name
- local jpi = collected[scanstring()]
- if jpi then
- local r = jpi.r
- if r and r ~= true then
- context(r)
- return
- end
- local p = jpi.p
- if p then
- context("page:" .. p)
+implement {
+ name = "MPr",
+ arguments = "string",
+ actions = function(name)
+ local jpi = collected[name]
+ if jpi then
+ local r = jpi.r
+ if r and r ~= true then
+ context(r)
+ return
+ end
+ local p = jpi.p
+ if p then
+ context("page:" .. p)
+ end
end
end
-end
+}
-local function MPpardata(n)
- local t = collected[n]
+local function MPpardata(id)
+ local t = collected[id]
if not t then
- local tag = f_p_tag(n)
+ local tag = f_p_tag(id)
t = collected[tag]
end
if t then
@@ -1233,157 +1334,213 @@ local function MPpardata(n)
end
end
-scanners.MPpardata = function() -- name
- MPpardata(scanstring())
-end
+implement {
+ name = "MPpardata",
+ arguments = "string",
+ actions = MPpardata
+}
-scanners.MPposset = function() -- name (special helper, used in backgrounds)
- local name = scanstring()
- local b = f_b_tag(name)
- local e = f_e_tag(name)
- local w = f_w_tag(name)
- local p = f_p_tag(getparagraph(b))
- MPpos(b) context(",") MPpos(e) context(",") MPpos(w) context(",") MPpos(p) context(",") MPpardata(p)
-end
+implement {
+ name = "MPposset",
+ arguments = "string",
+ actions = function(name)
+ local b = f_b_tag(name)
+ local e = f_e_tag(name)
+ local w = f_w_tag(name)
+ local p = f_p_tag(getparagraph(b))
+ MPpos(b) context(",") MPpos(e) context(",") MPpos(w) context(",") MPpos(p) context(",") MPpardata(p)
+ end
+}
-scanners.MPls = function() -- name
- local jpi = collected[scanstring()]
- if jpi then
- context("%.5Fpt",jpi.ls*pt)
- else
- context("0pt")
+implement {
+ name = "MPls",
+ arguments = "string",
+ actions = function(name)
+ local jpi = collected[name]
+ if jpi then
+ context("%.5Fpt",jpi.ls*pt)
+ else
+ context("0pt")
+ end
end
-end
+}
-scanners.MPrs = function() -- name
- local jpi = collected[scanstring()]
- if jpi then
- context("%.5Fpt",jpi.rs*pt)
- else
- context("0pt")
+implement {
+ name = "MPrs",
+ arguments = "string",
+ actions = function(name)
+ local jpi = collected[name]
+ if jpi then
+ context("%.5Fpt",jpi.rs*pt)
+ else
+ context("0pt")
+ end
end
-end
+}
local splitter = lpeg.tsplitat(",")
-scanners.MPplus = function() -- name n default
- local jpi = collected[scanstring()]
- local n = scaninteger()
- local default = scanstring()
- if jpi then
- local e = jpi.e
- if e then
- local split = jpi.split
- if not split then
- split = lpegmatch(splitter,jpi.e)
- jpi.split = split
+implement {
+ name = "MPplus",
+ arguments = { "string", "integer", "string" },
+ actions = function(name,n,default)
+ local jpi = collected[name]
+ if jpi then
+ local e = jpi.e
+ if e then
+ local split = jpi.split
+ if not split then
+ split = lpegmatch(splitter,jpi.e)
+ jpi.split = split
+ end
+ context(split[n] or default)
+ return
end
- context(split[n] or default)
- return
end
+ context(default)
end
- context(default)
-end
+}
-scanners.MPrest = function() -- name default
- local jpi = collected[scanstring()]
- local default = scanstring()
- context(jpi and jpi.e or default)
-end
+implement {
+ name = "MPrest",
+ arguments = { "string", "string" },
+ actions = function(name,default)
+ local jpi = collected[name]
+ context(jpi and jpi.e or default)
+ end
+}
-scanners.MPxywhd = function() -- name
- local jpi = collected[scanstring()]
- if jpi then
- context("%.5Fpt,%.5Fpt,%.5Fpt,%.5Fpt,%.5Fpt",
- jpi.x*pt,
- jpi.y*pt,
- jpi.w*pt,
- jpi.h*pt,
- jpi.d*pt
- )
- else
- context("0,0,0,0,0") -- for mp only
+implement {
+ name = "MPxywhd",
+ arguments = "string",
+ actions = function(name)
+ local jpi = collected[name]
+ if jpi then
+ context("%.5Fpt,%.5Fpt,%.5Fpt,%.5Fpt,%.5Fpt",
+ jpi.x*pt,
+ jpi.y*pt,
+ jpi.w*pt,
+ jpi.h*pt,
+ jpi.d*pt
+ )
+ else
+ context("0,0,0,0,0") -- for mp only
+ end
end
-end
+}
local doif = commands.doif
local doifelse = commands.doifelse
-scanners.doifelseposition = function() -- name
- doifelse(collected[scanstring()])
-end
-
-scanners.doifposition = function() -- name
- doif(collected[scanstring()])
-end
+implement {
+ name = "doifelseposition",
+ arguments = "string",
+ actions = function(name)
+ doifelse(collected[name])
+ end
+}
--- local ctx_iftrue = context.protected.cs.iftrue
--- local ctx_iffalse = context.protected.cs.iffalse
---
--- scanners.ifknownposition = function() -- name
--- (collected[scanstring()] and ctx_iftrue or ctx_iffalse)()
--- end
-
-scanners.doifelsepositiononpage = function() -- name page -- probably always realpageno
- local c = collected[scanstring()]
- local p = scaninteger()
- doifelse(c and c.p == p)
-end
+implement {
+ name = "doifposition",
+ arguments = "string",
+ actions = function(name)
+ doif(collected[name])
+ end
+}
-scanners.doifelseoverlapping = function() -- one two
- doifelse(overlapping(scanstring(),scanstring()))
-end
+implement {
+ name = "doifelsepositiononpage",
+ arguments = { "string", "integer" },
+ actions = function(name,p)
+ local c = collected[name]
+ doifelse(c and c.p == p)
+ end
+}
-scanners.doifelsepositionsonsamepage = function() -- list
- doifelse(onsamepage(scanstring()))
-end
+implement {
+ name = "doifelseoverlapping",
+ arguments = { "string", "string" },
+ actions = function(one,two)
+ doifelse(overlapping(one,two))
+ end
+}
-scanners.doifelsepositionsonthispage = function() -- list
- doifelse(onsamepage(scanstring(),tostring(texgetcount("realpageno"))))
-end
+implement {
+ name = "doifelsepositionsonsamepage",
+ arguments = "string",
+ actions = function(list)
+ doifelse(onsamepage(list))
+ end
+}
--- scanners.columnofpos = function()
--- context(columnofpos(scaninteger(),scandimen())
--- end
+implement {
+ name = "doifelsepositionsonthispage",
+ arguments = "string",
+ actions = function(list)
+ doifelse(onsamepage(list,tostring(texgetcount("realpageno"))))
+ end
+}
-scanners.doifelsepositionsused = function()
- doifelse(next(collected))
-end
+implement {
+ name = "doifelsepositionsused",
+ actions = function()
+ doifelse(next(collected))
+ end
+}
-scanners.markregionbox = function() -- box
- markregionbox(scaninteger())
-end
+implement {
+ name = "markregionbox",
+ arguments = "integer",
+ actions = markregionbox
+}
-scanners.setregionbox = function() -- box
- setregionbox(scaninteger())
-end
+implement {
+ name = "setregionbox",
+ arguments = "integer",
+ actions = setregionbox
+}
-scanners.markregionboxtagged = function() -- box tag
- markregionbox(scaninteger(),scanstring())
-end
+implement {
+ name = "markregionboxtagged",
+ arguments = { "integer", "string" },
+ actions = markregionbox
+}
-scanners.markregionboxtaggedn = function() -- box tag n
- markregionbox(scaninteger(),scanstring(),nil,
- nil,nil,nil,nil,nil,scaninteger())
-end
+implement {
+ name = "markregionboxtaggedn",
+ arguments = { "integer", "string", "integer" },
+ actions = function(box,tag,n)
+ markregionbox(box,tag,nil,nil,nil,nil,nil,nil,n)
+ end
+}
-scanners.setregionboxtagged = function() -- box tag
- setregionbox(scaninteger(),scanstring())
-end
+implement {
+ name = "setregionboxtagged",
+ arguments = { "integer", "string" },
+ actions = setregionbox
+}
-scanners.markregionboxcorrected = function() -- box tag
- markregionbox(scaninteger(),scanstring(),true)
-end
+implement {
+ name = "markregionboxcorrected",
+ arguments = { "integer", "string", true },
+ actions = markregionbox
+}
-scanners.markregionboxtaggedkind = function() -- box tag kind
- markregionbox(scaninteger(),scanstring(),nil,
- scaninteger(),scandimen(),scandimen(),scandimen(),scandimen())
-end
+implement {
+ name = "markregionboxtaggedkind",
+ arguments = { "integer", "string", "integer", "dimen", "dimen", "dimen", "dimen" },
+ actions = function(box,tag,n,d1,d2,d3,d4)
+ markregionbox(box,tag,nil,n,d1,d2,d3,d4)
+ end
+}
-scanners.reservedautoregiontag = function()
- nofregions = nofregions + 1
- context(f_region(nofregions))
-end
+implement {
+ name = "reservedautoregiontag",
+ actions = function()
+ nofregions = nofregions + 1
+ context(f_region(nofregions))
+ end
+}
-- statistics (at least for the moment, when testing)
@@ -1409,7 +1566,6 @@ end)
-- We support the low level positional commands too:
local newsavepos = nodes.pool.savepos
-local implement = interfaces.implement
implement { name = "savepos", actions = function() context(newsavepos()) end }
implement { name = "lastxpos", actions = function() context(gethpos()) end }
diff --git a/tex/context/base/mkiv/back-res.lua b/tex/context/base/mkiv/back-res.lua
index 2ca4a5ac8..4ee6d15d3 100644
--- a/tex/context/base/mkiv/back-res.lua
+++ b/tex/context/base/mkiv/back-res.lua
@@ -19,7 +19,6 @@ local scandimension = scanners.dimension
local scanword = scanners.word
local scanwhd = scanners.whd
-local scanners = interfaces.scanners
local implement = interfaces.implement
local constants = interfaces.constants
local variables = interfaces.variables
diff --git a/tex/context/base/mkiv/buff-ini.lua b/tex/context/base/mkiv/buff-ini.lua
index e4f01c03f..b4290f8b1 100644
--- a/tex/context/base/mkiv/buff-ini.lua
+++ b/tex/context/base/mkiv/buff-ini.lua
@@ -46,8 +46,6 @@ local getcommand = token.get_command
local getcsname = token.get_csname
local getnextchar = token.get_next_char
-local scanners = interfaces.scanners
-
local variables = interfaces.variables
local settings_to_array = utilities.parsers.settings_to_array
local formatters = string.formatters
@@ -623,21 +621,26 @@ end
tokens.pickup = pickup
-scanners.pickupbuffer = function()
- local name = scanstring()
- local start = scanstring()
- local stop = scanstring()
- local finish = scanstring()
- local catcodes = scaninteger()
- local doundent = scanboolean()
- local data = pickup(start,stop)
- if doundent or (autoundent and doundent == nil) then
- data = undent(data)
- end
- buffers.assign(name,data,catcodes)
- -- context[finish]()
- context(finish)
-end
+implement {
+ name = "pickupbuffer",
+ actions = function()
+ -- let's pickup all here (no arguments)
+ local name = scanstring()
+ local start = scanstring()
+ local stop = scanstring()
+ local finish = scanstring()
+ local catcodes = scaninteger()
+ local doundent = scanboolean()
+ -- could be a scanner:
+ local data = pickup(start,stop)
+ if doundent or (autoundent and doundent == nil) then
+ data = undent(data)
+ end
+ buffers.assign(name,data,catcodes)
+ -- context[finish]()
+ context(finish)
+ end
+}
local function savebuffer(list,name,prefix) -- name is optional
if not list or list == "" then
diff --git a/tex/context/base/mkiv/buff-ver.lua b/tex/context/base/mkiv/buff-ver.lua
index 2bf663704..ccb8ab0df 100644
--- a/tex/context/base/mkiv/buff-ver.lua
+++ b/tex/context/base/mkiv/buff-ver.lua
@@ -588,7 +588,7 @@ end
local function realign(lines,strip) -- "yes", <number>
local n
if strip == v_yes then
- n = math.huge
+ n = 0xFFFF
for i=1, #lines do
local spaces = find(lines[i],"%S") -- can be lpeg
if not spaces then
diff --git a/tex/context/base/mkiv/buff-ver.mkiv b/tex/context/base/mkiv/buff-ver.mkiv
index 24aaa57d3..a3c27977f 100644
--- a/tex/context/base/mkiv/buff-ver.mkiv
+++ b/tex/context/base/mkiv/buff-ver.mkiv
@@ -1016,4 +1016,8 @@
\stopcontextdefinitioncode
+%D This is \type {\asciimode} without the double comment hackery:
+
+\unexpanded\def\literalmode{\setcatcodetable\txtcatcodes}
+
\protect \endinput
diff --git a/tex/context/base/mkiv/cldf-ini.lua b/tex/context/base/mkiv/cldf-ini.lua
index 8e2d6f051..9569cf357 100644
--- a/tex/context/base/mkiv/cldf-ini.lua
+++ b/tex/context/base/mkiv/cldf-ini.lua
@@ -26,7 +26,7 @@ if not modules then modules = { } end modules ['cldf-ini'] = {
-- 0.651 local foo = getcount("ctxcatcodes")
-- 0.408 local foo = getcount(ctxcatcodes) -- local ctxcatcodes = tex.iscount("ctxcatcodes")
--- maybe:  (escape) or 0x2061 (apply function) or 0x2394 (software function ⎔)
+-- maybe:  (escape) or 0x2061 (apply function) or 0x2394 (software function ⎔) (old)
-- note : tex.print == line with endlinechar appended
-- todo : context("%bold{total: }%s",total)
-- todo : context.documentvariable("title")
@@ -58,6 +58,20 @@ if not modules then modules = { } end modules ['cldf-ini'] = {
-- time (for the better or worse). There have been no fundamental changes for many years
-- and performance has not changed much either.
+-- The code here has evolved over time, and was already present in the early versions of
+-- mkiv. However, it got adapted when feature were added to luatex, like the ability to
+-- "print" nodes and later tokens. We use to have control over the method used (if only
+-- for testing) but the older code has been removed now. The history is in the archives.
+-- These were the controls:
+
+-- local tokenflushmode = true
+-- local nodeflushmode = true
+-- local scannerdefmode = true
+-- local maxflushnodeindex = 0x10FFFF - 1
+
+-- In earlier experiments a function tables was referred to as lua.calls and the primitive
+-- \luafunctions was \luacall and we used our own implementation of a function table (more
+-- indirectness).
local format, stripstring = string.format, string.strip
local next, type, tostring, tonumber, unpack, select, rawset = next, type, tostring, tonumber, unpack, select, rawset
@@ -85,9 +99,6 @@ local texprint = tex.print -- each arg a separate line (not last in
----- texwrite = tex.write -- all 'space' and 'character'
local texgetcount = tex.getcount
--- local function texsprint(...) print("sprint",...) tex.sprint(...) end
--- local function texprint (...) print("print", ...) tex.print (...) end
-
local isnode = node.is_node
local writenode = node.write
local copynodelist = node.copy_list
@@ -118,19 +129,6 @@ local report_cld = logs.reporter("cld","stack")
local processlines = true -- experiments.register("context.processlines", function(v) processlines = v end)
-local tokenflushmode = true
-local nodeflushmode = true
-local scannerdefmode = true
-local maxflushnodeindex = 0x10FFFF - 1
-
--- tokenflushmode = false
--- nodeflushmode = false
--- scannerdefmode = false
-
--- In earlier experiments a function tables was referred to as lua.calls and the
--- primitive \luafunctions was \luacall and we used our own implementation of
--- a function table (more indirectness).
-
local trialtypesettingstate = createtoken("trialtypesettingstate").index
function context.trialtypesetting()
@@ -142,7 +140,9 @@ local showstackusage = false
trackers.register("context.stack",function(v) showstackusage = v end)
-local freed, nofused, noffreed = { }, 0, 0
+local freed = { }
+local nofused = 0
+local noffreed = 0
local usedstack = function()
return nofused, noffreed
@@ -208,11 +208,11 @@ local initex = environment.initex
storage.register("storage/storedfunctions", storedfunctions, "storage.storedfunctions")
local f_resolve = nil
-local p_resolve = ((1-lpegP("."))^1 / function(s) f_resolve = f_resolve[s] end * lpegP(".")^0)^1
+local p_resolve = ((1-lpegP("."))^1 / function(s) f_resolve = f_resolve[s] end * lpegP(".")^0)^1
local function resolvestoredfunction(str)
if type(str) == "string" then
- f_resolve = global
+ f_resolve = global -- namespace
lpegmatch(p_resolve,str)
return f_resolve
else
@@ -257,9 +257,11 @@ else
end
end
-local registerfunction = function(f,direct) -- either f=code or f=namespace,direct=name
- local slot, func
- if noffreed > 0 then
+local registerfunction = function(f,direct,slot) -- either f=code or f=namespace,direct=name
+ local func
+ if slot then
+ -- already used
+ elseif noffreed > 0 then
slot = freed[noffreed]
freed[noffreed] = nil
noffreed = noffreed - 1
@@ -269,12 +271,8 @@ local registerfunction = function(f,direct) -- either f=code or f=namespace,dire
end
if direct then
if initex then
- func = function(...)
- expose(slot,f,...)
- end
- if initex then
- storedfunctions[slot] = f
- end
+ func = function(...) expose(slot,f,...) end
+ storedfunctions[slot] = f
else
func = resolvestoredfunction(f)
end
@@ -357,73 +355,46 @@ do
end
--- so far
-
--- The next hack is a convenient way to define scanners at the Lua end and
--- get them available at the TeX end. There is some dirty magic needed to
--- prevent overload during format loading.
+-- The next hack is a convenient way to define scanners at the Lua end and get them
+-- available at the TeX end. There is some dirty magic needed to prevent overload
+-- during format loading. Nowadays we prefer to use the slightly less efficient way
+-- of defining interfaces using the implementer. There is a little more overhead in
+-- defining as well as runtime overhead, but we accept that.
-- interfaces.scanners.foo = function() context("[%s]",tokens.scanners.string()) end : \scan_foo
-interfaces.storedscanners = interfaces.storedscanners or { }
-local storedscanners = interfaces.storedscanners
+local storedscanners = interfaces.storedscanners or { }
+local interfacescanners = { }
+local privatenamespace = "clf_"
-storage.register("interfaces/storedscanners", storedscanners, "interfaces.storedscanners")
+interfaces.storedscanners = storedscanners
-local interfacescanners = setmetatablenewindex(function(t,k,v)
- rawset(t,k,v)
- if storedscanners[k] then
- -- report_cld("warning: scanner %a is already set (mode 1a)",k)
- -- os.exit()
- -- \scan_<k> is already in the format
- -- report_cld("using interface scanner: %s",k)
- elseif scannerdefmode then
- -- report_cld("installing interface scanner: %s (mode 1b)",k)
- -- local n = registerfunction(interfaces.scanners[k],true)
- local n = registerfunction("interfaces.scanners."..k,true)
- storedscanners[k] = n
- local name = "clf_" .. k
- setluatoken(name,n,"global") -- todo : protected and "protected" or ""
- else
- -- report_cld("installing interface scanner: %s (mode 1c)",k)
- storedscanners[k] = true
- context("\\installctxscanner{clf_%s}{interfaces.scanners.%s}",k,k)
- end
- -- rawset(t,k,v)
-end)
+storage.register("interfaces/storedscanners", storedscanners, "interfaces.storedscanners")
-function interfaces.registerscanner(name,action,protected,public,value)
+local function registerscanner(name,action,protected,public,value)
rawset(interfacescanners,name,action)
- if storedscanners[name] then
- -- report_cld("warning: scanner %a is already set (mode 2a)",name)
- -- os.exit()
- -- \scan_<k> is already in the format
- -- report_cld("using interface scanner: %s",k)
- elseif scannerdefmode then
- -- report_cld("installing interface scanner: %s (mode 2b)",name)
- -- local n = registerfunction(action,true) -- todo
- local n = registerfunction("interfaces.scanners."..name,true)
- storedscanners[name] = n
- local name = public and name or ("clf_" .. name)
- setluatoken(name,n,"global",protected and "protected" or "",value and "value" or "")
- else
- storedscanners[name] = true
- -- report_cld("installing interface scanner: %s (mode 2c)",name)
- context("\\install%sctxscanner{%s%s}{interfaces.scanners.%s}",
- protected and "protected" or "",
- public and "" or "clf_",
- name,
- name
- )
- end
- -- rawset(interfacescanners,name,action)
+ local n = storedscanners[name]
+ n = registerfunction("interfaces.scanners."..name,true,n)
+ storedscanners[name] = n
+ name = public and name or (privatenamespace .. name)
+ setluatoken(name,n,"global",protected and "protected" or "",value and "value" or "")
end
+interfaces.registerscanner = registerscanner
+
+function interfaces.knownscanner(name)
+ return interfacescanners[name]
+end
+
+setmetatablenewindex(interfacescanners, function(t,k,v)
+ report_cld("don't register scanner %a directly",k)
+ -- registerscanner(k,v)
+end)
+
interfaces.scanners = storage.mark(interfacescanners)
-interfaces._ = interfaces.scanners
context.functions = {
- register = registerfunction,
+ register = function(qualifiedname) return registerfunction(qualifiedname) end, -- only one argument
unregister = unregisterfunction,
reserve = reservefunction,
known = knownfunctions,
@@ -448,7 +419,7 @@ function commands.ctxresetter(name) -- to be checked
return function()
if storedscanners[name] then
rawset(interfacescanners,name,dummy)
- context.resetctxscanner("clf_" .. name)
+ context.resetctxscanner(privatenamespace .. name)
end
end
end
@@ -540,25 +511,11 @@ local endstripper = beginstripper * lpegP(-1)
local justaspace = space * lpegCc("")
local justanewline = newline * lpegCc("")
-local function n_content(s)
- flush(contentcatcodes,s)
-end
-
-local function n_verbose(s)
- flush(vrbcatcodes,s)
-end
-
-local function n_endofline()
- flush(currentcatcodes," \r")
-end
-
-local function n_emptyline()
- flushdirect(currentcatcodes,"\r")
-end
-
-local function n_simpleline()
- flush(currentcatcodes," \r")
-end
+local function n_content (s) flush (contentcatcodes,s ) end
+local function n_verbose (s) flush (vrbcatcodes, s ) end
+local function n_endofline () flush (currentcatcodes," \r") end
+local function n_emptyline () flushdirect(currentcatcodes,"\r" ) end
+local function n_simpleline() flush (currentcatcodes," \r") end
local n_exception = ""
@@ -646,7 +603,7 @@ function context.newverbosehandler(specification) -- a special variant for e.g.
specification = specification or { }
--
local f_line = specification.line or function() flushdirect("\r") end
- local f_space = specification.space or function() flush(" ") end
+ local f_space = specification.space or function() flush (" ") end
local f_content = specification.content or n_verbose
local f_before = specification.before
local f_after = specification.after
@@ -700,20 +657,6 @@ function context.printlines(str,raw) -- todo: see if via file is useable
end
end
--- function context.printtable(t,separator) -- todo: see if via file is useable
--- if separator == nil or separator == true then
--- separator = "\r"
--- elseif separator == "" then
--- separator = false
--- end
--- for i=1,#t do
--- context(t[i]) -- we need to go through catcode handling
--- if separator then
--- context(separator)
--- end
--- end
--- end
-
function context.printtable(t,separator) -- todo: see if via file is useable
if separator == nil or separator == true then
separator = "\r"
@@ -730,22 +673,6 @@ end
local containseol = patterns.containseol
-local s_cldl_option_b = "[\\cldl"
-local s_cldl_option_f = "[\\cldl" -- add space (not needed)
-local s_cldl_option_e = "]"
-local s_cldl_option_s = "\\cldl"
------ s_cldl_option_d = "\\cldd"
-local s_cldl_option_d = s_cldl_option_s
-local s_cldl_argument_b = "{\\cldl"
-local s_cldl_argument_f = "{\\cldl "
-local s_cldl_argument_e = "}"
-
--- local s_cldl_option_b = "["
--- local s_cldl_option_f = "" -- add space (not needed)
--- local s_cldl_option_s = ""
--- local s_cldl_argument_b = "{"
--- local s_cldl_argument_f = "{ "
-
local t_cldl_luafunction = newtoken("luafunctioncall",0)
local lua_expandable_call_token_code = token.command_id and token.command_id("lua_expandable_call")
@@ -756,17 +683,12 @@ directives.register("context.sorthash",function(v)
end)
local function writer(parent,command,...) -- already optimized before call
-
if type(command) == "string" then -- for now
flush(currentcatcodes,command) -- todo: ctx|prt|texcatcodes
else
flush(command) -- todo: ctx|prt|texcatcodes
end
-
local direct = false
- -- local t = { ... }
- -- for i=1,#t do
- -- local ti = t[i]
for i=1,select("#",...) do
local ti = select(i,...)
if direct then
@@ -849,15 +771,7 @@ local function writer(parent,command,...) -- already optimized before call
local tj = ti[1]
if type(tj) == "function" then
tj = storefunction(tj)
- if tokenflushmode then
- -- if newtoken then
- flush(currentcatcodes,"[",newtoken(tj,lua_expandable_call_token_code),"]")
- -- else
- -- flush(currentcatcodes,"[",t_cldl_luafunction,tj,"]")
- -- end
- else
- flush(currentcatcodes,s_cldl_option_b,tj,s_cldl_option_e)
- end
+ flush(currentcatcodes,"[",newtoken(tj,lua_expandable_call_token_code),"]")
else
flush(currentcatcodes,"[",tj,"]")
end
@@ -867,15 +781,7 @@ local function writer(parent,command,...) -- already optimized before call
local tj = ti[j]
if type(tj) == "function" then
tj = storefunction(tj)
- if tokenflushmode then
- -- if newtoken then
- flush(currentcatcodes,"[",newtoken(tj,lua_expandable_call_token_code),j == tn and "]" or ",")
- -- else
- -- flush(currentcatcodes,"[",t_cldl_luafunction,tj,j == tn and "]" or ",")
- -- end
- else
- flush(currentcatcodes,s_cldl_option_s,tj,j == tn and "]" or ",")
- end
+ flush(currentcatcodes,"[",newtoken(tj,lua_expandable_call_token_code),j == tn and "]" or ",")
else
if j == tn then
flush(currentcatcodes,tj,"]")
@@ -888,15 +794,7 @@ local function writer(parent,command,...) -- already optimized before call
elseif typ == "function" then
-- todo: ctx|prt|texcatcodes
ti = storefunction(ti)
- if tokenflushmode then
- -- if newtoken then
- flush(currentcatcodes,"{",newtoken(ti,lua_expandable_call_token_code),"}")
- -- else
- -- flush(currentcatcodes,"{",t_cldl_luafunction,ti,"}")
- -- end
- else
- flush(currentcatcodes,s_cldl_argument_f,ti,s_cldl_argument_e)
- end
+ flush(currentcatcodes,"{",newtoken(ti,lua_expandable_call_token_code),"}")
elseif typ == "boolean" then
if ti then
flushdirect(currentcatcodes,"\r")
@@ -906,16 +804,7 @@ local function writer(parent,command,...) -- already optimized before call
elseif typ == "thread" then
report_context("coroutines not supported as we cannot yield across boundaries")
elseif isnode(ti) then -- slow | why {} here ?
- if nodeflushmode then
- local n = tonut(ti)
- if n <= maxflushnodeindex then
- flush(currentcatcodes,"{",ti,"}")
- else
- flush(currentcatcodes,s_cldl_argument_b,storenode(ti),s_cldl_argument_e)
- end
- else
- flush(currentcatcodes,s_cldl_argument_b,storenode(ti),s_cldl_argument_e)
- end
+ flush(currentcatcodes,"{",ti,"}")
else
local s = tostring(ti)
if s then
@@ -924,109 +813,47 @@ local function writer(parent,command,...) -- already optimized before call
report_context("error: %a gets a weird argument %a",command,ti)
end
end
--- else
--- local n = isnode(ti)
--- if n then
--- if nodeflushmode and n <= maxflushnodeindex then
--- flush(ti)
--- else
--- flush(currentcatcodes,s_cldl_argument_b,storenode(ti),s_cldl_argument_e)
--- end
--- else
--- report_context("error: %a gets a weird argument %a",command,ti)
--- end
--- end
+ -- else
+ -- local n = isnode(ti)
+ -- if n then
+ -- flush(ti)
+ -- else
+ -- report_context("error: %a gets a weird argument %a",command,ti)
+ -- end
end
end
end
-local core
+local toks = tokens.cache
+context.tokenizedcs = toks
-if tokenflushmode then -- combine them
-
- local toks = tokens.cache
-
- context.tokenizedcs = toks
-
- core = setmetatableindex(function(parent,k)
- local t
- local f = function(first,...)
- if not t then
- t = toks[k]
- end
- if first == nil then
- flush(t)
- else
- return writer(context,t,first,...)
- end
+local core = setmetatableindex(function(parent,k)
+ local t
+ local f = function(first,...)
+ if not t then
+ t = toks[k]
end
- parent[k] = f
- return f
- end)
-
--- core = setmetatableindex(function(parent,k)
--- local t
--- local f = function(first,...)
--- if not t then
--- t = toks[k]
--- end
--- local f = function(first,...)
--- if first == nil then
--- flush(t)
--- else
--- return writer(context,t,first,...)
--- end
--- end
--- parent[k] = f
--- if first == nil then
--- flush(t)
--- else
--- return writer(context,t,first,...)
--- end
--- end
--- parent[k] = f
--- return f
--- end)
-
- core.cs = setmetatableindex(function(parent,k)
- local t
- local f = function()
- if not t then
- t = toks[k]
- end
+ if first == nil then
flush(t)
+ else
+ return writer(context,t,first,...)
end
- parent[k] = f
- return f
- end)
-
-else
-
- context.tokenizedcs = false
-
- core = setmetatableindex(function(parent,k)
- local c = "\\" .. k
- local f = function(first,...)
- if first == nil then
- flush(currentcatcodes,c)
- else
- return writer(context,c,first,...)
- end
- end
- parent[k] = f
- return f
- end)
+ end
+ parent[k] = f
+ return f
+end)
- core.cs = setmetatableindex(function(parent,k)
- local c = "\\" .. k -- tostring(k)
- local f = function()
- flush(currentcatcodes,c)
+core.cs = setmetatableindex(function(parent,k)
+ local t
+ local f = function()
+ if not t then
+ t = toks[k]
end
- parent[k] = f
- return f
- end)
-
-end
+ flush(t)
+ end
+ parent[k] = f
+ return f
+end)
local indexer = function(parent,k)
if type(k) == "string" then
@@ -1122,15 +949,7 @@ local caller = function(parent,f,a,...)
elseif typ == "function" then
-- ignored: a ...
f = storefunction(f)
- if tokenflushmode then
- -- if newtoken then
- flush(currentcatcodes,"{",newtoken(f,lua_expandable_call_token_code),"}")
- -- else
- -- flush(currentcatcodes,"{",t_cldl_luafunction,f,"}")
- -- end
- else
- flush(currentcatcodes,s_cldl_argument_b,f,s_cldl_argument_e) -- todo: ctx|prt|texcatcodes
- end
+ flush(currentcatcodes,"{",newtoken(f,lua_expandable_call_token_code),"}")
elseif typ == "boolean" then
if f then
if a ~= nil then
@@ -1149,16 +968,7 @@ local caller = function(parent,f,a,...)
elseif typ == "thread" then
report_context("coroutines not supported as we cannot yield across boundaries")
elseif isnode(f) then -- slow
- if nodeflushmode then
- local n = tonut(f)
- if n <= maxflushnodeindex then
- flush(f)
- else
- flush(currentcatcodes,s_cldl_option_s,storenode(f)," ")
- end
- else
- flush(currentcatcodes,s_cldl_option_s,storenode(f)," ")
- end
+ flush(f)
else
local s = tostring(f)
if s then
@@ -1167,29 +977,20 @@ local caller = function(parent,f,a,...)
report_context("error: %a gets a weird argument %a","context",f)
end
end
--- else
--- local n = isnode(f)
--- if n then
--- if nodeflushmode and n <= maxflushnodeindex then
--- flush(f)
--- else
--- flush(currentcatcodes,s_cldl_option_s,storenode(f)," ")
--- end
--- else
--- report_context("error: %a gets a weird argument %a","context",f)
--- end
--- end
+ -- else
+ -- local n = isnode(f)
+ -- if n then
+ -- flush(f)
+ -- else
+ -- report_context("error: %a gets a weird argument %a","context",f)
+ -- end
end
end
context.nodes = { -- todo
store = storenode,
flush = function(n)
- if nodeflushmode and tonut(n) <= maxflushnodeindex then
- flush(n)
- else
- flush(currentcatcodes,d and s_cldl_option_d or s_cldl_option_s,storenode(n)," ")
- end
+ flush(n)
end,
}
@@ -1198,11 +999,7 @@ context.nuts = { -- todo
return storenode(tonut(n))
end,
flush = function(n,d)
- if nodeflushmode and n <= maxflushnodeindex then
- flush(tonode(n))
- else
- flush(currentcatcodes,d and s_cldl_option_d or s_cldl_option_s,storenode(tonode(n))," ")
- end
+ flush(tonode(n))
end,
}
@@ -1640,22 +1437,7 @@ function context.newindexer(catcodes,cmdcodes)
contentcatcodes = savedcatcodes
end
- if tokenflushmode then
-
- handler.cs = core.cs
-
- else
-
- handler.cs = setmetatableindex(function(parent,k)
- local c = "\\" .. k -- tostring(k)
- local f = function()
- flush(cmdcodes,c)
- end
- parent[k] = f
- return f
- end)
-
- end
+ handler.cs = core.cs
setmetatableindex(handler,indexer)
setmetatablecall (handler,caller)
@@ -1675,23 +1457,6 @@ do
-- formatted.command([catcodes,]format[,...])
--- local function formattedflush(parent,c,catcodes,fmt,...)
--- if type(catcodes) == "number" then
--- if fmt then
--- local result
--- pushcatcodes(catcodes)
--- result = writer(parent,c,formatters[fmt](...))
--- popcatcodes()
--- return result
--- else
--- -- no need to change content catcodes
--- return writer(parent,c)
--- end
--- else
--- return writer(parent,c,formatters[catcodes](fmt,...))
--- end
--- end
-
local function formattedflush(parent,c,catcodes,fmt,...)
if not catcodes then
return writer(parent,c)
@@ -1708,51 +1473,26 @@ do
end
end
- local indexer
-
- if tokenflushmode then -- combine them
-
- local toks = tokens.cache
+ local toks = tokens.cache
- indexer = function(parent,k)
- if type(k) == "string" then
- local t
- local f = function(first,...)
- if not t then
- t = toks[k]
- end
- if first == nil then
- flush(t)
- else
- return formattedflush(parent,t,first,...)
- end
+ local indexer = function(parent,k)
+ if type(k) == "string" then
+ local t
+ local f = function(first,...)
+ if not t then
+ t = toks[k]
end
- parent[k] = f
- return f
- else
- return context -- catch
- end
- end
-
- else
-
- indexer = function(parent,k)
- if type(k) == "string" then
- local c = "\\" .. k
- local f = function(first,...)
- if first == nil then
- flush(currentcatcodes,c)
- else
- return formattedflush(parent,c,first,...)
- end
+ if first == nil then
+ flush(t)
+ else
+ return formattedflush(parent,t,first,...)
end
- parent[k] = f
- return f
- else
- return context -- catch
end
+ parent[k] = f
+ return f
+ else
+ return context -- catch
end
-
end
-- formatted([catcodes,]format[,...])
diff --git a/tex/context/base/mkiv/cldf-int.lua b/tex/context/base/mkiv/cldf-int.lua
index 86420f422..d869f3154 100644
--- a/tex/context/base/mkiv/cldf-int.lua
+++ b/tex/context/base/mkiv/cldf-int.lua
@@ -313,18 +313,22 @@ else
end
function interfaces.tolist(t)
- local r = { }
- for i=1,#t do
- r[i] = t[i]
- end
- local n = #r
- for k,v in table.sortedhash(t) do
- if type(k) ~= "number" then
- n = n + 1
- r[n] = k .. "=" .. v
+ if t then
+ local r = { }
+ for i=1,#t do
+ r[i] = t[i]
+ end
+ local n = #r
+ for k,v in table.sortedhash(t) do
+ if type(k) ~= "number" then
+ n = n + 1
+ r[n] = k .. "=" .. v
+ end
end
+ return concat(r,", ")
+ else
+ return ""
end
- return concat(r,", ")
end
-- \startluacode
@@ -358,9 +362,9 @@ end
-- context.startnarrower()
-- end
--
--- local function stopmore(opt_1)
+-- local function stopmore()
-- context.stopnarrower()
--- context("stop more, options: %s",interfaces.tolist(opt_1))
+-- context("stop more")
-- context.stopnarrower()
-- end
--
diff --git a/tex/context/base/mkiv/cldf-lmt.lua b/tex/context/base/mkiv/cldf-lmt.lua
index ab25f962e..4855372fa 100644
--- a/tex/context/base/mkiv/cldf-lmt.lua
+++ b/tex/context/base/mkiv/cldf-lmt.lua
@@ -8,8 +8,9 @@ if not modules then modules = { } end modules ['cldf-lmt'] = {
local next, load = next, load
-local setmetatableindex = table.setmetatableindex
-local serialize = table.serialize
+local setmetatableindex = table.setmetatableindex
+local setmetatablenewindex = table.setmetatablenewindex
+local serialize = table.serialize
local random = math.random
local randomseed = math.randomseed
@@ -30,8 +31,12 @@ local scancardinal = scanners.luacardinal
local scannumber = scanners.luanumber
local scanargument = scanners.argument
local scantoken = scanners.token
+local scancsname = scanners.csname
+
local getindex = token.get_index
+
local texsetdimen = tex.setdimen
+local texget = tex.get
local values = tokens.values
local none_code = values.none
@@ -57,7 +62,7 @@ implement {
value = true,
actions = function(b)
local n = scanword()
- if b then
+ if b == "value" then
context("%.99g",floats[n] or 0)
else
floats[n] = scannumber(true)
@@ -72,7 +77,7 @@ implement {
value = true,
actions = function(b)
local n = scanword()
- if b then
+ if b == "value" then
context("%i",integers[n] or 0)
else
integers[n] = scaninteger(true)
@@ -86,7 +91,7 @@ implement {
value = true,
actions = function(b)
local n = scanword()
- if b then
+ if b == "value" then
return integer_code, integers[n] or 0
else
integers[n] = scancount(true)
@@ -100,7 +105,7 @@ implement {
value = true,
actions = function(b)
local n = scanword()
- if b then
+ if b == "value" then
return dimension_code, integers[n] or 0
else
integers[n] = scandimen(false,false,true)
@@ -114,8 +119,8 @@ implement {
value = true,
actions = function(b)
local n = scanword()
- if b then
- context("%d",cardinals[n] or 0)
+ if b == "value" then
+ context("%1.0f",cardinals[n] or 0)
else
cardinals[n] = scancardinal(true)
end
@@ -128,8 +133,8 @@ implement {
value = true,
actions = function(b)
local n = scanword()
- if b then
- context("%d",floats[n] or integers[n] or cardinals[n] or 0)
+ if b == "value" then
+ context("%N",floats[n] or integers[n] or cardinals[n] or 0) -- maybe %N
else
-- floats[n] = scanfloat(true)
floats[n] = scannumber(true)
@@ -142,7 +147,7 @@ implement {
public = true,
value = true,
actions = function(b)
- if b then
+ if b == "value" then
return integer_code, random(scaninteger(),scaninteger())
else
randomseed(scaninteger(true))
@@ -243,7 +248,7 @@ implement {
d = d[scaninteger()]
end
local x = scaninteger()
- if b then
+ if b == "value" then
local code = a.code
if code == float_code then
context("%.99g",d[x])
@@ -258,7 +263,6 @@ implement {
end,
}
-
implement {
name = "arrayequals",
public = true,
@@ -275,7 +279,7 @@ implement {
d = d[scaninteger()]
end
local x = scaninteger()
- if b then
+ if b == "value" then
return boolean_code, a.scanner() == d[x]
end
end
@@ -299,7 +303,7 @@ implement {
d = d[scaninteger()]
end
local x = scaninteger()
- if b then
+ if b == "value" then
local v = a.scanner()
local d = d[x]
if d < v then
@@ -379,7 +383,7 @@ implement {
public = true,
value = true,
actions = function(b)
- if b then
+ if b == "value" then
local how = scanword()
local what = scandimen()
if how then
@@ -417,7 +421,7 @@ local setdata = tokens.setdata
local report = logs.reporter("lua table")
------ ctxsprint = context.sprint
+local ctxsprint = context.sprint
-- we could have an extra one that collects all end of grouped actions
-- so that we dispose more in one go but it doesn's pay off
@@ -607,3 +611,109 @@ context.luatables = {
inspect = inspectluatable,
show = showluatables,
}
+
+-- Here's another mechanism ...
+
+local tables = { }
+local stack = setmetatableindex("table")
+
+interfaces.implement {
+ name = "droptablegroup",
+ public = true,
+ actions = function()
+ local g = texget("currentgrouplevel") -- todo: tex.getgrouplevel()
+ local s = stack[g]
+ if s then
+ for t, data in next, s do
+ for k, v in next, data do
+ t[k] = v
+ end
+ end
+ stack[g] = { }
+ end
+ end,
+}
+
+local ctx_atendofgroup = context.core.cs.atendofgroup
+local ctx_droptablegroup = context.core.cs.droptablegroup
+
+local function handletable(t,b,array)
+ if b == "value" then
+ local k = array and scaninteger() or scanargument()
+ local v = t[k]
+ if v then
+ context(v)
+ end
+ else
+ local data = scanargument()
+ data = load("return {" .. data .. "}")
+ if data then
+ data = data()
+ if data then
+ local l = t.level
+ local g = texget("currentgrouplevel") -- todo: tex.getgrouplevel()
+ local s = stack[g]
+ local d = s[t]
+ if not d then
+ d = { }
+ s[t] = d
+ ctx_atendofgroup()
+ ctx_droptablegroup()
+ end
+ for k, v in next, data do
+ if not d[k] then
+ d[k] = t[k]
+ end
+ t[k] = v
+ end
+ if b == "global" then
+ for k, v in next, stack do
+ local t = s[t]
+ if t then
+ for k, v in next, data do
+ if t[k] then
+ t[k] = nil
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+local function newtable(array)
+ local name = scancsname(true)
+ if not tables[name] then
+ local t = { }
+ tables[name] = t
+ interfaces.implement {
+ name = name,
+ public = true,
+ value = true,
+ actions = function(b)
+ handletable(t,b,array)
+ end,
+ }
+ else
+ -- already defined
+ end
+end
+
+implement {
+ name = "newhashedtable",
+ protected = true,
+ public = true,
+ actions = newtable,
+}
+
+implement {
+ name = "newindexedtable",
+ protected = true,
+ public = true,
+ actions = function() newtable(true) end,
+}
+
+context.hashedtables = setmetatableindex(function(t,k) return tables[k] end)
+context.indexedtables = context.hashedtables
diff --git a/tex/context/base/mkiv/cldf-scn.lua b/tex/context/base/mkiv/cldf-scn.lua
index 1e5fe221d..fc4ea1e4a 100644
--- a/tex/context/base/mkiv/cldf-scn.lua
+++ b/tex/context/base/mkiv/cldf-scn.lua
@@ -8,32 +8,35 @@ if not modules then modules = { } end modules ['cldf-scn'] = {
local load, type, tostring = load, type, tostring
-local formatters = string.formatters
-local char = string.char
-local concat = table.concat
+local formatters = string.formatters
+local char = string.char
+local concat = table.concat
-local lpegmatch = lpeg.match
-local p_unquoted = lpeg.Cs(lpeg.patterns.unquoted)
+local lpegmatch = lpeg.match
+local p_unquoted = lpeg.Cs(lpeg.patterns.unquoted)
-local f_action_f = formatters["action%s(%s)"]
-local f_action_s = formatters["local action%s = action[%s]"]
-local f_command = formatters["local action = tokens._action\n%\nt\nreturn function(%s) return %s end"]
+local f_action_f = formatters["action%s(%s)"]
+local f_action_s = formatters["local action%s = action[%s]"]
+local f_command = formatters["local action = tokens._action\n%\nt\nreturn function(%s) return %s end"]
-local interfaces = interfaces
-local commands = commands
-local scanners = interfaces.scanners
-local register = interfaces.registerscanner
+local interfaces = interfaces
+local commands = commands
+local register = interfaces.registerscanner
+local knownscanner = interfaces.knownscanner
-local compile = tokens.compile or function() end
-local presets = tokens.presets
+local compile = tokens.compile or function() end
+local presets = tokens.presets
-local dummy = function() end
+local dummy = function() end
-local report = logs.reporter("interfaces","implementor")
+local report = logs.reporter("interfaces","implementor")
function interfaces.implement(specification)
+ local name = specification.name
+ if name == "" then
+ name = nil
+ end
local actions = specification.actions
- local name = specification.name
local arguments = specification.arguments
local private = specification.scope == "private"
local onlyonce = specification.onlyonce
@@ -45,9 +48,6 @@ function interfaces.implement(specification)
end
return
end
- if name == "" then
- name = nil
- end
local p = arguments and presets[arguments]
if p then
arguments = p
@@ -74,8 +74,8 @@ function interfaces.implement(specification)
if not name then
return scanner
end
- if scanners[name] and not specification.overload then
- report("warning: 'scanners.%s' is redefined",name)
+ if knownscanner(name) and not specification.overload then
+ report("warning: interface scanner %a is overloaded",name)
end
register(name,scanner,specification.protected,specification.public,specification.value)
if private then
@@ -160,12 +160,3 @@ interfaces.defined = tokens.defined
interfaces.setmacro = tokens.setters.macro
interfaces.setcount = tokens.setters.count
interfaces.setdimen = tokens.setters.dimen
-
-interfaces.strings = table.setmetatableindex(function(t,k)
- local v = { }
- for i=1,k do
- v[i] = "string"
- end
- t[k] = v
- return v
-end)
diff --git a/tex/context/base/mkiv/colo-ini.mkxl b/tex/context/base/mkiv/colo-ini.mkxl
index 63d29d0a6..724316629 100644
--- a/tex/context/base/mkiv/colo-ini.mkxl
+++ b/tex/context/base/mkiv/colo-ini.mkxl
@@ -250,8 +250,8 @@
%D The following command is obsolete:
-\unexpanded\def\startcolorpage {\startcolor[\ifempty\maintextcolor\defaulttextcolor\else\maintextcolor\fi]}
-\unexpanded\def\stopcolorpage {\stopcolor}
+\unexpanded\def\startcolorpage{\startcolor[\ifempty\maintextcolor\defaulttextcolor\else\maintextcolor\fi]}
+\unexpanded\def\stopcolorpage {\stopcolor}
\unexpanded\def\getcolorattributevalue#1#2% obsolete, use \thecolorattribute instead ...
{\begingroup
diff --git a/tex/context/base/mkiv/cont-new.mkiv b/tex/context/base/mkiv/cont-new.mkiv
index bdee367d1..3b01c297e 100644
--- a/tex/context/base/mkiv/cont-new.mkiv
+++ b/tex/context/base/mkiv/cont-new.mkiv
@@ -13,7 +13,7 @@
% \normalend % uncomment this to get the real base runtime
-\newcontextversion{2020.06.20 13:33}
+\newcontextversion{2020.06.25 10:55}
%D This file is loaded at runtime, thereby providing an excellent place for hacks,
%D patches, extensions and new features. There can be local overloads in cont-loc
diff --git a/tex/context/base/mkiv/context.mkiv b/tex/context/base/mkiv/context.mkiv
index f5d02a708..bbefc17e6 100644
--- a/tex/context/base/mkiv/context.mkiv
+++ b/tex/context/base/mkiv/context.mkiv
@@ -45,7 +45,7 @@
%D {YYYY.MM.DD HH:MM} format.
\edef\contextformat {\jobname}
-\edef\contextversion{2020.06.20 13:33}
+\edef\contextversion{2020.06.25 10:55}
\edef\contextkind {beta}
%D Kind of special:
diff --git a/tex/context/base/mkiv/context.mkxl b/tex/context/base/mkiv/context.mkxl
index e69d387f2..45a8e2f2f 100644
--- a/tex/context/base/mkiv/context.mkxl
+++ b/tex/context/base/mkiv/context.mkxl
@@ -29,7 +29,7 @@
%D {YYYY.MM.DD HH:MM} format.
\edef\contextformat {\jobname}
-\edef\contextversion{2020.06.20 13:33}
+\edef\contextversion{2020.06.25 10:55}
\edef\contextkind {beta}
%D Kind of special:
diff --git a/tex/context/base/mkiv/file-mod.lua b/tex/context/base/mkiv/file-mod.lua
index 10a187178..c10e557c7 100644
--- a/tex/context/base/mkiv/file-mod.lua
+++ b/tex/context/base/mkiv/file-mod.lua
@@ -246,18 +246,16 @@ function environment.useluamodule(list)
end
end
-local strings = interfaces.strings
-
implement {
name = "usemodules",
actions = environment.usemodules,
- arguments = strings[2]
+ arguments = "2 strings",
}
implement {
name = "doifelseolderversion",
actions = function(one,two) commands.doifelse(comparedversion(one,two) >= 0) end,
- arguments = strings[2]
+ arguments = "2 strings"
}
implement {
diff --git a/tex/context/base/mkiv/font-ctx.lua b/tex/context/base/mkiv/font-ctx.lua
index 9e59c66bc..3b2676667 100644
--- a/tex/context/base/mkiv/font-ctx.lua
+++ b/tex/context/base/mkiv/font-ctx.lua
@@ -1168,69 +1168,56 @@ local specifiers = { }
do -- else too many locals
- ----- ctx_setdefaultfontname = context.fntsetdefname
- ----- ctx_setsomefontname = context.fntsetsomename
- ----- ctx_setemptyfontsize = context.fntsetnopsize
- ----- ctx_setsomefontsize = context.fntsetsomesize
- ----- ctx_letvaluerelax = context.letvaluerelax
+ local starttiming = statistics.starttiming
+ local stoptiming = statistics.stoptiming
- local starttiming = statistics.starttiming
- local stoptiming = statistics.stoptiming
+ local setmacro = tokens.setters.macro
- local scanners = tokens.scanners
- local scanstring = scanners.string
- local scaninteger = scanners.integer
- local scannumber = scanners.number
- local scanboolean = scanners.boolean
-
- local setmacro = tokens.setters.macro
- local scanners = interfaces.scanners
-
- -- function commands.definefont_one(str)
-
- scanners.definefont_one = function()
- local str = scanstring()
-
- starttiming(fonts)
- if trace_defining then
- report_defining("memory usage before: %s",statistics.memused())
- report_defining("start stage one: %s",str)
- end
- local fullname, size = lpegmatch(splitpattern,str)
- local lookup, name, sub, method, detail = getspecification(fullname)
- if not name then
- report_defining("strange definition %a",str)
- -- ctx_setdefaultfontname()
- elseif name == "unknown" then
- -- ctx_setdefaultfontname()
- else
- -- ctx_setsomefontname(name)
- setmacro("somefontname",name,"global")
- end
- -- we can also use a count for the size
- if size and size ~= "" then
- local mode, size = lpegmatch(sizepattern,size)
- if size and mode then
- texsetcount("scaledfontmode",mode)
- -- ctx_setsomefontsize(size)
- setmacro("somefontsize",size)
+ implement {
+ name = "definefont_one",
+ arguments = "string",
+ actions = function(str)
+ starttiming(fonts)
+ if trace_defining then
+ report_defining("memory usage before: %s",statistics.memused())
+ report_defining("start stage one: %s",str)
+ end
+ local fullname, size = lpegmatch(splitpattern,str)
+ local lookup, name, sub, method, detail = getspecification(fullname)
+ if not name then
+ report_defining("strange definition %a",str)
+ -- ctx_setdefaultfontname()
+ elseif name == "unknown" then
+ -- ctx_setdefaultfontname()
+ else
+ -- ctx_setsomefontname(name)
+ setmacro("somefontname",name,"global")
+ end
+ -- we can also use a count for the size
+ if size and size ~= "" then
+ local mode, size = lpegmatch(sizepattern,size)
+ if size and mode then
+ texsetcount("scaledfontmode",mode)
+ -- ctx_setsomefontsize(size)
+ setmacro("somefontsize",size)
+ else
+ texsetcount("scaledfontmode",0)
+ -- ctx_setemptyfontsize()
+ end
+ elseif true then
+ -- so we don't need to check in tex
+ texsetcount("scaledfontmode",2)
+ -- ctx_setemptyfontsize()
else
texsetcount("scaledfontmode",0)
-- ctx_setemptyfontsize()
end
- elseif true then
- -- so we don't need to check in tex
- texsetcount("scaledfontmode",2)
- -- ctx_setemptyfontsize()
- else
- texsetcount("scaledfontmode",0)
- -- ctx_setemptyfontsize()
- end
- specification = definers.makespecification(str,lookup,name,sub,method,detail,size)
- if trace_defining then
- report_defining("stop stage one")
+ specification = definers.makespecification(str,lookup,name,sub,method,detail,size)
+ if trace_defining then
+ report_defining("stop stage one")
+ end
end
- end
+ }
local function nice_cs(cs)
return (gsub(cs,".->", ""))
@@ -1244,179 +1231,228 @@ do -- else too many locals
combinefeatures = v
end)
- scanners.definefont_two = function()
- local global = scanboolean() -- \ifx\fontclass\empty\s!false\else\s!true\fi
- local cs = scanstring () -- {#csname}%
- local str = scanstring () -- \somefontfile
- local size = scaninteger() -- \d_font_scaled_font_size
- local inheritancemode = scaninteger() -- \c_font_feature_inheritance_mode
- local classfeatures = scanstring () -- \m_font_class_features
- local fontfeatures = scanstring () -- \m_font_features
- local classfallbacks = scanstring () -- \m_font_class_fallbacks
- local fontfallbacks = scanstring () -- \m_font_fallbacks
- local mathsize = scaninteger() -- \fontface
- local textsize = scaninteger() -- \d_font_scaled_text_face
- local relativeid = scaninteger() -- \relativefontid
- local classgoodies = scanstring () -- \m_font_class_goodies
- local goodies = scanstring () -- \m_font_goodies
- local classdesignsize = scanstring () -- \m_font_class_designsize
- local fontdesignsize = scanstring () -- \m_font_designsize
- local scaledfontmode = scaninteger() -- \scaledfontmode
-
- if trace_defining then
- report_defining("start stage two: %s, size %s, features %a & %a, mode %a",str,size,classfeatures,fontfeatures,inheritancemode)
- end
- -- name is now resolved and size is scaled cf sa/mo
- local lookup, name, sub, method, detail = getspecification(str or "")
- -- new (todo: inheritancemode)
- local designsize = fontdesignsize ~= "" and fontdesignsize or classdesignsize or ""
- local designname = designsizefilename(name,designsize,size)
- if designname and designname ~= "" then
- if trace_defining or trace_designsize then
- report_defining("remapping name %a, specification %a, size %a, designsize %a",name,designsize,size,designname)
- end
- -- we don't catch detail here
- local o_lookup, o_name, o_sub, o_method, o_detail = getspecification(designname)
- if o_lookup and o_lookup ~= "" then lookup = o_lookup end
- if o_method and o_method ~= "" then method = o_method end
- if o_detail and o_detail ~= "" then detail = o_detail end
- name = o_name
- sub = o_sub
- end
- -- so far
- -- some settings can have been overloaded
- if lookup and lookup ~= "" then
- specification.lookup = lookup
- end
- if relativeid and relativeid ~= "" then -- experimental hook
- local id = tonumber(relativeid) or 0
- specification.relativeid = id > 0 and id
- end
- --
- specification.name = name
- specification.size = size
- specification.sub = (sub and sub ~= "" and sub) or specification.sub
- specification.mathsize = mathsize
- specification.textsize = textsize
- specification.goodies = goodies
- specification.cs = cs
- specification.global = global
- specification.scalemode = scaledfontmode -- context specific
- if detail and detail ~= "" then
- specification.method = method or "*"
- specification.detail = detail
- elseif specification.detail and specification.detail ~= "" then
- -- already set
- elseif inheritancemode == 0 then
- -- nothing
- elseif inheritancemode == 1 then
- -- fontonly
- if fontfeatures and fontfeatures ~= "" then
- specification.method = "*"
- specification.detail = fontfeatures
- end
- if fontfallbacks and fontfallbacks ~= "" then
- specification.fallbacks = fontfallbacks
- end
- elseif inheritancemode == 2 then
- -- classonly
- if classfeatures and classfeatures ~= "" then
- specification.method = "*"
- specification.detail = classfeatures
- end
- if classfallbacks and classfallbacks ~= "" then
- specification.fallbacks = classfallbacks
- end
- elseif inheritancemode == 3 then
- -- fontfirst
- if combinefeatures then
- if classfeatures and classfeatures ~= "" then
- specification.method = "*"
- if fontfeatures and fontfeatures ~= "" and fontfeatures ~= classfeatures then
- specification.detail = classfeatures .. "," .. fontfeatures
- else
- specification.detail = classfeatures
- end
- elseif fontfeatures and fontfeatures ~= "" then
- specification.method = "*"
- specification.detail = fontfeatures
+
+
+
+
+
+ implement {
+ name = "definefont_two",
+ arguments = {
+ "boolean", "string", "string", "integer", "integer", "string", "string", "string", "string",
+ "integer", "integer", "integer", "string", "string", "string", "string", "integer",
+ },
+ actions = function (
+ global, -- \ifx\fontclass\empty\s!false\else\s!true\fi
+ cs, -- {#csname}%
+ str, -- \somefontfile
+ size, -- \d_font_scaled_font_size
+ inheritancemode, -- \c_font_feature_inheritance_mode
+ classfeatures, -- \m_font_class_features
+ fontfeatures, -- \m_font_features
+ classfallbacks, -- \m_font_class_fallbacks
+ fontfallbacks, -- \m_font_fallbacks
+ mathsize, -- \fontface
+ textsize, -- \d_font_scaled_text_face
+ relativeid, -- \relativefontid
+ classgoodies, -- \m_font_class_goodies
+ goodies, -- \m_font_goodies
+ classdesignsize, -- \m_font_class_designsize
+ fontdesignsize, -- \m_font_designsize
+ scaledfontmode -- \scaledfontmode
+ )
+
+ if trace_defining then
+ report_defining("start stage two: %s, size %s, features %a & %a, mode %a",str,size,classfeatures,fontfeatures,inheritancemode)
+ end
+ -- name is now resolved and size is scaled cf sa/mo
+ local lookup, name, sub, method, detail = getspecification(str or "")
+ -- new (todo: inheritancemode)
+ local designsize = fontdesignsize ~= "" and fontdesignsize or classdesignsize or ""
+ local designname = designsizefilename(name,designsize,size)
+ if designname and designname ~= "" then
+ if trace_defining or trace_designsize then
+ report_defining("remapping name %a, specification %a, size %a, designsize %a",name,designsize,size,designname)
end
- else
+ -- we don't catch detail here
+ local o_lookup, o_name, o_sub, o_method, o_detail = getspecification(designname)
+ if o_lookup and o_lookup ~= "" then lookup = o_lookup end
+ if o_method and o_method ~= "" then method = o_method end
+ if o_detail and o_detail ~= "" then detail = o_detail end
+ name = o_name
+ sub = o_sub
+ end
+ -- so far
+ -- some settings can have been overloaded
+ if lookup and lookup ~= "" then
+ specification.lookup = lookup
+ end
+ if relativeid and relativeid ~= "" then -- experimental hook
+ local id = tonumber(relativeid) or 0
+ specification.relativeid = id > 0 and id
+ end
+ --
+ specification.name = name
+ specification.size = size
+ specification.sub = (sub and sub ~= "" and sub) or specification.sub
+ specification.mathsize = mathsize
+ specification.textsize = textsize
+ specification.goodies = goodies
+ specification.cs = cs
+ specification.global = global
+ specification.scalemode = scaledfontmode -- context specific
+ if detail and detail ~= "" then
+ specification.method = method or "*"
+ specification.detail = detail
+ elseif specification.detail and specification.detail ~= "" then
+ -- already set
+ elseif inheritancemode == 0 then
+ -- nothing
+ elseif inheritancemode == 1 then
+ -- fontonly
if fontfeatures and fontfeatures ~= "" then
specification.method = "*"
specification.detail = fontfeatures
- elseif classfeatures and classfeatures ~= "" then
+ end
+ if fontfallbacks and fontfallbacks ~= "" then
+ specification.fallbacks = fontfallbacks
+ end
+ elseif inheritancemode == 2 then
+ -- classonly
+ if classfeatures and classfeatures ~= "" then
specification.method = "*"
specification.detail = classfeatures
end
- end
- if fontfallbacks and fontfallbacks ~= "" then
- specification.fallbacks = fontfallbacks
- elseif classfallbacks and classfallbacks ~= "" then
- specification.fallbacks = classfallbacks
- end
- elseif inheritancemode == 4 then
- -- classfirst
- if combinefeatures then
- if fontfeatures and fontfeatures ~= "" then
- specification.method = "*"
- if classfeatures and classfeatures ~= "" and classfeatures ~= fontfeatures then
- specification.detail = fontfeatures .. "," .. classfeatures
- else
+ if classfallbacks and classfallbacks ~= "" then
+ specification.fallbacks = classfallbacks
+ end
+ elseif inheritancemode == 3 then
+ -- fontfirst
+ if combinefeatures then
+ if classfeatures and classfeatures ~= "" then
+ specification.method = "*"
+ if fontfeatures and fontfeatures ~= "" and fontfeatures ~= classfeatures then
+ specification.detail = classfeatures .. "," .. fontfeatures
+ else
+ specification.detail = classfeatures
+ end
+ elseif fontfeatures and fontfeatures ~= "" then
+ specification.method = "*"
specification.detail = fontfeatures
end
- elseif classfeatures and classfeatures ~= "" then
- specification.method = "*"
- specification.detail = classfeatures
+ else
+ if fontfeatures and fontfeatures ~= "" then
+ specification.method = "*"
+ specification.detail = fontfeatures
+ elseif classfeatures and classfeatures ~= "" then
+ specification.method = "*"
+ specification.detail = classfeatures
+ end
end
- else
- if classfeatures and classfeatures ~= "" then
- specification.method = "*"
- specification.detail = classfeatures
- elseif fontfeatures and fontfeatures ~= "" then
- specification.method = "*"
- specification.detail = fontfeatures
+ if fontfallbacks and fontfallbacks ~= "" then
+ specification.fallbacks = fontfallbacks
+ elseif classfallbacks and classfallbacks ~= "" then
+ specification.fallbacks = classfallbacks
+ end
+ elseif inheritancemode == 4 then
+ -- classfirst
+ if combinefeatures then
+ if fontfeatures and fontfeatures ~= "" then
+ specification.method = "*"
+ if classfeatures and classfeatures ~= "" and classfeatures ~= fontfeatures then
+ specification.detail = fontfeatures .. "," .. classfeatures
+ else
+ specification.detail = fontfeatures
+ end
+ elseif classfeatures and classfeatures ~= "" then
+ specification.method = "*"
+ specification.detail = classfeatures
+ end
+ else
+ if classfeatures and classfeatures ~= "" then
+ specification.method = "*"
+ specification.detail = classfeatures
+ elseif fontfeatures and fontfeatures ~= "" then
+ specification.method = "*"
+ specification.detail = fontfeatures
+ end
+ end
+ if classfallbacks and classfallbacks ~= "" then
+ specification.fallbacks = classfallbacks
+ elseif fontfallbacks and fontfallbacks ~= "" then
+ specification.fallbacks = fontfallbacks
end
end
- if classfallbacks and classfallbacks ~= "" then
- specification.fallbacks = classfallbacks
- elseif fontfallbacks and fontfallbacks ~= "" then
- specification.fallbacks = fontfallbacks
- end
- end
- --
- local tfmdata = definers.read(specification,size) -- id not yet known (size in spec?)
- --
- local lastfontid = 0
- local tfmtype = type(tfmdata)
- if tfmtype == "table" then
- -- setting the extra characters will move elsewhere
- local characters = tfmdata.characters
- local parameters = tfmdata.parameters
- local properties = tfmdata.properties
- -- we use char0 as signal; cf the spec pdf can handle this (no char in slot)
- characters[0] = nil
- -- characters[0x00A0] = { width = parameters.space }
- -- characters[0x2007] = { width = characters[0x0030] and characters[0x0030].width or parameters.space } -- figure
- -- characters[0x2008] = { width = characters[0x002E] and characters[0x002E].width or parameters.space } -- period
--
- local fallbacks = specification.fallbacks or ""
- local mathsize = (mathsize == 1 or mathsize == 2 or mathsize == 3) and mathsize or nil -- can be unset so we test 1 2 3
- if fallbacks ~= "" and mathsize and not busy then
- busy = true
- -- We need this ugly hack in order to resolve fontnames (at the \TEX end). Originally
- -- math was done in Lua after loading (plugged into aftercopying).
+ local tfmdata = definers.read(specification,size) -- id not yet known (size in spec?)
+ --
+ local lastfontid = 0
+ local tfmtype = type(tfmdata)
+ if tfmtype == "table" then
+ -- setting the extra characters will move elsewhere
+ local characters = tfmdata.characters
+ local parameters = tfmdata.parameters
+ local properties = tfmdata.properties
+ -- we use char0 as signal; cf the spec pdf can handle this (no char in slot)
+ characters[0] = nil
+ -- characters[0x00A0] = { width = parameters.space }
+ -- characters[0x2007] = { width = characters[0x0030] and characters[0x0030].width or parameters.space } -- figure
+ -- characters[0x2008] = { width = characters[0x002E] and characters[0x002E].width or parameters.space } -- period
--
- -- After tl 2017 I'll also do text fallbacks this way (although backups there are done
- -- in a completely different way.)
- if trace_defining then
- report_defining("defining %a, id %a, target %a, features %a / %a, fallbacks %a / %a, step %a",
- name,id,nice_cs(cs),classfeatures,fontfeatures,classfallbacks,fontfallbacks,1)
- end
- mathematics.resolvefallbacks(tfmdata,specification,fallbacks)
- context(function()
- busy = false
- mathematics.finishfallbacks(tfmdata,specification,fallbacks)
+ local fallbacks = specification.fallbacks or ""
+ local mathsize = (mathsize == 1 or mathsize == 2 or mathsize == 3) and mathsize or nil -- can be unset so we test 1 2 3
+ if fallbacks ~= "" and mathsize and not busy then
+ busy = true
+ -- We need this ugly hack in order to resolve fontnames (at the \TEX end). Originally
+ -- math was done in Lua after loading (plugged into aftercopying).
+ --
+ -- After tl 2017 I'll also do text fallbacks this way (although backups there are done
+ -- in a completely different way.)
+ if trace_defining then
+ report_defining("defining %a, id %a, target %a, features %a / %a, fallbacks %a / %a, step %a",
+ name,id,nice_cs(cs),classfeatures,fontfeatures,classfallbacks,fontfallbacks,1)
+ end
+ mathematics.resolvefallbacks(tfmdata,specification,fallbacks)
+ context(function()
+ busy = false
+ mathematics.finishfallbacks(tfmdata,specification,fallbacks)
+ local id = definefont(tfmdata)
+ csnames[id] = specification.cs
+ properties.id = id
+ definers.register(tfmdata,id) -- to be sure, normally already done
+ texdefinefont(global,cs,id)
+ constructors.cleanuptable(tfmdata)
+ constructors.finalize(tfmdata)
+ if trace_defining then
+ report_defining("defining %a, id %a, target %a, features %a / %a, fallbacks %a / %a, step %a",
+ name,id,nice_cs(cs),classfeatures,fontfeatures,classfallbacks,fontfallbacks,2)
+ end
+ -- resolved (when designsize is used):
+ local size = round(tfmdata.parameters.size or 655360)
+ setmacro("somefontsize",size.."sp")
+ -- ctx_setsomefontsize(size .. "sp")
+ texsetcount("scaledfontsize",size)
+ lastfontid = id
+ --
+ if trace_defining then
+ report_defining("memory usage after: %s",statistics.memused())
+ report_defining("stop stage two")
+ end
+ --
+ texsetcount("global","lastfontid",lastfontid)
+ specifiers[lastfontid] = { str, size }
+ if not mathsize then
+ -- forget about it (can't happen here)
+ elseif mathsize == 0 then
+ -- can't happen (here)
+ else
+ -- maybe only 1 2 3 (we already test for this)
+ lastmathids[mathsize] = lastfontid
+ end
+ stoptiming(fonts)
+ end)
+ return
+ else
local id = definefont(tfmdata)
csnames[id] = specification.cs
properties.id = id
@@ -1426,7 +1462,7 @@ do -- else too many locals
constructors.finalize(tfmdata)
if trace_defining then
report_defining("defining %a, id %a, target %a, features %a / %a, fallbacks %a / %a, step %a",
- name,id,nice_cs(cs),classfeatures,fontfeatures,classfallbacks,fontfallbacks,2)
+ name,id,nice_cs(cs),classfeatures,fontfeatures,classfallbacks,fontfallbacks,"-")
end
-- resolved (when designsize is used):
local size = round(tfmdata.parameters.size or 655360)
@@ -1434,102 +1470,78 @@ do -- else too many locals
-- ctx_setsomefontsize(size .. "sp")
texsetcount("scaledfontsize",size)
lastfontid = id
- --
- if trace_defining then
- report_defining("memory usage after: %s",statistics.memused())
- report_defining("stop stage two")
- end
- --
- texsetcount("global","lastfontid",lastfontid)
- specifiers[lastfontid] = { str, size }
- if not mathsize then
- -- forget about it (can't happen here)
- elseif mathsize == 0 then
- -- can't happen (here)
- else
- -- maybe only 1 2 3 (we already test for this)
- lastmathids[mathsize] = lastfontid
- end
- stoptiming(fonts)
- end)
- return
- else
- local id = definefont(tfmdata)
- csnames[id] = specification.cs
- properties.id = id
- definers.register(tfmdata,id) -- to be sure, normally already done
- texdefinefont(global,cs,id)
- constructors.cleanuptable(tfmdata)
- constructors.finalize(tfmdata)
+ end
+ elseif tfmtype == "number" then
if trace_defining then
- report_defining("defining %a, id %a, target %a, features %a / %a, fallbacks %a / %a, step %a",
- name,id,nice_cs(cs),classfeatures,fontfeatures,classfallbacks,fontfallbacks,"-")
+ report_defining("reusing %s, id %a, target %a, features %a / %a, fallbacks %a / %a, goodies %a / %a, designsize %a / %a",
+ name,tfmdata,nice_cs(cs),classfeatures,fontfeatures,classfallbacks,fontfallbacks,classgoodies,goodies,classdesignsize,fontdesignsize)
end
+ csnames[tfmdata] = specification.cs
+ texdefinefont(global,cs,tfmdata)
-- resolved (when designsize is used):
- local size = round(tfmdata.parameters.size or 655360)
- setmacro("somefontsize",size.."sp")
+ local size = round(fontdata[tfmdata].parameters.size or 0)
-- ctx_setsomefontsize(size .. "sp")
+ setmacro("somefontsize",size.."sp")
texsetcount("scaledfontsize",size)
- lastfontid = id
+ lastfontid = tfmdata
+ else
+ report_defining("unable to define %a as %a",name,nice_cs(cs))
+ lastfontid = -1
+ texsetcount("scaledfontsize",0)
+ -- ctx_letvaluerelax(cs) -- otherwise the current definition takes the previous one
end
- elseif tfmtype == "number" then
if trace_defining then
- report_defining("reusing %s, id %a, target %a, features %a / %a, fallbacks %a / %a, goodies %a / %a, designsize %a / %a",
- name,tfmdata,nice_cs(cs),classfeatures,fontfeatures,classfallbacks,fontfallbacks,classgoodies,goodies,classdesignsize,fontdesignsize)
- end
- csnames[tfmdata] = specification.cs
- texdefinefont(global,cs,tfmdata)
- -- resolved (when designsize is used):
- local size = round(fontdata[tfmdata].parameters.size or 0)
- -- ctx_setsomefontsize(size .. "sp")
- setmacro("somefontsize",size.."sp")
- texsetcount("scaledfontsize",size)
- lastfontid = tfmdata
- else
- report_defining("unable to define %a as %a",name,nice_cs(cs))
- lastfontid = -1
- texsetcount("scaledfontsize",0)
- -- ctx_letvaluerelax(cs) -- otherwise the current definition takes the previous one
- end
- if trace_defining then
- report_defining("memory usage after: %s",statistics.memused())
- report_defining("stop stage two")
- end
- --
- texsetcount("global","lastfontid",lastfontid)
- specifiers[lastfontid] = { str, size }
- if not mathsize then
- -- forget about it
- elseif mathsize == 0 then
- -- can't happen (here)
- else
- -- maybe only 1 2 3
- lastmathids[mathsize] = lastfontid
+ report_defining("memory usage after: %s",statistics.memused())
+ report_defining("stop stage two")
+ end
+ --
+ texsetcount("global","lastfontid",lastfontid)
+ specifiers[lastfontid] = { str, size }
+ if not mathsize then
+ -- forget about it
+ elseif mathsize == 0 then
+ -- can't happen (here)
+ else
+ -- maybe only 1 2 3
+ lastmathids[mathsize] = lastfontid
+ end
+ --
+ stoptiming(fonts)
end
- --
- stoptiming(fonts)
- end
+ }
- function scanners.specifiedfontspec()
- local f = specifiers[scaninteger()]
- if f then
- context(f[1])
- end
- end
- function scanners.specifiedfontsize()
- local f = specifiers[scaninteger()]
- if f then
- context(f[2])
+ implement {
+ name = "specifiedfontspec",
+ arguments = "integer",
+ actions = function(id)
+ local f = specifiers[id]
+ if f then
+ context(f[1])
+ end
end
- end
- function scanners.specifiedfont()
- local f = specifiers[scaninteger()]
- local s = scannumber()
- if f and s then
- context("%s at %0.2p",f[1],s * f[2]) -- we round to 2 decimals (as at the tex end)
+ }
+
+ implement {
+ name = "specifiedfontsize",
+ arguments = "integer",
+ actions = function(id)
+ local f = specifiers[id]
+ if f then
+ context(f[2])
+ end
end
- end
+ }
+ implement {
+ name = "specifiedfont",
+ arguments = { "integer", "number" },
+ actions = function(id,size)
+ local f = specifiers[id]
+ if f and size then
+ context("%s at %0.2p",f[1],size * f[2]) -- we round to 2 decimals (as at the tex end)
+ end
+ end
+ }
--
local function define(specification)
diff --git a/tex/context/base/mkiv/grph-chk.lua b/tex/context/base/mkiv/grph-chk.lua
index ed78b856c..0688f46ef 100644
--- a/tex/context/base/mkiv/grph-chk.lua
+++ b/tex/context/base/mkiv/grph-chk.lua
@@ -127,9 +127,9 @@ function checkers.pdf(data)
return genericchecker(data)
end
-local function wrappedidentify(identify,filename)
+local function wrappedidentify(identify,filename,filetype)
local wrapup = function() report_inclusion("fatal error reading %a",filename) end
- local _, result = xpcall(identify,wrapup,filename)
+ local _, result = xpcall(identify,wrapup,filename,filetype)
if result then
local xsize = result.xsize or 0
local ysize = result.ysize or 0
@@ -166,7 +166,7 @@ function checkers.jpg(data)
local inject = lpdf.injectors.jpg
local found = false
request.scanimage = function(t)
- local result = wrappedidentify(identify,t.filename)
+ local result = wrappedidentify(identify,t.filename,"jpg")
found = not result.error
return {
filename = result.filename,
@@ -202,7 +202,7 @@ function checkers.jp2(data) -- idem as jpg
local inject = lpdf.injectors.jp2
local found = false
request.scanimage = function(t)
- local result = wrappedidentify(identify,t.filename)
+ local result = wrappedidentify(identify,t.filename,"jp2")
found = not result.error
return {
filename = result.filename,
@@ -238,7 +238,7 @@ function checkers.png(data) -- same as jpg (for now)
local inject = lpdf.injectors.png -- currently pdf specific
local found = false
request.scanimage = function(t)
- local result = wrappedidentify(identify,t.filename)
+ local result = wrappedidentify(identify,t.filename,"png")
found = not result.error
return {
filename = result.filename,
diff --git a/tex/context/base/mkiv/lpdf-ini.lua b/tex/context/base/mkiv/lpdf-ini.lua
index 2163e8748..c6dd4765e 100644
--- a/tex/context/base/mkiv/lpdf-ini.lua
+++ b/tex/context/base/mkiv/lpdf-ini.lua
@@ -25,7 +25,6 @@ local report_finalizing = logs.reporter("backend","finalizing")
local report_blocked = logs.reporter("backend","blocked")
local implement = interfaces.implement
-local two_strings = interfaces.strings[2]
local context = context
@@ -1553,16 +1552,16 @@ end
-- interface
implement { name = "lpdf_collectedresources", actions = { lpdf.collectedresources, context } }
-implement { name = "lpdf_addtocatalog", arguments = two_strings, actions = lpdf.addtocatalog }
-implement { name = "lpdf_addtoinfo", arguments = two_strings, actions = function(a,b,c) lpdf.addtoinfo(a,b,c) end } -- gets adapted
-implement { name = "lpdf_addtonames", arguments = two_strings, actions = lpdf.addtonames }
-implement { name = "lpdf_addtopageattributes", arguments = two_strings, actions = lpdf.addtopageattributes }
-implement { name = "lpdf_addtopagesattributes", arguments = two_strings, actions = lpdf.addtopagesattributes }
-implement { name = "lpdf_addtopageresources", arguments = two_strings, actions = lpdf.addtopageresources }
-implement { name = "lpdf_adddocumentextgstate", arguments = two_strings, actions = function(a,b) lpdf.adddocumentextgstate (a,pdfverbose(b)) end }
-implement { name = "lpdf_adddocumentcolorspace", arguments = two_strings, actions = function(a,b) lpdf.adddocumentcolorspace(a,pdfverbose(b)) end }
-implement { name = "lpdf_adddocumentpattern", arguments = two_strings, actions = function(a,b) lpdf.adddocumentpattern (a,pdfverbose(b)) end }
-implement { name = "lpdf_adddocumentshade", arguments = two_strings, actions = function(a,b) lpdf.adddocumentshade (a,pdfverbose(b)) end }
+implement { name = "lpdf_addtocatalog", arguments = "2 strings", actions = lpdf.addtocatalog }
+implement { name = "lpdf_addtoinfo", arguments = "2 strings", actions = function(a,b,c) lpdf.addtoinfo(a,b,c) end } -- gets adapted
+implement { name = "lpdf_addtonames", arguments = "2 strings", actions = lpdf.addtonames }
+implement { name = "lpdf_addtopageattributes", arguments = "2 strings", actions = lpdf.addtopageattributes }
+implement { name = "lpdf_addtopagesattributes", arguments = "2 strings", actions = lpdf.addtopagesattributes }
+implement { name = "lpdf_addtopageresources", arguments = "2 strings", actions = lpdf.addtopageresources }
+implement { name = "lpdf_adddocumentextgstate", arguments = "2 strings", actions = function(a,b) lpdf.adddocumentextgstate (a,pdfverbose(b)) end }
+implement { name = "lpdf_adddocumentcolorspace", arguments = "2 strings", actions = function(a,b) lpdf.adddocumentcolorspace(a,pdfverbose(b)) end }
+implement { name = "lpdf_adddocumentpattern", arguments = "2 strings", actions = function(a,b) lpdf.adddocumentpattern (a,pdfverbose(b)) end }
+implement { name = "lpdf_adddocumentshade", arguments = "2 strings", actions = function(a,b) lpdf.adddocumentshade (a,pdfverbose(b)) end }
-- more helpers: copy from lepd to lpdf
diff --git a/tex/context/base/mkiv/luat-ini.mkiv b/tex/context/base/mkiv/luat-ini.mkiv
index d1d829be9..f059d2b85 100644
--- a/tex/context/base/mkiv/luat-ini.mkiv
+++ b/tex/context/base/mkiv/luat-ini.mkiv
@@ -121,13 +121,13 @@
%D \edef\luaescapestring#1{\!!bs#1\!!es}
%D \stoptyping
-\def\setdocumentfilename #1#2{\clf_setdocumentfilename\numexpr#1\relax{#2}}
-\def\setdocumentargument #1#2{\clf_setdocumentargument{#1}{#2}}
-\def\setdocumentargumentdefault#1#2{\clf_setdocumentdefaultargument{#1}{#2}}
-\def\getdocumentfilename #1{\clf_getdocumentfilename\numexpr#1\relax}
-\def\getdocumentargument #1{\clf_getdocumentargument{#1}{}}
-\def\setdocumentargument #1#2{\clf_setdocumentargument{#1}{#2}}
-\def\getdocumentargumentdefault#1#2{\clf_getdocumentargument{#1}{#2}}
+\normalprotected\def\setdocumentfilename #1#2{\clf_setdocumentfilename\numexpr#1\relax{#2}}
+\normalprotected\def\setdocumentargument #1#2{\clf_setdocumentargument{#1}{#2}}
+\normalprotected\def\setdocumentargumentdefault#1#2{\clf_setdocumentdefaultargument{#1}{#2}}
+ \def\getdocumentfilename #1{\clf_getdocumentfilename\numexpr#1\relax}
+ \def\getdocumentargument #1{\clf_getdocumentargument{#1}{}}
+\normalprotected\def\setdocumentargument #1#2{\clf_setdocumentargument{#1}{#2}}
+ \def\getdocumentargumentdefault#1#2{\clf_getdocumentargument{#1}{#2}}
% seldom used so no need for speedy variants:
diff --git a/tex/context/base/mkiv/luat-usr.lua b/tex/context/base/mkiv/luat-usr.lua
index b49379bbf..1756bb198 100644
--- a/tex/context/base/mkiv/luat-usr.lua
+++ b/tex/context/base/mkiv/luat-usr.lua
@@ -102,23 +102,6 @@ interfaces.implement {
arguments = "2 strings",
}
--- local scanners = interfaces.scanners
---
--- local function ctxscanner(name)
--- local scanner = scanners[name]
--- if scanner then
--- scanner()
--- else
--- report("unknown scanner: %s",name)
--- end
--- end
---
--- interfaces.implement {
--- name = "clfscanner",
--- actions = ctxscanner,
--- arguments = "string",
--- }
-
local function registername(name,message)
if not name or name == "" then
report_instance("no valid name given")
diff --git a/tex/context/base/mkiv/publ-aut.lua b/tex/context/base/mkiv/publ-aut.lua
index e74c7ee18..123a67009 100644
--- a/tex/context/base/mkiv/publ-aut.lua
+++ b/tex/context/base/mkiv/publ-aut.lua
@@ -530,9 +530,9 @@ implement {
name = "btxauthor",
actions = btxauthor,
arguments = {
- "string",
- "string",
- "string",
+ "argument",
+ "argument",
+ "argument",
{
{ "combiner" },
{ "kind" },
diff --git a/tex/context/base/mkiv/status-files.pdf b/tex/context/base/mkiv/status-files.pdf
index 374d3b695..26777bb6d 100644
--- a/tex/context/base/mkiv/status-files.pdf
+++ b/tex/context/base/mkiv/status-files.pdf
Binary files differ
diff --git a/tex/context/base/mkiv/status-lua.pdf b/tex/context/base/mkiv/status-lua.pdf
index a39f37412..ad3136f2a 100644
--- a/tex/context/base/mkiv/status-lua.pdf
+++ b/tex/context/base/mkiv/status-lua.pdf
Binary files differ
diff --git a/tex/context/base/mkiv/strc-itm.mklx b/tex/context/base/mkiv/strc-itm.mklx
index 2f3cc8425..3d1861d12 100644
--- a/tex/context/base/mkiv/strc-itm.mklx
+++ b/tex/context/base/mkiv/strc-itm.mklx
@@ -1321,6 +1321,7 @@
\letvalue{\??itemgroupstart\v!ran }\strc_itemgroups_start_edge
\letvalue{\??itemgroupstart\v!its }\strc_itemgroups_start_items
\letvalue{\??itemgroupstart\v!mar }\strc_itemgroups_start_margin
+\letvalue{\??itemgroupstart\v!txt }\strc_itemgroups_start_text
\def\optimizelistitemsbreak
{\ifcase\c_strc_itemgroups_column_depth
@@ -1578,6 +1579,11 @@
\appendtoks
\let\item \strc_itemgroups_start_do_item
+ \let\sub \strc_itemgroups_start_subitem
+ \let\sym \strc_itemgroups_start_symbol
+ \let\ran \strc_itemgroups_start_edge
+ \let\its \strc_itemgroups_start_items
+ \let\mar \strc_itemgroups_start_margin
\let\noitem \strc_itemgroups_start_no_item
\let\itm \strc_itemgroups_start_do_item
\let\but \strc_itemgroups_start_button
@@ -1588,27 +1594,29 @@
\let\startitem \startitemgroupitem
\let\stopitem \stopitemgroupitem
\let\starthead \startitemgrouphead
- \let\stophead \stopitemgroupitemhead
+ \let\stophead \stopitemgrouphead
\let\startspecialitem\startspecialitemgroupitem
\let\stopspecialitem \stopspecialitemgroupitem
\to \itemgroupcommands
-\ifx\currentinterface \v!english \else
-
- \appendtoks
- \expandafter\let\csname\v!item \endcsname\strc_itemgroups_start_do_item
- \expandafter\let\csname\v!sub \endcsname\strc_itemgroups_start_subitem
- \expandafter\let\csname\v!sym \endcsname\strc_itemgroups_start_symbol
- \expandafter\let\csname\v!ran \endcsname\strc_itemgroups_start_edge
- \expandafter\let\csname\v!head \endcsname\strc_itemgroups_head
- \expandafter\let\csname\v!its \endcsname\strc_itemgroups_start_items
- \expandafter\let\csname\v!mar \endcsname\strc_itemgroups_start_margin
- \expandafter\let\csname\v!txt \endcsname\strc_itemgroups_start_text
- \expandafter\let\csname\e!start\v!item\endcsname\startitemgroupitem
- \expandafter\let\csname\e!stop \v!item\endcsname\stopitemgroupitem
- \expandafter\let\csname\e!start\v!head\endcsname\startitemgrouphead
- \expandafter\let\csname\e!stop \v!head\endcsname\stopitemgrouphead
- \to \itemgroupcommands
+\ifx\currentinterface \s!english \else
+
+ \def\next#1#2{\ifcsname#1\endcsname\else\let\csname#1\endcsname#2\fi}
+
+ \etoksapp\itemgroupcommands{%
+ \next{\v!item }\strc_itemgroups_start_do_item
+ \next{\v!sub }\strc_itemgroups_start_subitem
+ \next{\v!sym }\strc_itemgroups_start_symbol
+ \next{\v!ran }\strc_itemgroups_start_edge
+ \next{\v!head }\strc_itemgroups_head
+ \next{\v!its }\strc_itemgroups_start_items
+ \next{\v!mar }\strc_itemgroups_start_margin
+ \next{\v!txt }\strc_itemgroups_start_text
+ \next{\e!start\v!item}\startitemgroupitem
+ \next{\e!stop \v!item}\stopitemgroupitem
+ \next{\e!start\v!head}\startitemgrouphead
+ \next{\e!stop \v!head}\stopitemgrouphead
+ }
\fi
diff --git a/tex/context/base/mkiv/strc-itm.mkvi b/tex/context/base/mkiv/strc-itm.mkvi
index cbbefd5db..1b306fe18 100644
--- a/tex/context/base/mkiv/strc-itm.mkvi
+++ b/tex/context/base/mkiv/strc-itm.mkvi
@@ -1321,6 +1321,7 @@
\letvalue{\??itemgroupstart\v!ran }\strc_itemgroups_start_edge
\letvalue{\??itemgroupstart\v!its }\strc_itemgroups_start_items
\letvalue{\??itemgroupstart\v!mar }\strc_itemgroups_start_margin
+\letvalue{\??itemgroupstart\v!txt }\strc_itemgroups_start_text
\def\optimizelistitemsbreak
{\ifcase\c_strc_itemgroups_column_depth \ifconditional\c_strc_itemgroups_optimize
@@ -1577,6 +1578,11 @@
\appendtoks
\let\item \strc_itemgroups_start_do_item
+ \let\sub \strc_itemgroups_start_subitem
+ \let\sym \strc_itemgroups_start_symbol
+ \let\ran \strc_itemgroups_start_edge
+ \let\its \strc_itemgroups_start_items
+ \let\mar \strc_itemgroups_start_margin
\let\noitem \strc_itemgroups_start_no_item
\let\itm \strc_itemgroups_start_do_item
\let\but \strc_itemgroups_start_button
@@ -1587,27 +1593,29 @@
\let\startitem \startitemgroupitem
\let\stopitem \stopitemgroupitem
\let\starthead \startitemgrouphead
- \let\stophead \stopitemgroupitemhead
+ \let\stophead \stopitemgrouphead
\let\startspecialitem\startspecialitemgroupitem
\let\stopspecialitem \stopspecialitemgroupitem
\to \itemgroupcommands
-\ifx\currentinterface \v!english \else
-
- \appendtoks
- \expandafter\let\csname\v!item \endcsname\strc_itemgroups_start_do_item
- \expandafter\let\csname\v!sub \endcsname\strc_itemgroups_start_subitem
- \expandafter\let\csname\v!sym \endcsname\strc_itemgroups_start_symbol
- \expandafter\let\csname\v!ran \endcsname\strc_itemgroups_start_edge
- \expandafter\let\csname\v!head \endcsname\strc_itemgroups_head
- \expandafter\let\csname\v!its \endcsname\strc_itemgroups_start_items
- \expandafter\let\csname\v!mar \endcsname\strc_itemgroups_start_margin
- \expandafter\let\csname\v!txt \endcsname\strc_itemgroups_start_text
- \expandafter\let\csname\e!start\v!item\endcsname\startitemgroupitem
- \expandafter\let\csname\e!stop \v!item\endcsname\stopitemgroupitem
- \expandafter\let\csname\e!start\v!head\endcsname\startitemgrouphead
- \expandafter\let\csname\e!stop \v!head\endcsname\stopitemgrouphead
- \to \itemgroupcommands
+\ifx\currentinterface \s!english \else
+
+ \def\next#1#2{\ifcsname#1\endcsname\else\let\csname#1\endcsname#2\fi}
+
+ \etoksapp\itemgroupcommands{%
+ \next{\v!item }\strc_itemgroups_start_do_item
+ \next{\v!sub }\strc_itemgroups_start_subitem
+ \next{\v!sym }\strc_itemgroups_start_symbol
+ \next{\v!ran }\strc_itemgroups_start_edge
+ \next{\v!head }\strc_itemgroups_head
+ \next{\v!its }\strc_itemgroups_start_items
+ \next{\v!mar }\strc_itemgroups_start_margin
+ \next{\v!txt }\strc_itemgroups_start_text
+ \next{\e!start\v!item}\startitemgroupitem
+ \next{\e!stop \v!item}\stopitemgroupitem
+ \next{\e!start\v!head}\startitemgrouphead
+ \next{\e!stop \v!head}\stopitemgrouphead
+ }
\fi
diff --git a/tex/context/base/mkiv/syst-aux.mkxl b/tex/context/base/mkiv/syst-aux.mkxl
index 956d43f89..2c84fe2c6 100644
--- a/tex/context/base/mkiv/syst-aux.mkxl
+++ b/tex/context/base/mkiv/syst-aux.mkxl
@@ -634,9 +634,9 @@
%D These are normally only used for keywords, i.e.\ strings so we can delegate
%D the work to \LUA:
-\unexpanded\def\doifelseinset#1#2{\clf_doifelseinset{#1}{#2}}
-\unexpanded\def\doifinset #1#2{\clf_doifinset {#1}{#2}}
-\unexpanded\def\doifnotinset #1#2{\clf_doifnotinset {#1}{#2}}
+%unexpanded\def\doifelseinset#1#2{\clf_doifelseinset{#1}{#2}}
+%unexpanded\def\doifinset #1#2{\clf_doifinset {#1}{#2}}
+%unexpanded\def\doifnotinset #1#2{\clf_doifnotinset {#1}{#2}}
% % \let\firstinset \clf_firstinset
% These don't accept spaces after commas:
diff --git a/tex/context/base/mkiv/syst-lua.lua b/tex/context/base/mkiv/syst-lua.lua
index 77960def7..5976e077f 100644
--- a/tex/context/base/mkiv/syst-lua.lua
+++ b/tex/context/base/mkiv/syst-lua.lua
@@ -20,11 +20,9 @@ local ctx_secondoftwoarguments = context.secondoftwoarguments
local ctx_firstofoneargument = context.firstofoneargument
local ctx_gobbleoneargument = context.gobbleoneargument
-local two_strings = interfaces.strings[2]
-
implement { -- will be overloaded later
name = "writestatus",
- arguments = two_strings,
+ arguments = "2 strings",
actions = logs.status,
}
@@ -123,7 +121,7 @@ implement {
implement {
name = "doifelsesame",
- arguments = two_strings,
+ arguments = "2 strings",
actions = function(a,b)
if a == b then
ctx_firstoftwoarguments()
@@ -135,7 +133,7 @@ implement {
implement {
name = "doifsame",
- arguments = two_strings,
+ arguments = "2 strings",
actions = function(a,b)
if a == b then
ctx_firstofoneargument()
@@ -147,7 +145,7 @@ implement {
implement {
name = "doifnotsame",
- arguments = two_strings,
+ arguments = "2 strings",
actions = function(a,b)
if a == b then
ctx_gobbleoneargument()
diff --git a/tex/context/base/mkiv/toks-ini.lua b/tex/context/base/mkiv/toks-ini.lua
index 0ac5dcc50..184a17489 100644
--- a/tex/context/base/mkiv/toks-ini.lua
+++ b/tex/context/base/mkiv/toks-ini.lua
@@ -43,6 +43,7 @@ end
local scan_toks = token.scan_toks
local scan_string = token.scan_string
local scan_argument = token.scan_argument
+local scan_delimited = token.scan_delimited
local scan_tokenlist = token.scan_tokenlist
local scan_int = token.scan_int
local scan_code = token.scan_code
@@ -55,6 +56,7 @@ local scan_keyword_cs = token.scan_keyword_cs or scan_keyword
local scan_token = token.scan_token
local scan_box = token.scan_box
local scan_word = token.scan_word
+local scan_letters = token.scan_letters or scan_word -- lmtx
local scan_key = token.scan_key
local scan_value = token.scan_value
local scan_char = token.scan_char
@@ -191,11 +193,13 @@ tokens.scanners = { -- these expand
count = scan_int,
string = scan_string,
argument = scan_argument,
+ delimited = scan_delimited,
tokenlist = scan_tokenlist,
verbatim = scan_verbatim, -- detokenize
code = scan_code,
tokencode = scan_token_code,
word = scan_word,
+ letters = scan_letters,
key = scan_key,
value = scan_value,
char = scan_char,
diff --git a/tex/context/base/mkiv/toks-scn.lua b/tex/context/base/mkiv/toks-scn.lua
index 09c3e13b2..7ef4ce603 100644
--- a/tex/context/base/mkiv/toks-scn.lua
+++ b/tex/context/base/mkiv/toks-scn.lua
@@ -22,13 +22,16 @@ local tokenbits = tokens.bits
local scanstring = scanners.string
local scanargument = scanners.argument
+local scandelimited = scanners.delimited -- lmtx
local scanverbatim = scanners.verbatim
local scantokenlist = scanners.tokenlist
+local scantoks = scanners.toks
local scaninteger = scanners.integer
local scannumber = scanners.number
local scankeyword = scanners.keyword
local scankeywordcs = scanners.keywordcs
local scanword = scanners.word
+local scanletters = scanners.letters
local scankey = scanners.key
local scancode = scanners.code
local scanboolean = scanners.boolean
@@ -113,23 +116,24 @@ local function scantable(t,data)
if not data then
data = { }
end
- local wrapped = scanopen()
- while true do
--- local key = scanword()
- local key = scanword(true)
- if key then
- local get = t[key]
- if get then
- data[key] = get()
+ if t then
+ local wrapped = scanopen()
+ while true do
+ local key = scanword(true)
+ if key then
+ local get = t[key]
+ if get then
+ data[key] = get()
+ else
+ -- catch all we can get
+ end
else
- -- catch all we can get
+ break
end
- else
- break
end
- end
- if wrapped then
- scanclose()
+ if wrapped then
+ scanclose()
+ end
end
return data
end
@@ -166,42 +170,84 @@ function scanners.whd()
end
end
+-- begin lmtx
+
+local l = utf.byte("[")
+local r = utf.byte("]")
+
+local function scanbracketed()
+ local s = scandelimited(l, r)
+ if s then
+ return s
+ else
+ report_scan("missing argument in line %i of %a", status.linenumber, status.filename)
+ return ""
+ end
+end
+
+local function scanoptional()
+ return scandelimited(l, r) or ""
+end
+
+local function scanbracketedasis()
+ return scandelimited(l, r, false)
+end
+
+local function scanargumentasis()
+ return scanargument(false)
+end
+
+scanners.bracketed = scanbracketed
+scanners.optional = scanoptional
+scanners.bracketedasis = scanbracketedasis
+scanners.argumentasis = scanargumentasis
+
+-- end lmtx
+
local shortcuts = {
- tokens = tokens,
- bits = tokenbits,
- open = open,
- close = close,
- scanners = scanners,
- scanstring = scanstring,
- scanargument = scanargument,
- scanverbatim = scanverbatim,
- scantokenlist = scantokenlist,
- scaninteger = scaninteger,
- scannumber = scannumber,
- scantable = scantable,
- scankeyword = scankeyword,
- scankeywordcs = scankeywordcs,
- scanword = scanword,
- -- scankey = scankey,
- scancode = scancode,
- scanboolean = scanboolean,
- scandimen = scandimen,
- scandimension = scandimen,
- scanbox = scanners.box,
- scanhbox = scanners.hbox,
- scanvbox = scanners.vbox,
- scanvtop = scanners.vtop,
- scanconditional = scanconditional,
- scanopen = scanopen,
- scanclose = scanclose,
- scanlist = scanlist,
- scancsname = scancsname,
- todimen = todimen,
- tonumber = tonumber,
- tostring = tostring,
- toboolean = toboolean,
- inspect = inspect,
- report = report_scan,
+ tokens = tokens,
+ bits = tokenbits,
+ open = open,
+ close = close,
+ scanners = scanners,
+ scanstring = scanstring,
+ scanargument = scanargument,
+ scanverbatim = scanverbatim,
+ scantokenlist = scantokenlist,
+ scantoks = scantoks,
+ scaninteger = scaninteger,
+ scannumber = scannumber,
+ scantable = scantable, -- not directly useable
+ scankeyword = scankeyword,
+ scankeywordcs = scankeywordcs,
+ scanword = scanword,
+ scanletters = scanletters,
+ -- scankey = scankey,
+ scancode = scancode,
+ scanboolean = scanboolean,
+ scandimen = scandimen,
+ scandimension = scandimen,
+ scanbox = scanners.box,
+ scanhbox = scanners.hbox,
+ scanvbox = scanners.vbox,
+ scanvtop = scanners.vtop,
+ scanconditional = scanconditional,
+ scanopen = scanopen,
+ scanclose = scanclose,
+ scanlist = scanlist,
+ scancsname = scancsname,
+ todimen = todimen,
+ tonumber = tonumber,
+ tostring = tostring,
+ toboolean = toboolean,
+ inspect = inspect,
+ report = report_scan,
+ -- lmtx
+ scandelimited = scandelimited, -- not directly useable
+ scanbracketed = scanbracketed,
+ scanoptional = scanoptional,
+ scanbracketedasis = scanbracketedasis,
+ scanargumentasis = scanargumentasis,
}
tokens.shortcuts = shortcuts
@@ -222,25 +268,28 @@ tokens.converters = {
toglue = "todimen",
}
--- We could just pickup a keyword but then we really need to make sure
--- that no number follows it when that is the assignment and adding
--- an optional = defeats the gain in speed. Currently we have sources
--- with no spaces (\startcontextdefinitioncode ...) so it fails there.
+-- We could just pickup a keyword but then we really need to make sure that no number
+-- follows it when that is the assignment and adding an optional = defeats the gain
+-- in speed. Currently we have sources with no spaces (\startcontextdefinitioncode
+-- ...) so it fails there.
--
--- Another drawback is that we then need to use { } instead of ending
--- with \relax (as we can do now) but that is no big deal. It's just
--- that I then need to check the TeX end. More pain than gain and a bit
--- risky too.
+-- Another drawback is that we then need to use { } instead of ending with \relax (as
+-- we can do now) but that is no big deal. It's just that I then need to check the TeX
+-- end. More pain than gain and a bit risky too. Using scanletters works better, but
+-- the gain is only some 10 percent but if we don't have keywords with numbers it might
+-- make sense in the end, some day.
local f_if = formatters[ " if scankeywordcs('%s') then data['%s'] = scan%s()"]
local f_elseif = formatters[" elseif scankeywordcs('%s') then data['%s'] = scan%s()"]
------ f_if = formatters[" local key = scanword() if key == '' then break elseif key == '%s' then data['%s'] = scan%s()"]
------ f_elseif = formatters[" elseif key == '%s' then data['%s'] = scan%s()"]
-
----- f_if_x = formatters[ " if not data['%s'] and scankeywordcs('%s') then data['%s'] = scan%s()"]
----- f_elseif_x = formatters[" elseif not data['%s'] and scankeywordcs('%s') then data['%s'] = scan%s()"]
+-- if CONTEXTLMTXMODE > 0 then
+-- f_if = formatters[" local key = scanletters() if key == '' then break elseif key == '%s' then data['%s'] = scan%s()"]
+-- f_elseif = formatters[" elseif key == '%s' then data['%s'] = scan%s()"]
+-- end
+
local f_local = formatters["local scan%s = scanners.%s"]
local f_scan = formatters["scan%s()"]
local f_shortcut = formatters["local %s = scanners.converters.%s"]
@@ -250,9 +299,11 @@ local f_elseif_c = formatters[" elseif scankeywordcs('%s') then data['%s'] = %s
local f_scan_c = formatters["%s(scan%s())"]
-- see above
---
------ f_if_c = formatters[" local key = scanword() if key == '' then break elseif key == '%s' then data['%s'] = %s(scan%s())"]
------ f_elseif_c = formatters[" elseif k == '%s' then data['%s'] = %s(scan%s())"]
+
+-- if CONTEXTLMTXMODE > 0 then
+-- f_if_c = formatters[" local key = scanletters() if key == '' then break elseif key == '%s' then data['%s'] = %s(scan%s())"]
+-- f_elseif_c = formatters[" elseif k == '%s' then data['%s'] = %s(scan%s())"]
+-- end
local f_any = formatters[" else local key = scanword(true) if key then data[key] = scan%s() else break end end"]
local f_any_c = formatters[" else local key = scanword(true) if key then data[key] = %s(scan%s()) else break end end"]
@@ -270,33 +321,6 @@ local f_action_f = formatters["action%s(%s)"]
local f_action_s = formatters["local action%s = tokens._action[%s]"]
local f_nested = formatters["local function scan%s()\n local data = { }\n%s\n return data\nend\n"]
--- local f_check = formatters[ [[
--- local wrapped = false
--- while true do
--- local c = scancode(open)
--- if c == 123 then
--- wrapped = true
--- break
--- elseif c ~= 32 then
--- break
--- end
--- end
--- while true do
--- ]] .. "%\nt\n" .. [[
--- %s
--- end
--- if wrapped then
--- while true do
--- local c = scancode(close)
--- if c == 125 then
--- break
--- elseif c ~= 32 then
--- break
--- end
--- end
--- end
--- ]] ]
-
local f_check = formatters[ [[
local wrapped = scanopen()
while true do
@@ -319,6 +343,11 @@ local presets = {
["6 strings"] = { "string", "string", "string", "string", "string", "string" },
["7 strings"] = { "string", "string", "string", "string", "string", "string", "string" },
["8 strings"] = { "string", "string", "string", "string", "string", "string", "string", "string" },
+
+ ["1 argument" ] = { "argument" },
+ ["2 arguments"] = { "argument", "argument" },
+ ["3 arguments"] = { "argument", "argument", "argument" },
+ ["4 arguments"] = { "argument", "argument", "argument", "argument" },
}
tokens.presets = presets
@@ -542,7 +571,7 @@ end
-- { "nature", "boolean" },
-- { "escape", "string" },
-- { "escape" },
--- }
+-- },
-- "boolean",
-- }
--
diff --git a/tex/context/base/mkiv/util-str.lua b/tex/context/base/mkiv/util-str.lua
index aba7859c3..2d3f4d669 100644
--- a/tex/context/base/mkiv/util-str.lua
+++ b/tex/context/base/mkiv/util-str.lua
@@ -1057,76 +1057,44 @@ local format_rest = function(s)
return format("%q",s) -- catches " and \n and such
end
--- local format_extension = function(extensions,f,name)
--- local extension = extensions[name] or "tostring(%s)"
--- local f = tonumber(f) or 1
--- local w = find(extension,"%.%.%.")
--- if f == 0 then
--- if w then
--- extension = gsub(extension,"%.%.%.","")
--- end
--- return extension
--- elseif f == 1 then
--- if w then
--- extension = gsub(extension,"%.%.%.","%%s")
--- end
--- n = n + 1
--- local a = "a" .. n
--- return format(extension,a,a) -- maybe more times?
--- elseif f < 0 then
--- local a = "a" .. (n + f + 1)
--- return format(extension,a,a)
--- else
--- if w then
--- extension = gsub(extension,"%.%.%.",rep("%%s,",f-1).."%%s")
--- end
--- -- we could fill an array and then n = n + 1 unpack(t,n,n+f) but as we
--- -- cache we don't save much and there are hardly any extensions anyway
--- local t = { }
--- for i=1,f do
--- n = n + 1
--- -- t[#t+1] = "a" .. n
--- t[i] = "a" .. n
--- end
--- return format(extension,unpack(t))
--- end
--- end
-
local format_extension = function(extensions,f,name)
local extension = extensions[name] or "tostring(%s)"
local f = tonumber(f) or 1
local w = find(extension,"%.%.%.")
- if w then
- -- we have a wildcard
- if f == 0 then
+ if f == 0 then
+ if w then
extension = gsub(extension,"%.%.%.","")
- return extension
- elseif f == 1 then
+ end
+ return extension
+ elseif f == 1 then
+ if w then
extension = gsub(extension,"%.%.%.","%%s")
- n = n + 1
- local a = "a" .. n
- return format(extension,a,a) -- maybe more times?
- elseif f < 0 then
+ end
+ n = n + 1
+ local a = "a" .. n
+ return format(extension,a,a) -- maybe more times?
+ elseif f < 0 then
+ if w then
+ -- not supported
+ extension = gsub(extension,"%.%.%.","")
+ return extension
+ else
local a = "a" .. (n + f + 1)
return format(extension,a,a)
- else
- extension = gsub(extension,"%.%.%.",rep("%%s,",f-1).."%%s")
- -- we could fill an array and then n = n + 1 unpack(t,n,n+f) but as we
- -- cache we don't save much and there are hardly any extensions anyway
- local t = { }
- for i=1,f do
- n = n + 1
- -- t[#t+1] = "a" .. n
- t[i] = "a" .. n
- end
- return format(extension,unpack(t))
end
else
- extension = gsub(extension,"%%s",function()
+ if w then
+ extension = gsub(extension,"%.%.%.",rep("%%s,",f-1).."%%s")
+ end
+ -- we could fill an array and then n = n + 1 unpack(t,n,n+f) but as we
+ -- cache we don't save much and there are hardly any extensions anyway
+ local t = { }
+ for i=1,f do
n = n + 1
- return "a" .. n
- end)
- return extension
+ -- t[#t+1] = "a" .. n
+ t[i] = "a" .. n
+ end
+ return format(extension,unpack(t))
end
end
diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua
index 68b47494a..471d32d1b 100644
--- a/tex/generic/context/luatex/luatex-fonts-merged.lua
+++ b/tex/generic/context/luatex/luatex-fonts-merged.lua
@@ -1,6 +1,6 @@
-- merged file : c:/data/develop/context/sources/luatex-fonts-merged.lua
-- parent file : c:/data/develop/context/sources/luatex-fonts.lua
--- merge date : 2020-06-20 13:33
+-- merge date : 2020-06-25 10:55
do -- begin closure to overcome local limits and interference
@@ -3761,33 +3761,36 @@ local format_extension=function(extensions,f,name)
local extension=extensions[name] or "tostring(%s)"
local f=tonumber(f) or 1
local w=find(extension,"%.%.%.")
- if w then
- if f==0 then
+ if f==0 then
+ if w then
extension=gsub(extension,"%.%.%.","")
- return extension
- elseif f==1 then
+ end
+ return extension
+ elseif f==1 then
+ if w then
extension=gsub(extension,"%.%.%.","%%s")
- n=n+1
- local a="a"..n
- return format(extension,a,a)
- elseif f<0 then
+ end
+ n=n+1
+ local a="a"..n
+ return format(extension,a,a)
+ elseif f<0 then
+ if w then
+ extension=gsub(extension,"%.%.%.","")
+ return extension
+ else
local a="a"..(n+f+1)
return format(extension,a,a)
- else
- extension=gsub(extension,"%.%.%.",rep("%%s,",f-1).."%%s")
- local t={}
- for i=1,f do
- n=n+1
- t[i]="a"..n
- end
- return format(extension,unpack(t))
end
else
- extension=gsub(extension,"%%s",function()
+ if w then
+ extension=gsub(extension,"%.%.%.",rep("%%s,",f-1).."%%s")
+ end
+ local t={}
+ for i=1,f do
n=n+1
- return "a"..n
- end)
- return extension
+ t[i]="a"..n
+ end
+ return format(extension,unpack(t))
end
end
local builder=Cs { "start",