diff options
Diffstat (limited to 'Master/texmf-dist/tex/context/base/strc-bkm.lua')
-rw-r--r-- | Master/texmf-dist/tex/context/base/strc-bkm.lua | 153 |
1 files changed, 106 insertions, 47 deletions
diff --git a/Master/texmf-dist/tex/context/base/strc-bkm.lua b/Master/texmf-dist/tex/context/base/strc-bkm.lua index f34d83ec557..6a2cc382775 100644 --- a/Master/texmf-dist/tex/context/base/strc-bkm.lua +++ b/Master/texmf-dist/tex/context/base/strc-bkm.lua @@ -9,25 +9,56 @@ if not modules then modules = { } end modules ['strc-bkm'] = { -- Future version will support adding arbitrary bookmarks with -- associated complex actions (rather trivial to implement). +-- this should become proper separated backend code + +-- we should hook the placement into everystoptext ... needs checking + local format, concat, gsub = string.format, table.concat, string.gsub -local texsprint, utfvalues = tex.sprint, string.utfvalues +local utfvalues = string.utfvalues +local settings_to_hash = utilities.parsers.settings_to_hash + +local codeinjections = backends.codeinjections + +local trace_bookmarks = false trackers.register("references.bookmarks", function(v) trace_bookmarks = v end) -local ctxcatcodes = tex.ctxcatcodes +local report_bookmarks = logs.reporter("structure","bookmarks") -local lists = structure.lists -local levelmap = structure.sections.levelmap +local structures = structures -structure.bookmarks = structure.bookmarks or { } +structures.bookmarks = structures.bookmarks or { } -local bookmarks = structure.bookmarks +local bookmarks = structures.bookmarks +local sections = structures.sections +local lists = structures.lists + +local levelmap = sections.levelmap +local variables = interfaces.variables bookmarks.method = "internal" -- or "page" -local names, opened = "", "" +local names, opened, forced, numbered = { }, { }, { }, { } -function bookmarks.register(n,o) - if names == "" then names = n else names = names .. "," .. n end - if opened == "" then opened = o else opened = opened .. "," .. o end +function bookmarks.register(settings) + local force = settings.force == variables.yes + local number = settings.number == variables.yes + local allopen = settings.opened == variables.all + for k, v in next, settings_to_hash(settings.names or "") do + names[k] = true + if force then + forced[k] = true + if allopen then + opened[k] = true + end + end + if number then + numbered[k] = true + end + end + if not allopen then + for k, v in next, settings_to_hash(settings.opened or "") do + opened[k] = true + end + end end function bookmarks.overload(name,text) @@ -61,23 +92,32 @@ end -- todo: collect specs and collect later i.e. multiple places +local numberspec = { } + +function bookmarks.setup(spec) + -- table.merge(numberspec,spec) + for k, v in next, spec do + numberspec[k] = v + end +end + function bookmarks.place() - if names ~= "" then - local list = lists.filter(names,"all",nil,lists.collected) - local lastlevel = 1 + if next(names) then + local list = lists.filtercollected(names,"all",nil,lists.collected,forced) if #list > 0 then - local opened, levels = aux.settings_to_set(opened), { } + local levels, noflevels, lastlevel = { }, 0, 1 for i=1,#list do local li = list[i] local metadata = li.metadata local name = metadata.name - if not metadata.nolist then -- and levelmap[name] then + if not metadata.nolist or forced[name] then -- and levelmap[name] then local titledata = li.titledata if titledata then local structural = levelmap[name] lastlevel = structural or lastlevel local title = titledata.bookmark if not title or title == "" then + -- We could typeset the title and then convert it. if not structural then -- placeholder, todo: bookmarklabel title = name .. ": " .. (titledata.title or "?") @@ -85,47 +125,66 @@ function bookmarks.place() title = titledata.title or "?" end end - levels[#levels+1] = { + if numbered[name] then + local sectiondata = sections.collected[li.references.section] + local numberdata = li.numberdata + if sectiondata and numberdata and not numberdata.hidenumber then + -- we could typeset the number and convert it + title = concat(sections.typesetnumber(sectiondata,"direct",numberspec,sectiondata)) .. " " .. title + end + end + noflevels = noflevels + 1 + levels[noflevels] = { lastlevel, - stripped(title), + stripped(title), -- can be replaced by converter li.references, -- has internal and realpage allopen or opened[name] } end end end - backends.codeinjections.addbookmarks(levels,bookmarks.method) + bookmarks.finalize(levels) end function bookmarks.place() end -- prevent second run end end -lpdf.registerdocumentfinalizer(function() structure.bookmarks.place() end,1) - --- bkm ---~ function nodes.toutf(list) ---~ local t= { } ---~ for n in node.traverse(list) do ---~ local id = n.id ---~ if id == node.id("glyph") then ---~ local c = n.char ---~ local f = fonts.ids[n.font] ---~ if f then ---~ local u = f.characters[c].tounicode ---~ if u then ---~ for s in string.gmatch(u,"..") do ---~ t[#t+1] = utf.char(tonumber(s,16)) ---~ end ---~ else ---~ t[#t+1] = utf.char(c) ---~ end ---~ else ---~ t[#t+1] = utf.char(c) ---~ end ---~ elseif id == node.id("glue") then ---~ t[#t+1] = " " ---~ end ---~ end ---~ return table.concat(t,"") ---~ end ---~ print(nodes.toutf(tex.box[999].list)) +function bookmarks.flatten(levels) + -- This function promotes leading structurelements with a higher level + -- to the next lower level. Such situations are the result of lack of + -- structure: a subject preceding a chapter in a sectionblock. So, the + -- following code runs over section blocks as well. (bookmarks-007.tex) + local noflevels = #levels + if noflevels > 1 then + local skip, start, one = false, 1, levels[1] + local first, block = one[1], one[3].block + for i=2,noflevels do + local li = levels[i] + local new, newblock = li[1], li[3].block + if newblock ~= block then + first, block, start, skip = new, newblock, i, false + elseif skip then + -- go on + elseif new > first then + skip = true + elseif new < first then + for j=start,i-1 do + local lj = levels[j] + local old = lj[1] + lj[1] = new + if trace_bookmarks then + report_bookmarks("promoting entry %s from level %s to %s: %s",j,old,new,lj[2]) + end + end + skip = true + end + end + end +end + +function bookmarks.finalize(levels) + -- This function can be overloaded by an optional converter + -- that uses nodes.toutf on a typeset stream. This is something + -- that we will support when the main loop has become a coroutine. + codeinjections.addbookmarks(levels,bookmarks.method) +end |