From b2db36adbd89b2dba9591da5fc13b4eba57d581e Mon Sep 17 00:00:00 2001 From: Hans Hagen Date: Mon, 11 Oct 2021 00:26:56 +0200 Subject: 2021-10-10 23:42:00 --- .../context/lexers/scite-context-lexer-tex.lua | 123 ++- context/data/scite/context/scite-ctx.lua | 28 +- doc/context/scripts/mkiv/context.html | 2 +- doc/context/scripts/mkiv/context.man | 2 +- doc/context/scripts/mkiv/context.xml | 2 +- doc/context/scripts/mkiv/mtx-context.html | 2 +- doc/context/scripts/mkiv/mtx-context.man | 2 +- doc/context/scripts/mkiv/mtx-context.xml | 2 +- .../sources/general/manuals/musings/musings.tex | 2 +- scripts/context/lua/mtx-context.xml | 2 +- tex/context/base/mkii/cont-new.mkii | 2 +- tex/context/base/mkii/context.mkii | 2 +- tex/context/base/mkiv/cont-new.mkiv | 2 +- tex/context/base/mkiv/context.mkiv | 2 +- tex/context/base/mkiv/lang-def.mkiv | 4 +- tex/context/base/mkiv/mtx-context-compare.tex | 1 - tex/context/base/mkiv/publ-ini.lua | 33 +- tex/context/base/mkiv/publ-ini.mkiv | 4 + tex/context/base/mkiv/status-files.pdf | Bin 24847 -> 24835 bytes tex/context/base/mkiv/status-lua.pdf | Bin 253894 -> 253897 bytes tex/context/base/mkxl/cont-new.mkxl | 2 +- tex/context/base/mkxl/context.mkxl | 5 +- tex/context/base/mkxl/font-emp.mklx | 84 ++- tex/context/base/mkxl/lang-def.mkxl | 4 +- tex/context/base/mkxl/publ-ini.mkxl | 18 +- tex/context/base/mkxl/strc-mar-old.lmt | 759 +++++++++++++++++++ tex/context/base/mkxl/strc-mar-old.mkxl | 142 ++++ tex/context/base/mkxl/strc-mar.lmt | 822 +++------------------ tex/context/base/mkxl/strc-mar.mkxl | 168 ++++- tex/generic/context/luatex/luatex-fonts-merged.lua | 2 +- 30 files changed, 1413 insertions(+), 810 deletions(-) create mode 100644 tex/context/base/mkxl/strc-mar-old.lmt create mode 100644 tex/context/base/mkxl/strc-mar-old.mkxl diff --git a/context/data/scite/context/lexers/scite-context-lexer-tex.lua b/context/data/scite/context/lexers/scite-context-lexer-tex.lua index a4aa83aa0..b1367f27d 100644 --- a/context/data/scite/context/lexers/scite-context-lexer-tex.lua +++ b/context/data/scite/context/lexers/scite-context-lexer-tex.lua @@ -9,7 +9,8 @@ local info = { local string, table, lpeg = string, table, lpeg local P, R, S, V, C, Cmt, Cp, Cc, Ct = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.C, lpeg.Cmt, lpeg.Cp, lpeg.Cc, lpeg.Ct local type, next = type, next -local find, match, lower, upper = string.find, string.match, string.lower, string.upper +local concat = table.concat +local find, match, lower, upper, gsub = string.find, string.match, string.lower, string.upper, string.gsub local lexers = require("scite-context-lexer") @@ -33,6 +34,8 @@ do -- todo: only once, store in global -- commands helpers primitives + local collected = { } + local definitions = lexers.loaddefinitions("scite-context-data-interfaces") if definitions then @@ -65,7 +68,7 @@ do -- todo: only once, store in global end end table.sort(used) - report("context user interfaces '%s' supported",table.concat(used," ")) + report("context user interfaces '%s' supported",concat(used," ")) end local definitions = lexers.loaddefinitions("scite-context-data-context") @@ -103,8 +106,8 @@ do -- todo: only once, store in global add(definitions.tex,true) add(definitions.etex,true) add(definitions.pdftex,true) - add(definitions.aleph,true) - add(definitions.omega,true) + -- add(definitions.aleph,true) + -- add(definitions.omega,true) add(definitions.luatex,true) add(definitions.xetex,true) end @@ -169,14 +172,14 @@ local p_rest = any local p_preamble = knownpreamble local p_comment = commentline ------ p_command = backslash * knowncommand +local p_command = backslash * knowncommand ----- p_constant = backslash * exactmatch(constants) ----- p_helper = backslash * exactmatch(helpers) ----- p_primitive = backslash * exactmatch(primitives) local p_csdone = #(1-cstoken) + P(-1) -local p_command = backslash * lexers.helpers.utfchartabletopattern(currentcommands) * p_csdone +----- p_command = backslash * lexers.helpers.utfchartabletopattern(currentcommands) * p_csdone local p_constant = backslash * lexers.helpers.utfchartabletopattern(constants) * p_csdone local p_helper = backslash * lexers.helpers.utfchartabletopattern(helpers) * p_csdone local p_primitive = backslash * lexers.helpers.utfchartabletopattern(primitives) * p_csdone @@ -209,40 +212,41 @@ local p_word = C(iwordpattern) * Cp() / function(s,p) return sty -- 2 : 10 sec -- -- the problem is that quite some style subtables get generated so collapsing ranges helps +-- although in the new scite approach this is less an issue (no lua tables) -local option = 1 - -if option == 1 then - - p_comment = p_comment^1 - p_grouping = p_grouping^1 - p_special = p_special^1 - p_extra = p_extra^1 - - p_command = p_command^1 - p_constant = p_constant^1 - p_helper = p_helper^1 - p_primitive = p_primitive^1 - p_ifprimitive = p_ifprimitive^1 - p_reserved = p_reserved^1 - -elseif option == 2 then - - local included = space^0 - - p_comment = (p_comment * included)^1 - p_grouping = (p_grouping * included)^1 - p_special = (p_special * included)^1 - p_extra = (p_extra * included)^1 - - p_command = (p_command * included)^1 - p_constant = (p_constant * included)^1 - p_helper = (p_helper * included)^1 - p_primitive = (p_primitive * included)^1 - p_ifprimitive = (p_ifprimitive * included)^1 - p_reserved = (p_reserved * included)^1 +local option = 0 -- otherwise we get e.g. \btx... and \xml... in commands colors ... -end +-- if option == 1 then +-- +-- p_comment = p_comment^1 +-- p_grouping = p_grouping^1 +-- p_special = p_special^1 +-- p_extra = p_extra^1 +-- +-- p_command = p_command^1 +-- p_constant = p_constant^1 +-- p_helper = p_helper^1 +-- p_primitive = p_primitive^1 +-- p_ifprimitive = p_ifprimitive^1 +-- p_reserved = p_reserved^1 +-- +-- elseif option == 2 then +-- +-- local included = space^0 +-- +-- p_comment = (p_comment * included)^1 +-- p_grouping = (p_grouping * included)^1 +-- p_special = (p_special * included)^1 +-- p_extra = (p_extra * included)^1 + +-- p_command = (p_command * included)^1 +-- p_constant = (p_constant * included)^1 +-- p_helper = (p_helper * included)^1 +-- p_primitive = (p_primitive * included)^1 +-- p_ifprimitive = (p_ifprimitive * included)^1 +-- p_reserved = (p_reserved * included)^1 +-- +-- end local p_invisible = invisibles^1 @@ -493,4 +497,47 @@ contextlexer.folding = { }, } +do + + local lastcurrent = nil + local allcommands = { } + + function contextlexer.completion(str) + if currentcommands then + if lastcurrent ~= currentcommands then + allcommands = { } + for k, v in next, currentcommands do + allcommands[#allcommands+1] = "\\" .. k + end + for k, v in next, helpers do + allcommands[#allcommands+1] = "\\" .. k + end + for k, v in next, primitives do + allcommands[#allcommands+1] = "\\" .. k + end + -- for k, v in next, constants do + -- allcommands[#constants+1] = "\\" .. k + -- end + lastcurrent = currentcommands + table.sort(allcommands) + end + if find(str,"^\\") then + local str = "^" .. str + local list = { } + local n = 0 + for i=1,#allcommands do + local c = allcommands[i] + if find(c,str) then + n = n + 1 ; list[n] = c + end + end + if n > 0 then + return list and concat(list," ") + end + end + end + end + +end + return contextlexer diff --git a/context/data/scite/context/scite-ctx.lua b/context/data/scite/context/scite-ctx.lua index 73ef06719..4bde33d2b 100644 --- a/context/data/scite/context/scite-ctx.lua +++ b/context/data/scite/context/scite-ctx.lua @@ -415,8 +415,9 @@ do print("\n- recognized first lines:\n") print("xml = 2 then + local snippet = editor:textrange(start,stop) + local list = syntax.completion(snippet) + if list then + editor.AutoCMaxHeight = 30 + editor.AutoCSeparator = 32 + editor:AutoCShow(length,list) + end + end + end + end + end + end + +-- function OnKey(a,b,c) +-- print("key",a,b,c) +-- end + diff --git a/doc/context/scripts/mkiv/context.html b/doc/context/scripts/mkiv/context.html index 016f6c768..15fa7985c 100644 --- a/doc/context/scripts/mkiv/context.html +++ b/doc/context/scripts/mkiv/context.html @@ -89,7 +89,7 @@ --nonstopmoderun without stopping --nosynctexnever initializes synctex (for production runs) - --synctexrun with synctex enabled (better use \setupsynctex[state=start] + --synctexrun with synctex enabled (better use \setupsynctex[state=start]) --nodatesomit runtime dates in pdf file (optional value: a number (this 1970 offset time) or string "YYYY-MM-DD HH:MM") --nocompressionforcefully turns off compression in the backend diff --git a/doc/context/scripts/mkiv/context.man b/doc/context/scripts/mkiv/context.man index b6e380237..93cd877be 100644 --- a/doc/context/scripts/mkiv/context.man +++ b/doc/context/scripts/mkiv/context.man @@ -129,7 +129,7 @@ run without stopping never initializes synctex (for production runs) .TP .B --synctex -run with synctex enabled (better use \setupsynctex[state=start] +run with synctex enabled (better use \setupsynctex[state=start]) .TP .B --nodates omit runtime dates in pdf file (optional value: a number (this 1970 offset time) or string "YYYY-MM-DD HH:MM") diff --git a/doc/context/scripts/mkiv/context.xml b/doc/context/scripts/mkiv/context.xml index d4e0d33c5..cc13bf7df 100644 --- a/doc/context/scripts/mkiv/context.xml +++ b/doc/context/scripts/mkiv/context.xml @@ -148,7 +148,7 @@ never initializes synctex (for production runs) - run with synctex enabled (better use \setupsynctex[state=start] + run with synctex enabled (better use \setupsynctex[state=start]) diff --git a/doc/context/scripts/mkiv/mtx-context.html b/doc/context/scripts/mkiv/mtx-context.html index 016f6c768..15fa7985c 100644 --- a/doc/context/scripts/mkiv/mtx-context.html +++ b/doc/context/scripts/mkiv/mtx-context.html @@ -89,7 +89,7 @@ --nonstopmoderun without stopping --nosynctexnever initializes synctex (for production runs) - --synctexrun with synctex enabled (better use \setupsynctex[state=start] + --synctexrun with synctex enabled (better use \setupsynctex[state=start]) --nodatesomit runtime dates in pdf file (optional value: a number (this 1970 offset time) or string "YYYY-MM-DD HH:MM") --nocompressionforcefully turns off compression in the backend diff --git a/doc/context/scripts/mkiv/mtx-context.man b/doc/context/scripts/mkiv/mtx-context.man index b6e380237..93cd877be 100644 --- a/doc/context/scripts/mkiv/mtx-context.man +++ b/doc/context/scripts/mkiv/mtx-context.man @@ -129,7 +129,7 @@ run without stopping never initializes synctex (for production runs) .TP .B --synctex -run with synctex enabled (better use \setupsynctex[state=start] +run with synctex enabled (better use \setupsynctex[state=start]) .TP .B --nodates omit runtime dates in pdf file (optional value: a number (this 1970 offset time) or string "YYYY-MM-DD HH:MM") diff --git a/doc/context/scripts/mkiv/mtx-context.xml b/doc/context/scripts/mkiv/mtx-context.xml index d4e0d33c5..cc13bf7df 100644 --- a/doc/context/scripts/mkiv/mtx-context.xml +++ b/doc/context/scripts/mkiv/mtx-context.xml @@ -148,7 +148,7 @@ never initializes synctex (for production runs) - run with synctex enabled (better use \setupsynctex[state=start] + run with synctex enabled (better use \setupsynctex[state=start]) diff --git a/doc/context/sources/general/manuals/musings/musings.tex b/doc/context/sources/general/manuals/musings/musings.tex index d3c1f3148..143dfe456 100644 --- a/doc/context/sources/general/manuals/musings/musings.tex +++ b/doc/context/sources/general/manuals/musings/musings.tex @@ -20,13 +20,13 @@ \component musings-roadmap \component musings-names \component musings-plain - % \component musings-toocomplex % \component musings-manuals % \component musings-performance % \component musings-history % \component musings-treasures % \component musings-whytex-again + \component musings-dontusetex \stopbodymatter \stopproduct diff --git a/scripts/context/lua/mtx-context.xml b/scripts/context/lua/mtx-context.xml index d4e0d33c5..cc13bf7df 100644 --- a/scripts/context/lua/mtx-context.xml +++ b/scripts/context/lua/mtx-context.xml @@ -148,7 +148,7 @@ never initializes synctex (for production runs) - run with synctex enabled (better use \setupsynctex[state=start] + run with synctex enabled (better use \setupsynctex[state=start]) diff --git a/tex/context/base/mkii/cont-new.mkii b/tex/context/base/mkii/cont-new.mkii index d43e2ccf1..6aa453475 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{2021.10.08 20:05} +\newcontextversion{2021.10.10 23:40} %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 3c7645d53..fff18ed27 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{2021.10.08 20:05} +\edef\contextversion{2021.10.10 23:40} %D For those who want to use this: diff --git a/tex/context/base/mkiv/cont-new.mkiv b/tex/context/base/mkiv/cont-new.mkiv index c8893eb1e..8bad7dd12 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{2021.10.08 20:05} +\newcontextversion{2021.10.10 23:40} %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 89e04f878..3924c7104 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{2021.10.08 20:05} +\edef\contextversion{2021.10.10 23:40} %D Kind of special: diff --git a/tex/context/base/mkiv/lang-def.mkiv b/tex/context/base/mkiv/lang-def.mkiv index 603935097..441d328c8 100644 --- a/tex/context/base/mkiv/lang-def.mkiv +++ b/tex/context/base/mkiv/lang-def.mkiv @@ -554,7 +554,7 @@ % Artificial Languages: Esperanto \installlanguage - [\s!esperanto] + [\s!eo] [\c!spacing=\v!packed, \c!leftsentence=\endash, \c!rightsentence=\endash, @@ -569,7 +569,7 @@ \s!lefthyphenmin=2, \s!righthyphenmin=2] -\installlanguage[\s!eo][\c!default=\s!esperanto] +\installlanguage[\s!esperanto][\c!default=\s!eo] % Baltic Languages: Lettish/Latvian, Lietuvių/Lithuanian diff --git a/tex/context/base/mkiv/mtx-context-compare.tex b/tex/context/base/mkiv/mtx-context-compare.tex index c940270c8..163ea5747 100644 --- a/tex/context/base/mkiv/mtx-context-compare.tex +++ b/tex/context/base/mkiv/mtx-context-compare.tex @@ -38,7 +38,6 @@ \stopTEXpage \stoptexdefinition - \startluacode local report = logs.reporter("compare") diff --git a/tex/context/base/mkiv/publ-ini.lua b/tex/context/base/mkiv/publ-ini.lua index 83f0ff9ac..584b23dbf 100644 --- a/tex/context/base/mkiv/publ-ini.lua +++ b/tex/context/base/mkiv/publ-ini.lua @@ -2168,18 +2168,18 @@ do function lists.combiinlist(dataset,tag) local rendering = renderings[dataset] - local list = rendering.list + -- local list = rendering.list local toindex = rendering.tagtolistindex return toindex and toindex[tag] end function lists.flushcombi(dataset,tag) local rendering = renderings[dataset] - local list = rendering.list local toindex = rendering.tagtolistindex local listindex = toindex and toindex[tag] if listindex then - local li = list[listindex] + local list = rendering.list + local li = list[listindex] if li then local data = datasets[dataset] local luadata = data.luadata @@ -3507,3 +3507,30 @@ do end end + +do + + -- no caching for now + + interfaces.implement { -- shared with mkiv so no public + name = "btxdoifelsecitedone", + protected = true, + -- public = true, + -- arguments = "2 arguments", + arguments = "2 strings", + actions = function(dataset,tag) + -- dataset ignored + local list = structures.lists.tobesaved + local done = false + for i=1,#list do + local u = list[i].userdata + if u.btxref == tag then + done = true + break + end + end + ctx_doifelse(done) + end + } + +end diff --git a/tex/context/base/mkiv/publ-ini.mkiv b/tex/context/base/mkiv/publ-ini.mkiv index dfed53c73..6e34d3ab5 100644 --- a/tex/context/base/mkiv/publ-ini.mkiv +++ b/tex/context/base/mkiv/publ-ini.mkiv @@ -799,9 +799,13 @@ \unexpanded\def\btxdoifelsecombiinlist#1#2% {\clf_btxdoifelsecombiinlist{#1}{#2}} +\unexpanded\def\btxdoifelsecitedone#1#2% + {\clf_btxdoifelsecitedone{#1}{#2}} + \let\btxdoifsameaspreviouscheckedelse\btxdoifelsesameaspreviouschecked \let\btxdoifsameaspreviouselse \btxdoifelsesameasprevious \let\btxdoifcombiinlistelse \btxdoifelsecombiinlist +\let\btxdoifcitedoneelse \btxdoifelsecitedone \def\publ_place_list_indeed#1#2[#3][#4]% {\begingroup diff --git a/tex/context/base/mkiv/status-files.pdf b/tex/context/base/mkiv/status-files.pdf index c251ad6c1..ff8592826 100644 Binary files a/tex/context/base/mkiv/status-files.pdf and b/tex/context/base/mkiv/status-files.pdf differ diff --git a/tex/context/base/mkiv/status-lua.pdf b/tex/context/base/mkiv/status-lua.pdf index 50cc0ad29..389d9cfd0 100644 Binary files a/tex/context/base/mkiv/status-lua.pdf and b/tex/context/base/mkiv/status-lua.pdf differ diff --git a/tex/context/base/mkxl/cont-new.mkxl b/tex/context/base/mkxl/cont-new.mkxl index e81d6cc7b..0a0624c12 100644 --- a/tex/context/base/mkxl/cont-new.mkxl +++ b/tex/context/base/mkxl/cont-new.mkxl @@ -13,7 +13,7 @@ % \normalend % uncomment this to get the real base runtime -\newcontextversion{2021.10.08 20:05} +\newcontextversion{2021.10.10 23:40} %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/mkxl/context.mkxl b/tex/context/base/mkxl/context.mkxl index a5b9cc7f1..98ed72845 100644 --- a/tex/context/base/mkxl/context.mkxl +++ b/tex/context/base/mkxl/context.mkxl @@ -29,7 +29,7 @@ %D {YYYY.MM.DD HH:MM} format. \immutable\edef\contextformat {\jobname} -\immutable\edef\contextversion{2021.10.08 20:05} +\immutable\edef\contextversion{2021.10.10 23:40} %overloadmode 1 % check frozen / warning %overloadmode 2 % check frozen / error @@ -249,8 +249,7 @@ \loadmkxlfile{strc-tag} \loadmkxlfile{strc-doc} \loadmkxlfile{strc-num} -%loadmkxlfile{strc-mar} -\doiffileelse{strc-mar-new.mkxl}{\loadmkxlfile{strc-mar-new}}{\loadmkxlfile{strc-mar}} +\loadmkxlfile{strc-mar} \loadmkxlfile{strc-sbe} \loadmklxfile{strc-lst} \loadmkxlfile{strc-sec} diff --git a/tex/context/base/mkxl/font-emp.mklx b/tex/context/base/mkxl/font-emp.mklx index 1e30e7012..e99f74afd 100644 --- a/tex/context/base/mkxl/font-emp.mklx +++ b/tex/context/base/mkxl/font-emp.mklx @@ -55,28 +55,45 @@ \permanent\protected\def\emphasistypeface{\font_emphasis_checked_typeface\sl\it} \permanent\protected\def\emphasisboldface{\font_emphasis_checked_typeface\bs\bi} -\permanent\protected\def\normalboldface % public +\permanent\protected\def\normalboldface % public, upgraded from mkvi / WS {\relax + \ifx\fontalternative\s!tf\bf\orelse \ifx\fontalternative\s!it\bi\orelse - \ifx\fontalternative\s!sl\bs\else + \ifx\fontalternative\s!sl\bs\orelse + \ifx\fontalternative\s!bf \orelse + \ifx\fontalternative\s!bi \orelse + \ifx\fontalternative\s!bs \else \bf\fi} -\permanent\protected\def\normalitalicface % public +\permanent\protected\def\normalitalicface % public, upgraded from mkvi {\relax \ifx\fontalternative\s!tf\it\orelse - \ifx\fontalternative\s!bf\bi\else - \tf\fi} - -\permanent\protected\def\normalslantedface % public - {\relax \ifx\fontalternative\s!tf\sl - \orelse\ifx\fontalternative\s!bf\bs - \else \tf\fi} - -\permanent\protected\def\normaltypeface % public + \ifx\fontalternative\s!it \orelse + \ifx\fontalternative\s!sl\it\orelse + \ifx\fontalternative\s!bf\bi\orelse + \ifx\fontalternative\s!bi\bi\orelse + \ifx\fontalternative\s!bs\bi\else + \it\fi} + +\permanent\protected\def\normalslantedface % public, upgraded from mkvi {\relax - \ifx\fontalternative\s!bi \it \orelse - \ifx\fontalternative\s!bs \sl \else - \tf \fi} + \ifx\fontalternative\s!tf\sl\orelse + \ifx\fontalternative\s!it\sl\orelse + \ifx\fontalternative\s!sl \orelse + \ifx\fontalternative\s!bf\bs\orelse + \ifx\fontalternative\s!bi\bs\orelse + \ifx\fontalternative\s!bs\bs\else + \sl\fi} + +\permanent\protected\def\normaltypeface % public, upgraded from mkvi + {\relax + \ifx\fontalternative\s!tf \orelse + \ifx\fontalternative\s!it\tf\orelse + \ifx\fontalternative\s!sl\tf\orelse + \ifx\fontalternative\s!bf \orelse + \ifx\fontalternative\s!bi\bf\orelse + \ifx\fontalternative\s!bs\bf\else + \tf\fi} \permanent\protected\def\swaptypeface % public {\relax @@ -93,6 +110,43 @@ \aliased\let\italicface \normalitalicface % public \aliased\let\swapface \swaptypeface % public +%D \startbuffer[demo] +%D \starttabulate[|l|c|c|c|c|c|c|c|] +%D \NC \NC \tex{tf} \NC \tex{it} \NC \tex{sl} \NC \tex{bf} +%D \NC \tex{bi} \NC \tex{bs} \NC \tex{sc} \NC \NR +%D \NC \NC \tf txt \NC \it txt \NC \sl txt \NC \bf txt +%D \NC \bi txt \NC \bs txt \NC \sc txt \NC \NR +%D \NC \tex{typeface} \NC \tf \typeface txt \NC \it \typeface txt \NC \sl \typeface txt \NC \bf \typeface txt +%D \NC \bi \typeface txt \NC \bs \typeface txt \NC \sc \typeface txt \NC \NR +%D \NC \tex{boldface} \NC \tf \boldface txt \NC \it \boldface txt \NC \sl \boldface txt \NC \bf \boldface txt +%D \NC \bi \boldface txt \NC \bs \boldface txt \NC \sc \boldface txt \NC \NR +%D \NC \tex{slantedface} \NC \tf \slantedface txt \NC \it \slantedface txt \NC \sl \slantedface txt \NC \bf \slantedface txt +%D \NC \bi \slantedface txt \NC \bs \slantedface txt \NC \sc \slantedface txt \NC \NR +%D \NC \tex{italicface} \NC \tf \italicface txt \NC \it \italicface txt \NC \sl \italicface txt \NC \bf \italicface txt +%D \NC \bi \italicface txt \NC \bs \italicface txt \NC \sc \italicface txt \NC \NR +%D \NC \tex{swapface} \NC \tf \swapface txt \NC \it \swapface txt \NC \sl \swapface txt \NC \bf \swapface txt +%D \NC \bi \swapface txt \NC \bs \swapface txt \NC \sc \swapface txt \NC \NR +%D \stoptabulate +%D \stopbuffer +%D +%D {\small \typebuffer[demo]} +%D +%D This gives: +%D +%D \getbuffer[demo] +%D +%D But with: +%D +%D \startbuffer +%D \setupbodyfontenvironment [default] [em=blue] % affects \swapface +%D \stopbuffer +%D +%D \typebuffer +%D +%D We get: +%D +%D {\getbuffer\getbuffer[demo]} + %D To be set with the default body font environment: \type {em} being \type %D {slanted} or \type {italic}. diff --git a/tex/context/base/mkxl/lang-def.mkxl b/tex/context/base/mkxl/lang-def.mkxl index 603935097..441d328c8 100644 --- a/tex/context/base/mkxl/lang-def.mkxl +++ b/tex/context/base/mkxl/lang-def.mkxl @@ -554,7 +554,7 @@ % Artificial Languages: Esperanto \installlanguage - [\s!esperanto] + [\s!eo] [\c!spacing=\v!packed, \c!leftsentence=\endash, \c!rightsentence=\endash, @@ -569,7 +569,7 @@ \s!lefthyphenmin=2, \s!righthyphenmin=2] -\installlanguage[\s!eo][\c!default=\s!esperanto] +\installlanguage[\s!esperanto][\c!default=\s!eo] % Baltic Languages: Lettish/Latvian, Lietuvių/Lithuanian diff --git a/tex/context/base/mkxl/publ-ini.mkxl b/tex/context/base/mkxl/publ-ini.mkxl index 2c52b24e9..f1e60ca43 100644 --- a/tex/context/base/mkxl/publ-ini.mkxl +++ b/tex/context/base/mkxl/publ-ini.mkxl @@ -805,9 +805,13 @@ \permanent\protected\def\btxdoifelsecombiinlist#1#2% {\clf_btxdoifelsecombiinlist{#1}{#2}} +\permanent\protected\def\btxdoifelsecitedone#1#2% + {\clf_btxdoifelsecitedone{#1}{#2}} + \aliased\let\btxdoifsameaspreviouscheckedelse\btxdoifelsesameaspreviouschecked \aliased\let\btxdoifsameaspreviouselse \btxdoifelsesameasprevious \aliased\let\btxdoifcombiinlistelse \btxdoifelsecombiinlist +\aliased\let\btxdoifcitedoneelse \btxdoifelsecitedone \tolerant\def\publ_place_list_indeed#1#2#*[#3]#*[#4]% {\begingroup @@ -1303,12 +1307,12 @@ \installcorenamespace{btxinteraction} -\setvalue{\??btxinteraction\v!number}{\settrue\btxinteractivenumber} -\setvalue{\??btxinteraction\v!text }{\settrue\btxinteractivetext} -\setvalue{\??btxinteraction\v!page }{\settrue\btxinteractivepage} -\setvalue{\??btxinteraction\v!all }{\settrue\btxinteractivenumber - \settrue\btxinteractivetext - \settrue\btxinteractivepage} +\defcsname\??btxinteraction\v!number\endcsname{\settrue\btxinteractivenumber} +\defcsname\??btxinteraction\v!text \endcsname{\settrue\btxinteractivetext} +\defcsname\??btxinteraction\v!page \endcsname{\settrue\btxinteractivepage} +\defcsname\??btxinteraction\v!all \endcsname{\settrue\btxinteractivenumber + \settrue\btxinteractivetext + \settrue\btxinteractivepage} % \setupbtx[interaction=page] % or text or number or all % \setupbtxrendering[pagestate=start] @@ -1557,7 +1561,7 @@ %D Setup helpers, beware, we need to wrap this .. now we need to know %D how setups are implemented. -\setvalue{\??setup:\s!btx:\s!unknown}#1{\inframed{\tttf#1}} +\defcsname\??setup:\s!btx:\s!unknown\endcsname#1{\inframed{\tttf#1}} \def\publ_fast_setup_yes#1#2% {\csname\??setup:\s!btx:% diff --git a/tex/context/base/mkxl/strc-mar-old.lmt b/tex/context/base/mkxl/strc-mar-old.lmt new file mode 100644 index 000000000..eb94f9fc3 --- /dev/null +++ b/tex/context/base/mkxl/strc-mar-old.lmt @@ -0,0 +1,759 @@ +if not modules then modules = { } end modules ['strc-mar'] = { + version = 1.001, + comment = "companion to strc-mar.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- todo: cleanup stack (structures.marks.reset(v_all) also does the job) +-- todo: only commands.* print to tex, native marks return values + +local insert, concat = table.insert, table.concat +local tostring, next, rawget, type = tostring, next, rawget, type +local lpegmatch = lpeg.match + +local context = context +local commands = commands + +local implement = interfaces.implement + +local allocate = utilities.storage.allocate +local setmetatableindex = table.setmetatableindex + +local nuts = nodes.nuts +local tonut = nuts.tonut + +local getid = nuts.getid +local getlist = nuts.getlist +local getattr = nuts.getattr +local getbox = nuts.getbox + +local nextnode = nuts.traversers.node + +local nodecodes = nodes.nodecodes +local whatsitcodes = nodes.whatsitcodes + +local glyph_code = nodecodes.glyph +local hlist_code = nodecodes.hlist +local vlist_code = nodecodes.vlist +local whatsit_code = nodecodes.whatsit + +local lateluawhatsit_code = whatsitcodes.latelua + +local texsetattribute = tex.setattribute + +local a_marks = attributes.private("marks") + +local trace_set = false trackers.register("marks.set", function(v) trace_set = v end) +local trace_get = false trackers.register("marks.get", function(v) trace_get = v end) +local trace_details = false trackers.register("marks.details", function(v) trace_details = v end) + +local report_marks = logs.reporter("structure","marks") + +local variables = interfaces.variables + +local v_first = variables.first +local v_last = variables.last +local v_previous = variables.previous +local v_next = variables.next +local v_top = variables.top +local v_bottom = variables.bottom +local v_current = variables.current +local v_default = variables.default +local v_page = variables.page +local v_all = variables.all +local v_keep = variables.keep + +local v_nocheck_suffix = ":" .. variables.nocheck + +local v_first_nocheck = variables.first .. v_nocheck_suffix +local v_last_nocheck = variables.last .. v_nocheck_suffix +local v_previous_nocheck = variables.previous .. v_nocheck_suffix +local v_next_nocheck = variables.next .. v_nocheck_suffix +local v_top_nocheck = variables.top .. v_nocheck_suffix +local v_bottom_nocheck = variables.bottom .. v_nocheck_suffix + +local structures = structures +local marks = structures.marks + +local settings_to_array = utilities.parsers.settings_to_array + +local boxes_too = false -- at some point we can also tag boxes or use a zero char + +directives.register("marks.boxestoo", function(v) boxes_too = v end) + +local data = marks.data or allocate() +marks.data = data + +storage.register("structures/marks/data", marks.data, "structures.marks.data") + +local stack, topofstack = { }, 0 + +local ranges = { + [v_page] = { + first = 0, + last = 0, + }, +} + +local function resolve(t,k) + if k then + if trace_set or trace_get then + report_marks("undefined mark, name %a",k) + end + local crap = { autodefined = true } -- maybe set = 0 and reset = 0 + t[k] = crap + return crap + else + -- weird: k is nil + end +end + +setmetatableindex(data, resolve) + +function marks.exists(name) + return rawget(data,name) ~= nil +end + +-- identify range + +local function sweep(head,first,last) + for n, id, subtype in nextnode, head do + -- we need to handle empty heads so we test for latelua + if id == glyph_code or (id == whatsit_code and subtype == lateluawhatsit_code) then -- brrr + local a = getattr(n,a_marks) + if not a then + -- next + elseif first == 0 then + first, last = a, a + elseif a > last then + last = a + end + elseif id == hlist_code or id == vlist_code then + if boxes_too then + local a = getattr(n,a_marks) + if not a then + -- next + elseif first == 0 then + first, last = a, a + elseif a > last then + last = a + end + end + local list = getlist(n) + if list then + first, last = sweep(list,first,last) + end + end + end + return first, last +end + +local classes = { } + +setmetatableindex(classes, function(t,k) local s = settings_to_array(k) t[k] = s return s end) + +local lasts = { } + +function marks.synchronize(class,n,option) + local box = getbox(n) + if box then + local first, last = sweep(getlist(box),0,0) + if option == v_keep and first == 0 and last == 0 then + if trace_get or trace_set then + report_marks("action %a, class %a, box %a","retain at synchronize",class,n) + end + -- todo: check if still valid first/last in range + first = lasts[class] or 0 + last = first + else + lasts[class] = last + local classlist = classes[class] + for i=1,#classlist do + local class = classlist[i] + local range = ranges[class] + if range then + range.first = first + range.last = last + else + range = { + first = first, + last = last, + } + ranges[class] = range + end + if trace_get or trace_set then + report_marks("action %a, class %a, first %a, last %a","synchronize",class,range.first,range.last) + end + end + end + elseif trace_get or trace_set then + report_marks("action %s, class %a, box %a","synchronize without content",class,n) + end +end + +-- define etc + +local function resolve(t,k) + if k == "fullchain" then + local fullchain = { } + local chain = t.chain + while chain and chain ~= "" do + insert(fullchain,1,chain) + chain = data[chain].chain + end + t[k] = fullchain + return fullchain + elseif k == "chain" then + t[k] = "" + return "" + elseif k == "reset" or k == "set" then + t[k] = 0 + return 0 + elseif k == "parent" then + t[k] = false + return false + end +end + +function marks.define(name,settings) + if not settings then + settings = { } + elseif type(settings) == "string" then + settings = { parent = settings } + end + data[name] = settings + local parent = settings.parent + if parent == nil or parent == "" or parent == name then + settings.parent = false + else + local dp = data[parent] + if not dp then + settings.parent = false + elseif dp.parent then + settings.parent = dp.parent + end + end + setmetatableindex(settings, resolve) +end + +for k, v in next, data do + setmetatableindex(v,resolve) -- runtime loaded table +end + +local function parentname(name) + local dn = data[name] + return dn and dn.parent or name +end + +function marks.relate(name,chain) + local dn = data[name] + if dn and not dn.parent then + if chain and chain ~= "" then + dn.chain = chain + local dc = data[chain] + if dc then + local children = dc.children + if not children then + children = { } + dc.children = children + end + children[#children+1] = name + end + elseif trace_set then + report_marks("error: invalid relation, name %a, chain %a",name,chain) + end + end +end + +local function resetchildren(new,name) + local dn = data[name] + if dn and not dn.parent then + local children = dn.children + if children then + for i=1,#children do + local ci = children[i] + new[ci] = false + if trace_set then + report_marks("action %a, parent %a, child %a","reset",name,ci) + end + resetchildren(new,ci) + end + end + end +end + +function marks.set(name,value) + local dn = data[name] + if dn then + local child = name + local parent = dn.parent + if parent then + name = parent + dn = data[name] + end + dn.set = topofstack + if not dn.reset then + dn.reset = 0 -- in case of selfdefined + end + local top = stack[topofstack] + local new = { } + if top then + for k, v in next, top do + local d = data[k] + local r = d.reset or 0 + local s = d.set or 0 + if r <= topofstack and s < r then + new[k] = false + else + new[k] = v + end + end + end + resetchildren(new,name) + new[name] = value + topofstack = topofstack + 1 + stack[topofstack] = new + if trace_set then + if name == child then + report_marks("action %a, name %a, index %a, value %a","set",name,topofstack,value) + else + report_marks("action %a, parent %a, child %a, index %a, value %a","set",parent,child,topofstack,value) + end + end + texsetattribute("global",a_marks,topofstack) + end +end + +local function reset(name) + if v_all then + if trace_set then + report_marks("action %a","reset all") + end + stack = { } + for name, dn in next, data do + local parent = dn.parent + if parent then + dn.reset = 0 + dn.set = 0 + end + end + else + local dn = data[name] + if dn then + local parent = dn.parent + if parent then + name = parent + dn = data[name] + end + if trace_set then + report_marks("action %a, name %a, index %a","reset",name,topofstack) + end + dn.reset = topofstack + local children = dn.children + if children then + for i=1,#children do + local ci = children[i] + reset(ci) + end + end + end + end +end + +marks.reset = reset + +function marks.get(n,name,value) + local dn = data[name] + if dn then + name = dn.parent or name + local top = stack[n] + if top then + context(top[name]) + end + end +end + +function marks.show(first,last) + if first and last then + for k=first,last do + local v = stack[k] + if v then + report_marks("% 4i: %s",k,table.sequenced(v)) + end + end + else + for k, v in table.sortedpairs(stack) do + report_marks("% 4i: %s",k,table.sequenced(v)) + end + end +end + +local function resolve(name,first,last,strict,quitonfalse,notrace) + local dn = data[name] + if dn then + local child = name + local parent = dn.parent + name = parent or child + dn = data[name] + local step, method + if first > last then + step, method = -1, "bottom-up" + else + step, method = 1, "top-down" + end + if trace_get and not notrace then + report_marks("action %a, strategy %a, name %a, parent %a, strict %a","request",method,child,parent,strict or false) + end + if trace_details and not notrace then + marks.show(first,last) + end + local r = dn.reset + local s = dn.set + if first <= last and first <= r then + if trace_get and not notrace then + report_marks("action %a, name %a, first %a, last %a, reset %a, index %a","reset first",name,first,last,r,first) + end + elseif first >= last and last <= r then + if trace_get and not notrace then + report_marks("action %a, name %a, first %a, last %a, reset %a, index %a","reset last",name,first,last,r,last) + end + elseif not stack[first] or not stack[last] then + if trace_get and not notrace then + -- a previous or next method can give an out of range, which is valid + report_marks("error: out of range, name %a, reset %a, index %a",name,r,first) + end + elseif strict then + local top = stack[first] + local fullchain = dn.fullchain + if not fullchain or #fullchain == 0 then + if trace_get and not notrace then + report_marks("warning: no full chain, trying again, name %a, first %a, last %a",name,first,last) + end + return resolve(name,first,last) + else + if trace_get and not notrace then + report_marks("found chain [ % => T ]",fullchain) + end + local chaindata = { } + local chainlength = #fullchain + for i=1,chainlength do + local cname = fullchain[i] + if data[cname].set > 0 then + local value = resolve(cname,first,last,false,false,true) + if value == "" then + if trace_get and not notrace then + report_marks("quitting chain, name %a, reset %a, start %a",name,r,first) + end + return "" + else + chaindata[i] = value + end + end + end + if trace_get and not notrace then + report_marks("using chain [ % => T ]",chaindata) + end + local value, index, found = resolve(name,first,last,false,false,true) + if value ~= "" then + if trace_get and not notrace then + report_marks("following chain [ % => T ]",chaindata) + end + for i=1,chainlength do + local cname = fullchain[i] + if data[cname].set > 0 and chaindata[i] ~= found[cname] then + if trace_get and not notrace then + report_marks("quiting chain, name %a, reset %a, index %a",name,r,first) + end + return "" + end + end + if trace_get and not notrace then + report_marks("found in chain, name %a, reset %a, start %a, index %a, value %a",name,r,first,index,value) + end + return value, index, found + elseif trace_get and not notrace then + report_marks("not found, name %a, reset %a",name,r) + end + end + else + for i=first,last,step do + local current = stack[i] + local value = current and current[name] + if value == nil then + -- search on + elseif value == false then + if quitonfalse then + return "" + end + elseif value == true then + if trace_get and not notrace then + report_marks("quitting steps, name %a, reset %a, start %a, index %a",name,r,first,i) + end + return "" + elseif value ~= "" then + if trace_get and not notrace then + report_marks("found in steps, name %a, reset %a, start %a, index %a, value %a",name,r,first,i,value) + end + return value, i, current + end + end + if trace_get and not notrace then + report_marks("not found in steps, name %a, reset %a",name,r) + end + end + end + return "" +end + +-- todo: column:first column:last + +local methods = { } + +local function doresolve(name,rangename,swap,df,dl,strict) + local range = ranges[rangename] or ranges[v_page] + local first = range.first + local last = range.last + if trace_get then + report_marks("action %a, name %a, range %a, swap %a, first %a, last %a, df %a, dl %a, strict %a", + "resolving",name,rangename,swap or false,first,last,df,dl,strict or false) + end + if swap then + first, last = last + df, first + dl + else + first, last = first + df, last + dl + end + local value, index, found = resolve(name,first,last,strict) + -- maybe something more + return value, index, found +end + +-- previous : last before sync +-- next : first after sync + +-- top : first in sync +-- bottom : last in sync + +-- first : first not top in sync +-- last : last not bottom in sync + +methods[v_previous] = function(name,range) return doresolve(name,range,false,-1,0,true ) end -- strict +methods[v_top] = function(name,range) return doresolve(name,range,false, 0,0,true ) end -- strict +methods[v_bottom] = function(name,range) return doresolve(name,range,true , 0,0,true ) end -- strict +methods[v_next] = function(name,range) return doresolve(name,range,true , 0,1,true ) end -- strict + +methods[v_previous_nocheck] = function(name,range) return doresolve(name,range,false,-1,0,false) end +methods[v_top_nocheck] = function(name,range) return doresolve(name,range,false, 0,0,false) end +methods[v_bottom_nocheck] = function(name,range) return doresolve(name,range,true , 0,0,false) end +methods[v_next_nocheck] = function(name,range) return doresolve(name,range,true , 0,1,false) end + +local function do_first(name,range,check) + if trace_get then + report_marks("action %a, name %a, range %a","resolving first",name,range) + end + local f_value, f_index, f_found = doresolve(name,range,false,0,0,check) + if f_found then + if trace_get then + report_marks("action %a, name %a, range %a","resolving last",name,range) + end + local l_value, l_index, l_found = doresolve(name,range,true ,0,0,check) + if l_found and l_index > f_index then + local name = parentname(name) + for i=f_index,l_index,1 do + local si = stack[i] + local sn = si[name] + if sn and sn ~= false and sn ~= true and sn ~= "" and sn ~= f_value then + if trace_get then + report_marks("action %a, name %a, range %a, index %a, value %a","resolving",name,range,i,sn) + end + return sn, i, si + end + end + end + end + if trace_get then + report_marks("resolved, name %a, range %a, using first",name,range) + end + return f_value, f_index, f_found +end + +local function do_last(name,range,check) + if trace_get then + report_marks("action %a, name %a, range %a","resolving last",name,range) + end + local l_value, l_index, l_found = doresolve(name,range,true ,0,0,check) + if l_found then + if trace_get then + report_marks("action %a, name %a, range %a","resolving first",name,range) + end + local f_value, f_index, f_found = doresolve(name,range,false,0,0,check) + if f_found and l_index > f_index then + local name = parentname(name) + for i=l_index,f_index,-1 do + local si = stack[i] + local sn = si[name] + if sn and sn ~= false and sn ~= true and sn ~= "" and sn ~= l_value then + if trace_get then + report_marks("action %a, name %a, range %a, index %a, value %a","resolving",name,range,i,sn) + end + return sn, i, si + end + end + end + end + if trace_get then + report_marks("resolved, name %a, range %a, using first",name,range) + end + return l_value, l_index, l_found +end + +methods[v_first ] = function(name,range) return do_first(name,range,true ) end +methods[v_last ] = function(name,range) return do_last (name,range,true ) end +methods[v_first_nocheck] = function(name,range) return do_first(name,range,false) end +methods[v_last_nocheck ] = function(name,range) return do_last (name,range,false) end + +methods[v_current] = function(name,range) -- range is ignored here + local top = stack[topofstack] + return top and top[parentname(name)] or "" +end + +local function fetched(name,range,method) + local value = (methods[method] or methods[v_first])(name,range) or "" + if not trace_get then + -- no report + elseif value == "" then + report_marks("nothing fetched, name %a, range %a, method %a",name,range,method) + else + report_marks("marking fetched, name %a, range %a, method %a, value %a",name,range,method,value) + end + return value or "" +end + +-- can be used at the lua end: + +marks.fetched = fetched + +-- this will move to a separate runtime modules + +marks.tracers = marks.tracers or { } + +function marks.tracers.showtable() + context.starttabulate { "|l|l|l|lp|lp|" } + context.tabulaterowbold("name","parent","chain","children","fullchain") + context.ML() + for k, v in table.sortedpairs(data) do + local parent = v.parent or "" + local chain = v.chain or "" + local children = v.children or { } + local fullchain = v.fullchain or { } + table.sort(children) -- in-place but harmless + context.tabulaterowtyp(k,parent,chain,concat(children," "),concat(fullchain," ")) + end + context.stoptabulate() +end + +-- pushing to context: + +-- local separator = context.nested.markingseparator +-- local command = context.nested.markingcommand +-- local ctxconcat = context.concat + +-- local function fetchonemark(name,range,method) +-- context(command(name,fetched(name,range,method))) +-- end + +-- local function fetchtwomarks(name,range) +-- ctxconcat( { +-- command(name,fetched(name,range,v_first)), +-- command(name,fetched(name,range,v_last)), +-- }, separator(name)) +-- end + +-- local function fetchallmarks(name,range) +-- ctxconcat( { +-- command(name,fetched(name,range,v_previous)), +-- command(name,fetched(name,range,v_first)), +-- command(name,fetched(name,range,v_last)), +-- }, separator(name)) +-- end + + local ctx_separator = context.markingseparator + local ctx_command = context.markingcommand + + local function fetchonemark(name,range,method) + ctx_command(name,fetched(name,range,method)) + end + + local function fetchtwomarks(name,range) + ctx_command(name,fetched(name,range,v_first)) + ctx_separator(name) + ctx_command(name,fetched(name,range,v_last)) + end + + local function fetchallmarks(name,range) + ctx_command(name,fetched(name,range,v_previous)) + ctx_separator(name) + ctx_command(name,fetched(name,range,v_first)) + ctx_separator(name) + ctx_command(name,fetched(name,range,v_last)) + end + +function marks.fetch(name,range,method) -- chapter page first | chapter column:1 first + if trace_get then + report_marks("marking requested, name %a, range %a, method %a",name,range,method) + end + if method == "" or method == v_default then + fetchonemark(name,range,v_first) + elseif method == v_both then + fetchtwomarks(name,range) + elseif method == v_all then + fetchallmarks(name,range) + else + fetchonemark(name,range,method) + end +end + +function marks.fetchonemark (name,range,method) fetchonemark (name,range,method) end +function marks.fetchtwomarks(name,range) fetchtwomarks(name,range ) end +function marks.fetchallmarks(name,range) fetchallmarks(name,range ) end + +-- here we have a few helpers .. will become commands.* + +local pattern = lpeg.afterprefix("li::") + +function marks.title(tag,n) + local listindex = lpegmatch(pattern,n) + if listindex then + commands.savedlisttitle(tag,listindex,"marking") + else + context(n) + end +end + +function marks.number(tag,n) -- no spec + local listindex = lpegmatch(pattern,n) + if listindex then + commands.savedlistnumber(tag,listindex) + else + -- no prefix (as it is the prefix) + context(n) + end +end + +-- interface + +implement { name = "markingtitle", actions = marks.title, arguments = "2 strings" } +implement { name = "markingnumber", actions = marks.number, arguments = "2 strings" } + +implement { name = "definemarking", actions = marks.define, arguments = "2 strings" } +implement { name = "relatemarking", actions = marks.relate, arguments = "2 strings" } +implement { name = "setmarking", actions = marks.set, arguments = "2 strings" } +implement { name = "resetmarking", actions = marks.reset, arguments = "string" } +implement { name = "synchronizemarking", actions = marks.synchronize, arguments = { "string", "integer", "string" } } +implement { name = "getmarking", actions = marks.fetch, arguments = "3 strings" } +implement { name = "fetchonemark", actions = marks.fetchonemark, arguments = "3 strings" } +implement { name = "fetchtwomarks", actions = marks.fetchtwomarks, arguments = "2 strings" } +implement { name = "fetchallmarks", actions = marks.fetchallmarks, arguments = "2 strings" } + +implement { name = "doifelsemarking", actions = { marks.exists, commands.doifelse }, arguments = "string" } diff --git a/tex/context/base/mkxl/strc-mar-old.mkxl b/tex/context/base/mkxl/strc-mar-old.mkxl new file mode 100644 index 000000000..b2c421dbf --- /dev/null +++ b/tex/context/base/mkxl/strc-mar-old.mkxl @@ -0,0 +1,142 @@ +%D \module +%D [ file=strc-mar, +%D version=2008.10.20, +%D title=\CONTEXT\ Structure Macros, +%D subtitle=Markings, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Structure Macros / Markings} + +\registerctxluafile{strc-mar-old}{autosuffix} + +\unprotect + +%D Synchronizing marks is a rather tricky and messy business. When setting a mark, a +%D node is added to the list in order for to \TEX\ be able to figure out the 3 +%D current marks when a page is made (last mark on previous page, first on current +%D page, last on current page; in \LUATEX\ we might at one point have the first on +%D the next page as well). +%D +%D Resetting a mark is not easy. An empty one will not erase the last one on the +%D previous page for instance. In \LUATEX\ we can clear a marks state register with +%D \type {\clearmarks} but since this is an immediate operation it might have +%D unwanted side effects when \TEX\ has collected several pages of text and +%D finishing off these pages uses marks. +%D +%D In \MKIV\ we provide an alternative model that permits some more control over the +%D way marks are used. It is not entirely compatible with \MKII\ or previous \MKIV\ +%D implementations but in practice this is not a real problem. It's also easier now +%D to extend this mechanism. + +% first last previous next top bottom [:nocheck] +% current +% default page all keep + +\definesystemattribute [marks] [global] + +\installcorenamespace{marking} + +\installcommandhandler \??marking {marking} \??marking + +\newconditional\inhibitgetmarking % will become private +\newconditional\inhibitsetmarking % will become private + +\newtoks \everymarking + +\appendtoks + \clf_definemarking{\currentmarking}{\currentmarkingparent}% +\to \everydefinemarking + +\permanent\protected\tolerant\def\relatemarking [#1]#*[#2]{\clf_relatemarking{#1}{#2}} +\permanent\protected\tolerant\def\resetmarking [#1]{\clf_resetmarking{#1}} +\permanent\protected\tolerant\def\synchronizemarking[#1]#*[#2]#*[#3]{\ifvoid#2\else\clf_synchronizemarking{#1}#2{#3}\fi} +\permanent \def\doifelsemarking #1{\clf_doifelsemarking{#1}} % no \noexpanded + +\aliased\let\clearmarking\resetmarking % different in the new situation + +\def\strc_markings_synchronize#1#2#3{\ifvoid#2\else\clf_synchronizemarking{#1}#2{#3}\fi} % called in page-ini + +\permanent\protected\tolerant\def\setmarking[#1]#:#2% + {\ifconditional\inhibitsetmarking\else + \doifelse{\namedmarkingparameter{#1}\c!expansion}\v!yes + {\clf_setmarking{#1}{#2}}% + {\clf_setmarking{#1}{\detokenize{#2}}}% + \fi} + +\aliased\let\marking \setmarking +\aliased\let\doifmarkingelse\doifelsemarking + +% defaults + +\setupmarking + [\c!expansion=\v!no, + \c!separator=\space\emdash\space, + \c!filtercommand=\firstofoneargument, + \c!state=\v!start] + +% fetching, regular interface + +\permanent\protected\def\getmarking + {\ifconditional\inhibitgetmarking + \expandafter\strc_markings_get_nop + \else + \expandafter\strc_markings_get_yes + \fi} + +\tolerant\def\strc_markings_get_nop[#-]#*[#-]#*[#-]% + {} + +\tolerant\def\strc_markings_get_yes[#1]#*[#2]#*[#3]% + {\ifcstok{\namedmarkingparameter{#1}\c!state}\v!start + \begingroup + \setsystemmode\v!marking + \the\everymarking + \ifparameter#3\or + \clf_getmarking{#1}{#2}{#3}% + \else + \clf_getmarking{#1}{\v!page}{#2}% + \fi + \endgroup + \fi} + +% the fetchers are fully expandable: [name][method] + +\permanent\tolerant\def\fetchonemark[#1]#*[#2]{\ifconditional\inhibitgetmarking\else\clf_fetchonemark {#1}{\v!page}{#2}\fi} +\permanent\tolerant\def\fetchtwomarks [#1]{\ifconditional\inhibitgetmarking\else\clf_fetchtwomarks{#1}{\v!page}\fi} +\permanent\tolerant\def\fetchallmarks [#1]{\ifconditional\inhibitgetmarking\else\clf_fetchallmarks{#1}{\v!page}\fi} + +\aliased\let\fetchmark\fetchonemark + +% also fully expandable but here we have: [name][range][method] + +\permanent\tolerant\def\fetchonemarking[#1]#*[#2]#*[#3]{\ifconditional\inhibitgetmarking\else\clf_fetchonemark {#1}{#2}{#3}\fi} +\permanent\tolerant\def\fetchtwomarkings [#1]#*[#2]{\ifconditional\inhibitgetmarking\else\clf_fetchtwomarks{#1}{#2}\fi} +\permanent\tolerant\def\fetchallmarkings [#1]#*[#2]{\ifconditional\inhibitgetmarking\else\clf_fetchallmarks{#1}{#2}\fi} + +\aliased\let\fetchmarking\fetchonemarking + +\permanent\def\markingseparator#1{\namedmarkingparameter{#1}\c!separator} +\permanent\def\markingcommand #1{\namedmarkingparameter{#1}\c!filtercommand} + +%D Experimental: +%D +%D \starttyping +%D \definemarking[boxmark] +%D +%D \setbox0\ruledvbox{ +%D \marking[boxmark]{tufte} \input tufte \par +%D \marking[boxmark]{ward} \input ward \par +%D } +%D +%D \synchronizemarking[zerobox][0] \box0 +%D +%D marks: (\getmarking[boxmark][zerobox][first],\getmarking[boxmark][zerobox][last]) +%D \stoptyping + +\protect \endinput diff --git a/tex/context/base/mkxl/strc-mar.lmt b/tex/context/base/mkxl/strc-mar.lmt index eb94f9fc3..e5266daf0 100644 --- a/tex/context/base/mkxl/strc-mar.lmt +++ b/tex/context/base/mkxl/strc-mar.lmt @@ -6,719 +6,143 @@ if not modules then modules = { } end modules ['strc-mar'] = { license = "see context related readme files" } --- todo: cleanup stack (structures.marks.reset(v_all) also does the job) --- todo: only commands.* print to tex, native marks return values - -local insert, concat = table.insert, table.concat -local tostring, next, rawget, type = tostring, next, rawget, type local lpegmatch = lpeg.match - -local context = context -local commands = commands - -local implement = interfaces.implement - -local allocate = utilities.storage.allocate -local setmetatableindex = table.setmetatableindex - -local nuts = nodes.nuts -local tonut = nuts.tonut - -local getid = nuts.getid -local getlist = nuts.getlist -local getattr = nuts.getattr -local getbox = nuts.getbox - -local nextnode = nuts.traversers.node - -local nodecodes = nodes.nodecodes -local whatsitcodes = nodes.whatsitcodes - -local glyph_code = nodecodes.glyph -local hlist_code = nodecodes.hlist -local vlist_code = nodecodes.vlist -local whatsit_code = nodecodes.whatsit - -local lateluawhatsit_code = whatsitcodes.latelua - -local texsetattribute = tex.setattribute - -local a_marks = attributes.private("marks") - -local trace_set = false trackers.register("marks.set", function(v) trace_set = v end) -local trace_get = false trackers.register("marks.get", function(v) trace_get = v end) -local trace_details = false trackers.register("marks.details", function(v) trace_details = v end) - -local report_marks = logs.reporter("structure","marks") - -local variables = interfaces.variables - -local v_first = variables.first -local v_last = variables.last -local v_previous = variables.previous -local v_next = variables.next -local v_top = variables.top -local v_bottom = variables.bottom -local v_current = variables.current -local v_default = variables.default -local v_page = variables.page -local v_all = variables.all -local v_keep = variables.keep - -local v_nocheck_suffix = ":" .. variables.nocheck - -local v_first_nocheck = variables.first .. v_nocheck_suffix -local v_last_nocheck = variables.last .. v_nocheck_suffix -local v_previous_nocheck = variables.previous .. v_nocheck_suffix -local v_next_nocheck = variables.next .. v_nocheck_suffix -local v_top_nocheck = variables.top .. v_nocheck_suffix -local v_bottom_nocheck = variables.bottom .. v_nocheck_suffix - -local structures = structures -local marks = structures.marks - -local settings_to_array = utilities.parsers.settings_to_array - -local boxes_too = false -- at some point we can also tag boxes or use a zero char - -directives.register("marks.boxestoo", function(v) boxes_too = v end) - -local data = marks.data or allocate() -marks.data = data - -storage.register("structures/marks/data", marks.data, "structures.marks.data") - -local stack, topofstack = { }, 0 - -local ranges = { - [v_page] = { - first = 0, - last = 0, - }, -} - -local function resolve(t,k) - if k then - if trace_set or trace_get then - report_marks("undefined mark, name %a",k) - end - local crap = { autodefined = true } -- maybe set = 0 and reset = 0 - t[k] = crap - return crap - else - -- weird: k is nil - end -end - -setmetatableindex(data, resolve) - -function marks.exists(name) - return rawget(data,name) ~= nil -end - --- identify range - -local function sweep(head,first,last) - for n, id, subtype in nextnode, head do - -- we need to handle empty heads so we test for latelua - if id == glyph_code or (id == whatsit_code and subtype == lateluawhatsit_code) then -- brrr - local a = getattr(n,a_marks) - if not a then - -- next - elseif first == 0 then - first, last = a, a - elseif a > last then - last = a - end - elseif id == hlist_code or id == vlist_code then - if boxes_too then - local a = getattr(n,a_marks) - if not a then - -- next - elseif first == 0 then - first, last = a, a - elseif a > last then - last = a - end - end - local list = getlist(n) +local setmetatableindex = table.setmetatableindex + +local context = context + +local implement = interfaces.implement +local variables = interfaces.variables + +local v_first = variables.first +local v_last = variables.last +local v_previous = variables.previous +local v_next = variables.next +local v_column = variables.column + +local nuts = nodes.nuts +local nextmark = nuts.traversers.mark +local getbox = nuts.getbox +local getid = nuts.getid +local getlist = nuts.getlist +local getindex = nuts.getindex +local getdata = nuts.getdata +----- setmark_code = nodes.markcodes.set +local flushmark_code = nodes.markcodes.flush +local hlist_code = nodes.nodecodes.hlist +local vlist_code = nodes.nodecodes.vlist + +local marks = { } +structures.marks = marks + +local markdata = setmetatableindex("table") +local pattern = lpeg.splitat(":") + +implement { + name = "synchronizemarking", + arguments = { "string", "integer", "integer" }, + actions = function(category,index,boxnumber) + local new = setmetatableindex("table") + local box = getbox(boxnumber) + while box and getid(box) == hlist_code do + box = getlist(box) + end + if box and getid(box) == vlist_code then + local list = getlist(box) if list then - first, last = sweep(list,first,last) - end - end - end - return first, last -end - -local classes = { } - -setmetatableindex(classes, function(t,k) local s = settings_to_array(k) t[k] = s return s end) - -local lasts = { } - -function marks.synchronize(class,n,option) - local box = getbox(n) - if box then - local first, last = sweep(getlist(box),0,0) - if option == v_keep and first == 0 and last == 0 then - if trace_get or trace_set then - report_marks("action %a, class %a, box %a","retain at synchronize",class,n) - end - -- todo: check if still valid first/last in range - first = lasts[class] or 0 - last = first - else - lasts[class] = last - local classlist = classes[class] - for i=1,#classlist do - local class = classlist[i] - local range = ranges[class] - if range then - range.first = first - range.last = last - else - range = { - first = first, - last = last, - } - ranges[class] = range - end - if trace_get or trace_set then - report_marks("action %a, class %a, first %a, last %a","synchronize",class,range.first,range.last) - end - end - end - elseif trace_get or trace_set then - report_marks("action %s, class %a, box %a","synchronize without content",class,n) - end -end - --- define etc - -local function resolve(t,k) - if k == "fullchain" then - local fullchain = { } - local chain = t.chain - while chain and chain ~= "" do - insert(fullchain,1,chain) - chain = data[chain].chain - end - t[k] = fullchain - return fullchain - elseif k == "chain" then - t[k] = "" - return "" - elseif k == "reset" or k == "set" then - t[k] = 0 - return 0 - elseif k == "parent" then - t[k] = false - return false - end -end - -function marks.define(name,settings) - if not settings then - settings = { } - elseif type(settings) == "string" then - settings = { parent = settings } - end - data[name] = settings - local parent = settings.parent - if parent == nil or parent == "" or parent == name then - settings.parent = false - else - local dp = data[parent] - if not dp then - settings.parent = false - elseif dp.parent then - settings.parent = dp.parent - end - end - setmetatableindex(settings, resolve) -end - -for k, v in next, data do - setmetatableindex(v,resolve) -- runtime loaded table -end - -local function parentname(name) - local dn = data[name] - return dn and dn.parent or name -end - -function marks.relate(name,chain) - local dn = data[name] - if dn and not dn.parent then - if chain and chain ~= "" then - dn.chain = chain - local dc = data[chain] - if dc then - local children = dc.children - if not children then - children = { } - dc.children = children - end - children[#children+1] = name - end - elseif trace_set then - report_marks("error: invalid relation, name %a, chain %a",name,chain) - end - end -end - -local function resetchildren(new,name) - local dn = data[name] - if dn and not dn.parent then - local children = dn.children - if children then - for i=1,#children do - local ci = children[i] - new[ci] = false - if trace_set then - report_marks("action %a, parent %a, child %a","reset",name,ci) - end - resetchildren(new,ci) - end - end - end -end - -function marks.set(name,value) - local dn = data[name] - if dn then - local child = name - local parent = dn.parent - if parent then - name = parent - dn = data[name] - end - dn.set = topofstack - if not dn.reset then - dn.reset = 0 -- in case of selfdefined - end - local top = stack[topofstack] - local new = { } - if top then - for k, v in next, top do - local d = data[k] - local r = d.reset or 0 - local s = d.set or 0 - if r <= topofstack and s < r then - new[k] = false - else - new[k] = v - end - end - end - resetchildren(new,name) - new[name] = value - topofstack = topofstack + 1 - stack[topofstack] = new - if trace_set then - if name == child then - report_marks("action %a, name %a, index %a, value %a","set",name,topofstack,value) - else - report_marks("action %a, parent %a, child %a, index %a, value %a","set",parent,child,topofstack,value) - end - end - texsetattribute("global",a_marks,topofstack) - end -end - -local function reset(name) - if v_all then - if trace_set then - report_marks("action %a","reset all") - end - stack = { } - for name, dn in next, data do - local parent = dn.parent - if parent then - dn.reset = 0 - dn.set = 0 - end - end - else - local dn = data[name] - if dn then - local parent = dn.parent - if parent then - name = parent - dn = data[name] - end - if trace_set then - report_marks("action %a, name %a, index %a","reset",name,topofstack) - end - dn.reset = topofstack - local children = dn.children - if children then - for i=1,#children do - local ci = children[i] - reset(ci) - end - end - end - end -end - -marks.reset = reset - -function marks.get(n,name,value) - local dn = data[name] - if dn then - name = dn.parent or name - local top = stack[n] - if top then - context(top[name]) - end - end -end - -function marks.show(first,last) - if first and last then - for k=first,last do - local v = stack[k] - if v then - report_marks("% 4i: %s",k,table.sequenced(v)) - end - end - else - for k, v in table.sortedpairs(stack) do - report_marks("% 4i: %s",k,table.sequenced(v)) - end - end -end - -local function resolve(name,first,last,strict,quitonfalse,notrace) - local dn = data[name] - if dn then - local child = name - local parent = dn.parent - name = parent or child - dn = data[name] - local step, method - if first > last then - step, method = -1, "bottom-up" - else - step, method = 1, "top-down" - end - if trace_get and not notrace then - report_marks("action %a, strategy %a, name %a, parent %a, strict %a","request",method,child,parent,strict or false) - end - if trace_details and not notrace then - marks.show(first,last) - end - local r = dn.reset - local s = dn.set - if first <= last and first <= r then - if trace_get and not notrace then - report_marks("action %a, name %a, first %a, last %a, reset %a, index %a","reset first",name,first,last,r,first) - end - elseif first >= last and last <= r then - if trace_get and not notrace then - report_marks("action %a, name %a, first %a, last %a, reset %a, index %a","reset last",name,first,last,r,last) - end - elseif not stack[first] or not stack[last] then - if trace_get and not notrace then - -- a previous or next method can give an out of range, which is valid - report_marks("error: out of range, name %a, reset %a, index %a",name,r,first) - end - elseif strict then - local top = stack[first] - local fullchain = dn.fullchain - if not fullchain or #fullchain == 0 then - if trace_get and not notrace then - report_marks("warning: no full chain, trying again, name %a, first %a, last %a",name,first,last) - end - return resolve(name,first,last) - else - if trace_get and not notrace then - report_marks("found chain [ % => T ]",fullchain) - end - local chaindata = { } - local chainlength = #fullchain - for i=1,chainlength do - local cname = fullchain[i] - if data[cname].set > 0 then - local value = resolve(cname,first,last,false,false,true) - if value == "" then - if trace_get and not notrace then - report_marks("quitting chain, name %a, reset %a, start %a",name,r,first) - end - return "" - else - chaindata[i] = value + for n, subtype in nextmark, list do + local class = getindex(n) + local entry = new[class] + if subtype == flushmark_code then + entry.first = false + entry.last = false + else + if not entry.first then + entry.first = n end + entry.last = n end end - if trace_get and not notrace then - report_marks("using chain [ % => T ]",chaindata) - end - local value, index, found = resolve(name,first,last,false,false,true) - if value ~= "" then - if trace_get and not notrace then - report_marks("following chain [ % => T ]",chaindata) - end - for i=1,chainlength do - local cname = fullchain[i] - if data[cname].set > 0 and chaindata[i] ~= found[cname] then - if trace_get and not notrace then - report_marks("quiting chain, name %a, reset %a, index %a",name,r,first) - end - return "" - end + for class, entry in next, new do + local first = entry.first + local last = entry.last + if last and first ~= last then + entry.last = getdata(last,true) end - if trace_get and not notrace then - report_marks("found in chain, name %a, reset %a, start %a, index %a, value %a",name,r,first,index,value) + if first then + entry.first = getdata(first,true) end - return value, index, found - elseif trace_get and not notrace then - report_marks("not found, name %a, reset %a",name,r) end + else + -- wipe empty columns end else - for i=first,last,step do - local current = stack[i] - local value = current and current[name] - if value == nil then - -- search on - elseif value == false then - if quitonfalse then - return "" - end - elseif value == true then - if trace_get and not notrace then - report_marks("quitting steps, name %a, reset %a, start %a, index %a",name,r,first,i) - end - return "" - elseif value ~= "" then - if trace_get and not notrace then - report_marks("found in steps, name %a, reset %a, start %a, index %a, value %a",name,r,first,i,value) - end - return value, i, current - end - end - if trace_get and not notrace then - report_marks("not found in steps, name %a, reset %a",name,r) - end - end - end - return "" -end - --- todo: column:first column:last - -local methods = { } - -local function doresolve(name,rangename,swap,df,dl,strict) - local range = ranges[rangename] or ranges[v_page] - local first = range.first - local last = range.last - if trace_get then - report_marks("action %a, name %a, range %a, swap %a, first %a, last %a, df %a, dl %a, strict %a", - "resolving",name,rangename,swap or false,first,last,df,dl,strict or false) - end - if swap then - first, last = last + df, first + dl - else - first, last = first + df, last + dl - end - local value, index, found = resolve(name,first,last,strict) - -- maybe something more - return value, index, found -end - --- previous : last before sync --- next : first after sync - --- top : first in sync --- bottom : last in sync - --- first : first not top in sync --- last : last not bottom in sync - -methods[v_previous] = function(name,range) return doresolve(name,range,false,-1,0,true ) end -- strict -methods[v_top] = function(name,range) return doresolve(name,range,false, 0,0,true ) end -- strict -methods[v_bottom] = function(name,range) return doresolve(name,range,true , 0,0,true ) end -- strict -methods[v_next] = function(name,range) return doresolve(name,range,true , 0,1,true ) end -- strict - -methods[v_previous_nocheck] = function(name,range) return doresolve(name,range,false,-1,0,false) end -methods[v_top_nocheck] = function(name,range) return doresolve(name,range,false, 0,0,false) end -methods[v_bottom_nocheck] = function(name,range) return doresolve(name,range,true , 0,0,false) end -methods[v_next_nocheck] = function(name,range) return doresolve(name,range,true , 0,1,false) end - -local function do_first(name,range,check) - if trace_get then - report_marks("action %a, name %a, range %a","resolving first",name,range) - end - local f_value, f_index, f_found = doresolve(name,range,false,0,0,check) - if f_found then - if trace_get then - report_marks("action %a, name %a, range %a","resolving last",name,range) - end - local l_value, l_index, l_found = doresolve(name,range,true ,0,0,check) - if l_found and l_index > f_index then - local name = parentname(name) - for i=f_index,l_index,1 do - local si = stack[i] - local sn = si[name] - if sn and sn ~= false and sn ~= true and sn ~= "" and sn ~= f_value then - if trace_get then - report_marks("action %a, name %a, range %a, index %a, value %a","resolving",name,range,i,sn) + -- wipe empty columns + end + local m = markdata[category] + if m then + local entry = m[index] + if entry then + local prev = index == 1 and m[#m] or m[index-1] + for class, data in next, entry do + local pcls = prev[class] + local last = pcls and pcls.last + if last then + local ncls = new[class] + ncls.previous = last + if not ncls.first then + ncls.first = last + end + if not ncls.last then + ncls.last = ncls.first + end end - return sn, i, si end end + m[index] = new + else + new.previous = "" + markdata[category] = { [index] = new } end - end - if trace_get then - report_marks("resolved, name %a, range %a, using first",name,range) - end - return f_value, f_index, f_found -end + -- inspect(data) + end, +} -local function do_last(name,range,check) - if trace_get then - report_marks("action %a, name %a, range %a","resolving last",name,range) - end - local l_value, l_index, l_found = doresolve(name,range,true ,0,0,check) - if l_found then - if trace_get then - report_marks("action %a, name %a, range %a","resolving first",name,range) - end - local f_value, f_index, f_found = doresolve(name,range,false,0,0,check) - if f_found and l_index > f_index then - local name = parentname(name) - for i=l_index,f_index,-1 do - local si = stack[i] - local sn = si[name] - if sn and sn ~= false and sn ~= true and sn ~= "" and sn ~= l_value then - if trace_get then - report_marks("action %a, name %a, range %a, index %a, value %a","resolving",name,range,i,sn) +implement { + name = "getsynchronizedmarking", + arguments = { "integer", "string", "string" }, + actions = function(class,category,what) + local category, n = lpegmatch(pattern,category) + local useddata = markdata[category] + if useddata then + local index = tonumber(n) or 1 + local data = useddata[index] + if data then + local entry = data[class] + if entry then + if what == v_first then + context(entry.first or "") + elseif what == v_last then + context(entry.last or "") + elseif what == v_previous then + context(entry.previous or "") + elseif what == v_next then + -- context(entry.next or "") -- will be done when i need it, unreliable anyway end - return sn, i, si end end end end - if trace_get then - report_marks("resolved, name %a, range %a, using first",name,range) - end - return l_value, l_index, l_found -end - -methods[v_first ] = function(name,range) return do_first(name,range,true ) end -methods[v_last ] = function(name,range) return do_last (name,range,true ) end -methods[v_first_nocheck] = function(name,range) return do_first(name,range,false) end -methods[v_last_nocheck ] = function(name,range) return do_last (name,range,false) end - -methods[v_current] = function(name,range) -- range is ignored here - local top = stack[topofstack] - return top and top[parentname(name)] or "" -end - -local function fetched(name,range,method) - local value = (methods[method] or methods[v_first])(name,range) or "" - if not trace_get then - -- no report - elseif value == "" then - report_marks("nothing fetched, name %a, range %a, method %a",name,range,method) - else - report_marks("marking fetched, name %a, range %a, method %a, value %a",name,range,method,value) - end - return value or "" -end - --- can be used at the lua end: - -marks.fetched = fetched - --- this will move to a separate runtime modules - -marks.tracers = marks.tracers or { } - -function marks.tracers.showtable() - context.starttabulate { "|l|l|l|lp|lp|" } - context.tabulaterowbold("name","parent","chain","children","fullchain") - context.ML() - for k, v in table.sortedpairs(data) do - local parent = v.parent or "" - local chain = v.chain or "" - local children = v.children or { } - local fullchain = v.fullchain or { } - table.sort(children) -- in-place but harmless - context.tabulaterowtyp(k,parent,chain,concat(children," "),concat(fullchain," ")) - end - context.stoptabulate() -end - --- pushing to context: - --- local separator = context.nested.markingseparator --- local command = context.nested.markingcommand --- local ctxconcat = context.concat - --- local function fetchonemark(name,range,method) --- context(command(name,fetched(name,range,method))) --- end - --- local function fetchtwomarks(name,range) --- ctxconcat( { --- command(name,fetched(name,range,v_first)), --- command(name,fetched(name,range,v_last)), --- }, separator(name)) --- end - --- local function fetchallmarks(name,range) --- ctxconcat( { --- command(name,fetched(name,range,v_previous)), --- command(name,fetched(name,range,v_first)), --- command(name,fetched(name,range,v_last)), --- }, separator(name)) --- end - - local ctx_separator = context.markingseparator - local ctx_command = context.markingcommand - - local function fetchonemark(name,range,method) - ctx_command(name,fetched(name,range,method)) - end - - local function fetchtwomarks(name,range) - ctx_command(name,fetched(name,range,v_first)) - ctx_separator(name) - ctx_command(name,fetched(name,range,v_last)) - end - - local function fetchallmarks(name,range) - ctx_command(name,fetched(name,range,v_previous)) - ctx_separator(name) - ctx_command(name,fetched(name,range,v_first)) - ctx_separator(name) - ctx_command(name,fetched(name,range,v_last)) - end +} -function marks.fetch(name,range,method) -- chapter page first | chapter column:1 first - if trace_get then - report_marks("marking requested, name %a, range %a, method %a",name,range,method) - end - if method == "" or method == v_default then - fetchonemark(name,range,v_first) - elseif method == v_both then - fetchtwomarks(name,range) - elseif method == v_all then - fetchallmarks(name,range) - else - fetchonemark(name,range,method) +implement { + name = "resetsynchronizedmarking", + arguments = "argument", + actions = function(category) + local category, n = lpegmatch(pattern,category) + markdata[category] = nil end -end - -function marks.fetchonemark (name,range,method) fetchonemark (name,range,method) end -function marks.fetchtwomarks(name,range) fetchtwomarks(name,range ) end -function marks.fetchallmarks(name,range) fetchallmarks(name,range ) end - --- here we have a few helpers .. will become commands.* +} local pattern = lpeg.afterprefix("li::") @@ -743,17 +167,5 @@ end -- interface -implement { name = "markingtitle", actions = marks.title, arguments = "2 strings" } -implement { name = "markingnumber", actions = marks.number, arguments = "2 strings" } - -implement { name = "definemarking", actions = marks.define, arguments = "2 strings" } -implement { name = "relatemarking", actions = marks.relate, arguments = "2 strings" } -implement { name = "setmarking", actions = marks.set, arguments = "2 strings" } -implement { name = "resetmarking", actions = marks.reset, arguments = "string" } -implement { name = "synchronizemarking", actions = marks.synchronize, arguments = { "string", "integer", "string" } } -implement { name = "getmarking", actions = marks.fetch, arguments = "3 strings" } -implement { name = "fetchonemark", actions = marks.fetchonemark, arguments = "3 strings" } -implement { name = "fetchtwomarks", actions = marks.fetchtwomarks, arguments = "2 strings" } -implement { name = "fetchallmarks", actions = marks.fetchallmarks, arguments = "2 strings" } - -implement { name = "doifelsemarking", actions = { marks.exists, commands.doifelse }, arguments = "string" } +implement { name = "markingtitle", actions = marks.title, arguments = "2 strings" } +implement { name = "markingnumber", actions = marks.number,arguments = "2 strings" } diff --git a/tex/context/base/mkxl/strc-mar.mkxl b/tex/context/base/mkxl/strc-mar.mkxl index fcce83173..a0767e609 100644 --- a/tex/context/base/mkxl/strc-mar.mkxl +++ b/tex/context/base/mkxl/strc-mar.mkxl @@ -34,13 +34,31 @@ %D implementations but in practice this is not a real problem. It's also easier now %D to extend this mechanism. -% first last previous next top bottom [:nocheck] +%D In \LUAMETATEX\ we have extended the marks mechanism with a few handy options. +%D First of all we have automigration built in for inserts and marks (so we no +%D longer need to do that in \LUA) and marks can be properly flushed. + +% \ifdefined\automigrationmode \automigrationmode0 \fi +% \starttext +% \dorecurse{10}{ +% \dontleavehmode\setbox0\hbox{SAMPLE #1}\box0 +% \marks\foomark{sample #1}% +% \samplefile{tufte}\par +% }% +% \stoptext + % current + +% column:n | n | column | etc ... now only column:n + % default page all keep -\definesystemattribute [marks] [global] +%definesystemattribute [marks] [global] \installcorenamespace{marking} +\installcorenamespace{markingclass} +\installcorenamespace{markingsyncs} +\installcorenamespace{markingfilter} \installcommandhandler \??marking {marking} \??marking @@ -49,24 +67,70 @@ \newtoks \everymarking +% \clf_definemarking{\currentmarking}{\currentmarkingparent}% + \appendtoks - \clf_definemarking{\currentmarking}{\currentmarkingparent}% + \ifcsname\??markingclass\currentmarking\endcsname\else + \ifempty\currentmarkingparent + \expandafter\newmarks\csname\??markingclass\currentmarking\endcsname + \expandafter\newtoks \csname\??markingsyncs\currentmarking\endcsname + \else + \expandafter\letcsname\??markingclass\currentmarking\expandafter\endcsname\csname\??markingclass\currentmarkingparent\endcsname + \expandafter\letcsname\??markingsyncs\currentmarking\expandafter\endcsname\csname\??markingsyncs\currentmarkingparent\endcsname + \fi + \fi \to \everydefinemarking -\permanent\protected\tolerant\def\relatemarking [#1]#*[#2]{\clf_relatemarking{#1}{#2}} -\permanent\protected\tolerant\def\resetmarking [#1]{\clf_resetmarking{#1}} -\permanent\protected\tolerant\def\synchronizemarking[#1]#*[#2]#*[#3]{\ifvoid#2\else\clf_synchronizemarking{#1}#2{#3}\fi} -\permanent \def\doifelsemarking #1{\clf_doifelsemarking{#1}} % no \noexpanded +\permanent\protected\tolerant\def\relatemarking[#1]#*[#2]% + {\ifarguments\or\else + \xtoksapp\csname\??markingsyncs#2\endcsname{% + \flushmarks\csname\??markingclass#1\endcsname + \noexpand\the\begincsname\??markingsyncs#1\endcsname + }% + \fi} + +\permanent\protected\tolerant\def\clearmarking[#1]% + {\ifarguments\else + \begingroup + \clearmarks\csname\??markingclass#1\endcsname + \enforced\let\flushmarks\clearmarks + \the\csname\??markingsyncs#1\endcsname + \endgroup + \fi} + +\permanent\protected\tolerant\def\resetmarking[#1]% + {\ifarguments\else + % probably best: \dontleavehmode + \the\csname\??markingsyncs#1\endcsname + \fi} -\aliased\let\clearmarking\resetmarking % different in the new situation +\permanent\protected\tolerant\def\resetsynchronizemarking[#1]% + {\clf_resetsynchronizemarking{#1}} -\def\strc_markings_synchronize#1#2#3{\ifvoid#2\else\clf_synchronizemarking{#1}#2{#3}\fi} % called in page-ini +\tolerant\def\synchronizemarking[#1]#*[#2]#*[#3]% #3: options + {\clf_synchronizemarking{#1}\plusone\numexpr#2\relax} + +\def\strc_markings_synchronize#1#2#3% category n box + {\ifvoid#3\orelse\ifcstok{#1}\v!page\else + \clf_synchronizemarking{#1}\numexpr#2\relax\numexpr#3\relax + \fi} + +\permanent\def\doifelsemarking#1% + {\ifcondition\ifcommandhandler\??marking{#1}% + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} \permanent\protected\tolerant\def\setmarking[#1]#:#2% - {\ifconditional\inhibitsetmarking\else - \doifelse{\namedmarkingparameter{#1}\c!expansion}\v!yes - {\clf_setmarking{#1}{#2}}% - {\clf_setmarking{#1}{\detokenize{#2}}}% + {\ifarguments\orelse\ifconditional\inhibitsetmarking\else + % probably best: \dontleavehmode + \the\csname\??markingsyncs#1\endcsname + \ifcstok{\namedmarkingparameter{#1}\c!expansion}\v!yes + \marks\csname\??markingclass#1\endcsname{#2}% + \else + \marks\csname\??markingclass#1\endcsname{\detokenize{#2}}% + \fi \fi} \aliased\let\marking \setmarking @@ -111,19 +175,85 @@ \endgroup \fi} +% previous : last before sync next : first after sync +% top : first in sync bottom : last in sync +% first|default : first not top in sync last : last not bottom in sync + +% current + +\defcsname\??markingfilter\v!previous\endcsname#1{\topmarks \csname\??markingclass#1\endcsname} +\defcsname\??markingfilter\v!next \endcsname#1{\botmarks \csname\??markingclass#1\endcsname} + +%defcsname\??markingfilter\v!top \endcsname#1{\topmarks \csname\??markingclass#1\endcsname} +\defcsname\??markingfilter\v!top \endcsname#1{\firstmarks \csname\??markingclass#1\endcsname} +\defcsname\??markingfilter\v!bottom \endcsname#1{\botmarks \csname\??markingclass#1\endcsname} + +\defcsname\??markingfilter\v!first \endcsname#1{\firstmarks \csname\??markingclass#1\endcsname} +\defcsname\??markingfilter\v!last \endcsname#1{\botmarks \csname\??markingclass#1\endcsname} + +\defcsname\??markingfilter\v!current \endcsname#1{\currentmarks\csname\??markingclass#1\endcsname} + +\letcsname\??markingfilter\v!default\expandafter\endcsname + \csname\??markingfilter\v!first \endcsname + % the fetchers are fully expandable: [name][method] -\permanent\tolerant\def\fetchonemark[#1]#*[#2]{\ifconditional\inhibitgetmarking\else\clf_fetchonemark {#1}{\v!page}{#2}\fi} -\permanent\tolerant\def\fetchtwomarks [#1]{\ifconditional\inhibitgetmarking\else\clf_fetchtwomarks{#1}{\v!page}\fi} -\permanent\tolerant\def\fetchallmarks [#1]{\ifconditional\inhibitgetmarking\else\clf_fetchallmarks{#1}{\v!page}\fi} +\def\strc_markings_fetch_one#1#2#3% + {\ifparameter#1\or + \ifconditional\inhibitgetmarking\else + \ifcstok{#2}\v!page + \markingcommand{#1}{\begincsname\??markingfilter#3\endcsname{#1}}% + \else + \markingcommand{#1}{\clf_getsynchronizedmarking{#1}{#2}}% + \fi + \fi + \fi} + +\def\strc_markings_fetch_two#1#2% + {\ifparameter#1\or + \ifconditional\inhibitgetmarking\else + \ifcstok{#2}\v!page + \markingcommand{#1}{\begincsname\??markingfilter\v!first\endcsname{#1}}% + \markingseparator{#1}% + \markingcommand{#1}{\begincsname\??markingfilter\v!last\endcsname{#1}}% + \else + \markingcommand{#1}{\clf_getsynchronizedmarking{#1}\v!first}% + \markingseparator{#1}% + \markingcommand{#1}{\clf_getsynchronizedmarking{#1}\v!last}% + \fi + \fi + \fi} + +\def\strc_markings_fetch_all#1#2% + {\ifparameter#1\or + \ifconditional\inhibitgetmarking\else + \ifcstok{#2}\v!page + \markingcommand{#1}{\begincsname\??markingfilter\v!previous\endcsname{#1}}% + \markingseparator{#1}% + \markingcommand{#1}{\begincsname\??markingfilter\v!first\endcsname{#1}}% + \markingseparator{#1}% + \markingcommand{#1}{\begincsname\??markingfilter\v!last\endcsname{#1}}% + \else + %\markingcommand{#1}{\begincsname\??markclass:\v!previous\endcsname{#1}}% + %\markingseparator{#1}% + \markingcommand{#1}{\clf_getsynchronizedmarking{#1}\v!first}% + \markingseparator{#1}% + \markingcommand{#1}{\clf_getsynchronizedmarking{#1}\v!last}% + \fi + \fi + \fi} + +\permanent\tolerant\def\fetchonemark [#1]#*[#2]{\strc_markings_fetch_one{#1}\v!page{#2}} +\permanent\tolerant\def\fetchtwomarks [#1]{\strc_markings_fetch_two{#1}\v!page} +\permanent\tolerant\def\fetchallmarks [#1]{\strc_markings_fetch_all{#1}\v!page} \aliased\let\fetchmark\fetchonemark % also fully expandable but here we have: [name][range][method] -\permanent\tolerant\def\fetchonemarking[#1]#*[#2]#*[#3]{\ifconditional\inhibitgetmarking\else\clf_fetchonemark {#1}{#2}{#3}\fi} -\permanent\tolerant\def\fetchtwomarkings [#1]#*[#2]{\ifconditional\inhibitgetmarking\else\clf_fetchtwomarks{#1}{#2}\fi} -\permanent\tolerant\def\fetchallmarkings [#1]#*[#2]{\ifconditional\inhibitgetmarking\else\clf_fetchallmarks{#1}{#2}\fi} +\permanent\tolerant\def\fetchonemarking [#1]#*[#2]#*[#3]{\strc_markings_fetch_one{#1}{#2}{#3}} +\permanent\tolerant\def\fetchtwomarkings [#1]#*[#2]{\strc_markings_fetch_two{#1}{#2}} +\permanent\tolerant\def\fetchallmarkings [#1]#*[#2]{\strc_markings_fetch_all{#1}{#2}} \aliased\let\fetchmarking\fetchonemarking diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua index 02f89ada1..72164b777 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 : 2021-10-08 20:05 +-- merge date : 2021-10-10 23:40 do -- begin closure to overcome local limits and interference -- cgit v1.2.3