diff options
Diffstat (limited to 'tex/context/base/strc-num.lua')
-rw-r--r-- | tex/context/base/strc-num.lua | 207 |
1 files changed, 64 insertions, 143 deletions
diff --git a/tex/context/base/strc-num.lua b/tex/context/base/strc-num.lua index b82132a00..0715a9e49 100644 --- a/tex/context/base/strc-num.lua +++ b/tex/context/base/strc-num.lua @@ -6,13 +6,12 @@ if not modules then modules = { } end modules ['strc-num'] = { license = "see context related readme files" } +-- this will be reimplemented and some more will move to the commands namespace + local format = string.format local next, type = next, type local min, max = math.min, math.max -local texcount, texsetcount = tex.count, tex.setcount - --- Counters are managed here. They can have multiple levels which makes it easier to synchronize --- them. Synchronization is sort of special anyway, as it relates to document structuring. +local texcount = tex.count local allocate = utilities.storage.allocate local setmetatableindex = table.setmetatableindex @@ -27,23 +26,8 @@ local counters = structures.counters local documents = structures.documents local variables = interfaces.variables -local v_start = variables.start -local v_page = variables.page -local v_reverse = variables.reverse -local v_first = variables.first -local v_next = variables.next -local v_previous = variables.previous -local v_prev = variables.prev -local v_last = variables.last ------ v_no = variables.no -local v_backward = variables.backward -local v_forward = variables.forward ------ v_subs = variables.subs or "subs" - --- states: start stop none reset - --- specials are used for counters that are set and incremented in special ways, like --- pagecounters that get this treatment in the page builder + +-- state: start stop none reset counters.specials = counters.specials or { } local counterspecials = counters.specials @@ -82,83 +66,54 @@ end job.register('structures.counters.collected', tobesaved, initializer, finalizer) -local constructor = { -- maybe some day we will provide an installer for more variants - - last = function(t,name,i) +local function constructor(t,s,name,i) -- variables ? + if s == "last" then local cc = collected[name] - local stop = (cc and cc[i] and cc[i][t.range]) or 0 -- stop is available for diagnostics purposes only - t.stop = stop + t.stop = (cc and cc[i] and cc[i][t.range]) or 0 -- stop is available for diagnostics purposes only if t.offset then - return stop - t.step + return t.stop - t.step else - return stop + return t.stop end - end, - - first = function(t,name,i) - local start = t.start - if start > 0 then - return start -- brrr + elseif s == "first" then + if t.start > 0 then + return t.start -- brrr elseif t.offset then - return start + t.step + 1 + return t.start + t.step + 1 else - return start + 1 + return t.start + 1 end - end, - - prev = function(t,name,i) + elseif s == "prev" or s == "previous" then return max(t.first,t.number-1) -- todo: step - end, - - previous = function(t,name,i) - return max(t.first,t.number-1) -- todo: step - end, - - next = function(t,name,i) + elseif s == "next" then return min(t.last,t.number+1) -- todo: step - end, - - backward =function(t,name,i) + elseif s == "backward" then if t.number - 1 < t.first then return t.last else return t.previous end - end, - - forward = function(t,name,i) + elseif s == "forward" then if t.number + 1 > t.last then return t.first else return t.next end - end, - - subs = function(t,name,i) + elseif s == "subs" then local cc = collected[name] t.subs = (cc and cc[i+1] and cc[i+1][t.range]) or 0 return t.subs - end, - -} - -local function dummyconstructor(t,name,i) - return nil -- was 0, but that is fuzzy in testing for e.g. own -end - -setmetatableindex(constructor,function(t,k) - if trace_counters then - report_counters("unknown constructor %q",tostring(k)) + else + return nil -- was 0, but that is fuzzy in testing for e.g. own end - return dummyconstructor -end) +end local function enhance() for name, cd in next, counterdata do local data = cd.data for i=1,#data do local ci = data[i] - setmetatableindex(ci, function(t,s) return constructor[s](t,name,i) end) + setmetatableindex(ci, function(t,s) return constructor(t,s,name,i) end) end end enhance = nil @@ -171,7 +126,7 @@ local function allocate(name,i) -- can be metatable level = 1, -- block = "", -- todo numbers = nil, - state = v_start, -- true + state = variables.start, -- true data = { }, saved = { }, } @@ -190,7 +145,7 @@ local function allocate(name,i) -- can be metatable offset = false, stop = 0, -- via metatable: last, first, stop only for tracing } - setmetatableindex(ci, function(t,s) return constructor[s](t,name,i) end) + setmetatableindex(ci, function(t,s) return constructor(t,s,name,i) end) cd[i] = ci tobesaved[name][i] = { } else @@ -209,12 +164,12 @@ local function savevalue(name,i) local cs = tobesaved[name][i] local cc = collected[name] if trace_counters then - report_counters("saving, counter: %s, value: %s",name,cd.number) + report_counters("saving value %s of counter named %s",cd.number,name) end local cr = cd.range local old = (cc and cc[i] and cc[i][cr]) or 0 local number = cd.number - if cd.method == v_page then + if cd.method == variables.page then -- we can be one page ahead number = number - 1 end @@ -231,8 +186,8 @@ function counters.define(specification) if name and name ~= "" then -- todo: step local d = allocate(name,1) - d.start = tonumber(specification.start) or 0 - d.state = v_state or "" + d.start = specification.start + d.state = variables.start or "" local counter = specification.counter if counter and counter ~= "" then d.counter = counter -- only for special purposes, cannot be false @@ -247,15 +202,18 @@ end function counters.compact(name,level,onlynumbers) local cd = counterdata[name] +--~ print(name,cd) if cd then local data = cd.data local compact = { } for i=1,level or #data do local d = data[i] +--~ print(name,i,d.number) if d.number ~= 0 then compact[i] = (onlynumbers and d.number) or d end end +--~ print(table.serialize(compact)) return compact end end @@ -288,76 +246,65 @@ function counters.subs(name,n) return counterdata[name].data[n].subs or 0 end -local function setvalue(name,tag,value) +function counters.setvalue(name,tag,value) local cd = counterdata[name] if cd then cd[tag] = value end end -counters.setvalue = setvalue - function counters.setstate(name,value) -- true/false value = variables[value] if value then - setvalue(name,"state",value) + counters.setvalue(name,"state",value) end end function counters.setlevel(name,value) - setvalue(name,"level",value) + counters.setvalue(name,"level",value) end function counters.setoffset(name,value) - setvalue(name,"offset",value) + counters.setvalue(name,"offset",value) end local function synchronize(name,d) local dc = d.counter if dc then if trace_counters then - report_counters("synchronize, counter: %s, name: %s, value: %s, action: setting",dc,name,d.number) + report_counters("setting counter %s with name %s to %s",dc,name,d.number) end - texsetcount("global",dc,d.number) + tex.setcount("global",dc,d.number) end local cs = counterspecials[name] if cs then if trace_counters then - report_counters("synchronize, counter: %s, name: %s, action: special",dc,name) + report_counters("invoking special for name %s",name) end - cs(name) + cs() end end -local function reset(name,n) +function counters.reset(name,n) local cd = counterdata[name] if cd then for i=n or 1,#cd.data do local d = cd.data[i] savevalue(name,i) - local number = d.start or 0 - d.number = number + d.number = d.start or 0 d.own = nil - if trace_counters then - report_counters("resetting, name: %s, sub: %s, value: %s",name,i,number) - end synchronize(name,d) end cd.numbers = nil - else end end -local function set(name,n,value) +function counters.set(name,n,value) local cd = counterdata[name] if cd then local d = allocate(name,n) - local number = value or 0 - d.number = number + d.number = value or 0 d.own = nil - if trace_counters then - report_counters("setting, name: %s, value: %s",name,number) - end synchronize(name,d) end end @@ -366,19 +313,12 @@ local function check(name,data,start,stop) for i=start or 1,stop or #data do local d = data[i] savevalue(name,i) - local number = d.start or 0 - d.number = number + d.number = d.start or 0 d.own = nil - if trace_counters then - report_counters("checking, name: %s, sub: %s, value: %s",name,i,number) - end synchronize(name,d) end end -counters.reset = reset -counters.set = set - function counters.setown(name,n,value) local cd = counterdata[name] if cd then @@ -388,7 +328,7 @@ function counters.setown(name,n,value) local level = cd.level if not level or level == -1 then -- -1 is signal that we reset manually - elseif level > 0 or level == -3 then + elseif level > 0 then check(name,d,n+1) elseif level == 0 then -- happens elsewhere, check this for block @@ -405,7 +345,7 @@ function counters.restart(name,n,newstart,noreset) local d = allocate(name,n) d.start = newstart if not noreset then - reset(name,n) -- hm + counters.reset(name,n) -- hm end end end @@ -427,38 +367,24 @@ end function counters.add(name,n,delta) local cd = counterdata[name] - if cd and (cd.state == v_start or cd.state == "") then +-- inspect(cd) + if cd and (cd.state == variables.start or cd.state == "") then local data = cd.data local d = allocate(name,n) d.number = (d.number or d.start or 0) + delta*(d.step or 0) -- d.own = nil local level = cd.level +-- print(name,n,delta,level) if not level or level == -1 then -- -1 is signal that we reset manually - if trace_counters then - report_counters("adding, name: %s, level: manually, action: no checking",name) - end elseif level == -2 then -- -2 is signal that we work per text - if trace_counters then - report_counters("adding, name: %s, level: text, action: checking",name) - end check(name,data,n+1) - elseif level > 0 or level == -3 then + elseif level > 0 then -- within countergroup - if trace_counters then - report_counters("adding, name: %s, level: %s, action: checking within group",name,level) - end check(name,data,n+1) elseif level == 0 then -- happens elsewhere - if trace_counters then - report_counters("adding, name: %s, level: %s, action: no checking",name,level) - end - else - if trace_counters then - report_counters("adding, name: %s, level: unknown, action: no checking",name) - end end synchronize(name,d) return d.number -- not needed @@ -466,23 +392,19 @@ function counters.add(name,n,delta) return 0 end -function counters.check(level) +function counters.check(level) -- not used (yet) for name, cd in next, counterdata do - if level > 0 and cd.level == -3 then -- could become an option + -- report_counters("%s %s %s",name,cd.level,level) + if cd.level == level then if trace_counters then - report_counters("resetting, name: %s, level: %s (head)",name,level) + report_counters("resetting %s at level %s",name,level) end - reset(name) - elseif cd.level == level then - if trace_counters then - report_counters("resetting, name: %s, level: %s (normal)",name,level) - end - reset(name) + counters.reset(name) end end end -local function get(name,n,key) +function counters.get(name,n,key) local d = allocate(name,n) d = d and d[key] if not d then @@ -494,10 +416,8 @@ local function get(name,n,key) end end -counters.get = get - function counters.value(name,n) -- what to do with own - return get(name,n or 1,'number') or 0 + return counters.get(name,n or 1,'number') or 0 end function counters.converted(name,spec) -- name can be number and reference to storage @@ -511,8 +431,9 @@ function counters.converted(name,spec) -- name can be number and reference to st if cd then local spec = spec or { } local numbers, ownnumbers = { }, { } - local reverse = spec.order == v_reverse + local reverse = spec.order == variables.reverse local kind = spec.type or "number" + local v_first, v_next, v_previous, v_last = variables.first, variables.next, variables.previous, variables.last local data = cd.data for k=1,#data do local v = data[k] @@ -525,7 +446,7 @@ function counters.converted(name,spec) -- name can be number and reference to st vn = v.first elseif kind == v_next then vn = v.next - elseif kind == v_prev or kind == v_previous then + elseif kind == v_previous then vn = v.prev elseif kind == v_last then vn = v.last @@ -577,7 +498,7 @@ function commands.showcounter(name) local data = cd.data for i=1,#data do local d = data[i] - context(" (%s: %s,%s,%s s:%s r:%s)",i,d.start or 0,d.number or 0,d.last,d.step or 0,d.range or 0) + context(" (%s: %s,%s,%s s:%s r:%s)",i,(d.start or 0),d.number or 0,d.last,d.step or 0,d.range or 0) end context("]") end @@ -622,7 +543,7 @@ end --~ return cd, false, "no section data" --~ end --~ -- local preferences ---~ local no = v_no +--~ local no = variables.no --~ if counterspecification and counterspecification.prefix == no then --~ return cd, false, "current spec blocks prefix" --~ end |