diff options
Diffstat (limited to 'Master/texmf-dist/tex/context/base/strc-doc.lua')
-rw-r--r-- | Master/texmf-dist/tex/context/base/strc-doc.lua | 163 |
1 files changed, 131 insertions, 32 deletions
diff --git a/Master/texmf-dist/tex/context/base/strc-doc.lua b/Master/texmf-dist/tex/context/base/strc-doc.lua index cb279e32065..7faf0d5b393 100644 --- a/Master/texmf-dist/tex/context/base/strc-doc.lua +++ b/Master/texmf-dist/tex/context/base/strc-doc.lua @@ -1,21 +1,28 @@ if not modules then modules = { } end modules ['strc-doc'] = { version = 1.001, - comment = "companion to strc-doc.tex", + comment = "companion to strc-doc.mkiv", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", copyright = "PRAGMA ADE / ConTeXt Development Team", license = "see context related readme files" } +-- todo: associate counter with head + +-- we need to freeze and document this module + local next, type = next, type -local format, gsub, find, concat = string.format, string.gsub, string.find, table.concat +local format, gsub, find, concat, gmatch, match = string.format, string.gsub, string.find, table.concat, string.gmatch, string.match local texsprint, texwrite = tex.sprint, tex.write +local concat = table.concat +local max, min = math.max, math.min local ctxcatcodes = tex.ctxcatcodes local variables = interfaces.variables -if not trackers then trackers = { register = function() end } end +--~ if not trackers then trackers = { register = function() end } end local trace_sectioning = false trackers.register("structure.sectioning", function(v) trace_sectioning = v end) +local trace_detail = false trackers.register("structure.detail", function(v) trace_detail = v end) local function report(...) --~ print(...) @@ -58,7 +65,7 @@ function documents.reset() data.forced = { } data.ownnumbers = { } data.status = { } - data.checkers = { } +--~ data.checkers = { } data.depth = 0 end @@ -130,6 +137,8 @@ storage.register("structure/sections/levelmap", structure.sections.levelmap, "st sections.verbose = true +levelmap.block = -1 + function sections.setlevel(name,level) -- level can be number or parent (=string) local l = tonumber(level) if not l then @@ -157,6 +166,7 @@ function sections.setblock(name) end function sections.pushblock(name) + structure.counters.check(0) -- we assume sane usage of \page between blocks local block = name or data.block data.blocks[#data.blocks+1] = block data.block = block @@ -187,15 +197,18 @@ end function sections.somelevel(given) -- old number local numbers, ownnumbers, forced, status, olddepth = data.numbers, data.ownnumbers, data.forced, data.status, data.depth ---~ print("old",olddepth,given.metadata.name,levelmap[given.metadata.name]) - local newdepth = tonumber(levelmap[given.metadata.name] or (olddepth > 0 and olddepth) or 1) -- hm, levelmap only works for section-* ---~ print("new",newdepth) + local givenname = given.metadata.name + local mappedlevel = levelmap[givenname] + local newdepth = tonumber(mappedlevel or (olddepth > 0 and olddepth) or 1) -- hm, levelmap only works for section-* local directives = given.directives local resetset = (directives and directives.resetset) or "" - local resetter = sets.getall("structure:resets",data.block,resetset) + -- local resetter = sets.getall("structure:resets",data.block,resetset) -- a trick to permits userdata to overload title, ownnumber and reference -- normally these are passed as argument but nowadays we provide several -- interfaces (we need this because we want to be compatible) + if trace_detail then + logs.report("structure","name '%s', mapped level '%s', old depth '%s', new depth '%s', reset set '%s'",givenname,mappedlevel,olddepth,newdepth,resetset) + end local u = given.userdata if u then -- kind of obsolete as we can pass them directly anyway @@ -209,7 +222,9 @@ function sections.somelevel(given) if newdepth > olddepth then for i=olddepth+1,newdepth do local s = tonumber(sets.get("structure:resets",data.block,resetset,i)) ---~ logs.report("structure >","old: %s, new:%s, reset: %s (%s: %s)",olddepth,newdepth,s,resetset,table.concat(resetter,",")) + if trace_detail then + logs.report("structure","new>old (%s>%s), reset set '%s', reset value '%s', current '%s'",olddepth,newdepth,resetset,s or "?",numbers[i] or "?") + end if not s or s == 0 then numbers[i] = numbers[i] or 0 ownnumbers[i] = ownnumbers[i] or "" @@ -222,7 +237,9 @@ function sections.somelevel(given) elseif newdepth < olddepth then for i=olddepth,newdepth+1,-1 do local s = tonumber(sets.get("structure:resets",data.block,resetset,i)) ---~ logs.report("structure <","old: %s, new:%s, reset: %s (%s: %s)",olddepth,newdepth,s,resetset,table.concat(resetter,",")) + if trace_detail then + logs.report("structure","new<old (%s<%s), reset set '%s', reset value '%s', current '%s'",olddepth,newdepth,resetset,s or "?",numbers[i] or "?") + end if not s or s == 0 then numbers[i] = numbers[i] or 0 ownnumbers[i] = ownnumbers[i] or "" @@ -233,13 +250,14 @@ function sections.somelevel(given) status[i] = nil end end + structure.counters.check(newdepth) ownnumbers[newdepth] = given.numberdata.ownnumber or "" given.numberdata.ownnumber = nil data.depth = newdepth -- new number olddepth = newdepth if given.metadata.increment then - local oldn, newn = numbers[newdepth], 0 + local oldn, newn = numbers[newdepth] or 0, 0 local fd = forced[newdepth] if fd then if fd[1] == "add" then @@ -251,21 +269,31 @@ function sections.somelevel(given) newn = 1 -- maybe zero is nicer end forced[newdepth] = nil + if trace_detail then + logs.report("structure","old depth '%s', new depth '%s, old n '%s', new n '%s', forced '%s'",olddepth,newdepth,oldn,newn,concat(fd,"")) + end elseif newn then newn = oldn + 1 + if trace_detail then + logs.report("structure","old depth '%s', new depth '%s, old n '%s', new n '%s', increment",olddepth,newdepth,oldn,newn) + end else local s = tonumber(sets.get("structure:resets",data.block,resetset,newdepth)) ---~ logs.report("structure =","old: %s, new:%s, reset: %s (%s: %s)",olddepth,newdepth,s,resetset,table.concat(resetter,",")) - if not s or s == 0 then + if not s then + newn = oldn or 0 + elseif s == 0 then newn = oldn or 0 else newn = s - 1 end + if trace_detail then + logs.report("structure","old depth '%s', new depth '%s, old n '%s', new n '%s', reset",olddepth,newdepth,oldn,newn) + end end numbers[newdepth] = newn end status[newdepth] = given or { } - for k, v in pairs(data.checkers) do + for k, v in next, data.checkers do if v[1] == newdepth and v[2] then v[2](k) end @@ -284,6 +312,9 @@ function sections.somelevel(given) if #ownnumbers > 0 then numberdata.ownnumbers = table.fastcopy(ownnumbers) end + if trace_detail then + logs.report("structure","name '%s', numbers '%s', own numbers '%s'",givenname,concat(numberdata.numbers, " "),concat(numberdata.ownnumbers, " ")) + end given.references.section = sections.save(given) -- given.numberdata = nil end @@ -293,7 +324,7 @@ function sections.writestatus() local numbers, ownnumbers, status, depth = data.numbers, data.ownnumbers, data.status, data.depth local d = status[depth] local o = concat(ownnumbers,".",1,depth) - local n = (numbers and concat(numbers,".",1,depth)) or 0 + local n = (numbers and concat(numbers,".",1,min(depth,#numbers))) or 0 local l = d.titledata.title or "" local t = (l ~= "" and l) or d.titledata.title or "[no title]" local m = d.metadata.name @@ -310,7 +341,7 @@ end function sections.setnumber(depth,n) local forced, depth, new = data.forced, depth or data.depth, tonumber(n) if type(n) == "string" then - if n:find("^[%+%-]") then + if find(n,"^[%+%-]") then forced[depth] = { "add", new } else forced[depth] = { "set", new } @@ -324,8 +355,25 @@ function sections.number_at_depth(depth) return data.numbers[tonumber(depth) or sections.getlevel(depth) or 0] or 0 end -function sections.getnumber(depth) - return texwrite(data.numbers[depth] or 0) +function sections.numbers() + return data.numbers +end + +function sections.matching_till_depth(depth,numbers,parentnumbers) + local dn = parentnumbers or data.numbers + local ok = false + for i=1,depth do + if dn[i] == numbers[i] then + ok = true + else + return false + end + end + return ok +end + +function sections.getnumber(depth) -- redefined later ... + texwrite(data.numbers[depth] or 0) end function sections.set(key,value) @@ -341,7 +389,7 @@ function sections.structuredata(depth,key,default,honorcatcodetable) -- todo: sp if not depth or depth == 0 then depth = data.depth end local data = data.status[depth] local d = data - for k in key:gmatch("([^.]+)") do + for k in gmatch(key,"([^.]+)") do if type(d) == "table" then d = d[k] if not d then @@ -383,8 +431,8 @@ function sections.userdata(depth,key,default) end end -function sections.setchecker(name,level,command) - data.checkers[name] = (name and command and level > 0 and { level, command }) or nil +function sections.setchecker(name,level,command) -- hm, checkers are not saved + data.checkers[name] = (name and command and level >= 0 and { level, command }) or nil end function sections.current() @@ -432,16 +480,20 @@ function sections.typesetnumber(entry,kind,...) -- kind='section','number','pref local conversionset = "" local conversion = "" local stopper = "" + local starter = "" local connector = "" local set = "" local segments = "" local criterium = "" - for _, data in ipairs { ... } do -- can be multiple parametersets + local dataset = { ... } + for d=1,#dataset do + local data = dataset[d] -- can be multiple parametersets if data then if separatorset == "" then separatorset = data.separatorset or "" end if conversionset == "" then conversionset = data.conversionset or "" end if conversion == "" then conversion = data.conversion or "" end if stopper == "" then stopper = data.stopper or "" end + if starter == "" then starter = data.starter or "" end if connector == "" then connector = data.connector or "" end if set == "" then set = data.set or "" end if segments == "" then segments = data.segments or "" end @@ -449,9 +501,10 @@ function sections.typesetnumber(entry,kind,...) -- kind='section','number','pref end end if separatorset == "" then separatorset = "default" end - if conversionset == "" then conversionset = "default" end + if conversionset == "" then conversionset = "default" end -- not used if conversion == "" then conversion = nil end if stopper == "" then stopper = nil end + if starter == "" then starter = nil end if connector == "" then connector = nil end if set == "" then set = "default" end if segments == "" then segments = nil end @@ -466,9 +519,9 @@ function sections.typesetnumber(entry,kind,...) -- kind='section','number','pref criterium = 0 end -- - local firstprefix, lastprefix = 0, 100 + local firstprefix, lastprefix = 0, 16 if segments then - local f, l = (tostring(segments)):match("^(.-):(.+)$") + local f, l = match(tostring(segments),"^(.-):(.+)$") if f and l then -- 0:100, chapter:subsubsection firstprefix = tonumber(f) or sections.getlevel(f) or 0 @@ -486,12 +539,13 @@ function sections.typesetnumber(entry,kind,...) -- kind='section','number','pref if numbers then local done, preceding = false, false local function process(index) -- move to outer + -- todo: too much (100 steps) local number = numbers and (numbers[index] or 0) local ownnumber = ownnumbers and ownnumbers[index] or "" if number > criterium or (ownnumber ~= "") then - local block = entry.block + local block = (entry.block ~= "" and entry.block) or sections.currentblock() -- added if preceding then - local separator = sets.get("structure:separators",b,s,preceding,".") + local separator = sets.get("structure:separators",block,separatorset,preceding,".") if separator then processors.sprint(ctxcatcodes,separator) end @@ -505,7 +559,7 @@ function sections.typesetnumber(entry,kind,...) -- kind='section','number','pref -- traditional (e.g. used in itemgroups) texsprint(ctxcatcodes,format("\\convertnumber{%s}{%s}",conversion,number)) else - local theconversion = sets.get("structure:conversions",block,conversion,index,"numbers") + local theconversion = sets.get("structure:conversions",block,conversionset,index,"numbers") processors.sprint(ctxcatcodes,theconversion,function(str) return format("\\convertnumber{%s}{%s}",str or "numbers",number) end) @@ -517,6 +571,9 @@ function sections.typesetnumber(entry,kind,...) -- kind='section','number','pref end -- local prefixlist = set and sets.getall("structure:prefixes","",set) -- "" == block + if starter then + processors.sprint(ctxcatcodes,starter) + end if prefixlist and (kind == 'section' or kind == 'prefix') then -- find valid set (problem: for sectionnumber we should pass the level) -- if kind == "section" then @@ -587,17 +644,59 @@ function sections.typesetnumber(entry,kind,...) -- kind='section','number','pref processors.sprint(ctxcatcodes,stopper) end else - report("error: no numbers") + -- report("error: no numbers") end end end -function sections.fullnumber(depth) +function sections.title() + local sc = sections.current() + if sc then + helpers.title(sc.titledata.title,sc.metadata) + end +end + +function sections.findnumber(depth,what) local data = data.status[depth or data.depth] if data then - local sectiondata = jobsections.collected[data.references.section] + local index = data.references.section + local collected = jobsections.collected + local sectiondata = collected[index] if sectiondata and sectiondata.hidenumber ~= true then -- can be nil - sections.typesetnumber(sectiondata,'section',sectiondata) + if what == variables.first then + for i=index,1,-1 do + local s = collected[i] + local n = s.numbers + if #n == depth and n[depth] and n[depth] ~= 0 then + sectiondata = s + elseif #n < depth then + break + end + end + elseif what == variables.last then + for i=index,#collected do + local s = collected[i] + local n = s.numbers + if #n == depth and n[depth] and n[depth] ~= 0 then + sectiondata = s + elseif #n < depth then + break + end + end + end + return sectiondata end end end + +function sections.fullnumber(depth,what,raw) + local sectiondata = sections.findnumber(depth,what) + if sectiondata then + sections.typesetnumber(sectiondata,'section',sectiondata) + end +end + +function sections.getnumber(depth,what) -- redefined here + local sectiondata = sections.findnumber(depth,what) + texwrite((sectiondata and sectiondata.numbers[depth]) or 0) +end |