diff options
Diffstat (limited to 'Master/texmf-dist/tex/context/base/data-tex.lua')
-rw-r--r-- | Master/texmf-dist/tex/context/base/data-tex.lua | 306 |
1 files changed, 123 insertions, 183 deletions
diff --git a/Master/texmf-dist/tex/context/base/data-tex.lua b/Master/texmf-dist/tex/context/base/data-tex.lua index c9fa3625a66..14148b20ea8 100644 --- a/Master/texmf-dist/tex/context/base/data-tex.lua +++ b/Master/texmf-dist/tex/context/base/data-tex.lua @@ -6,221 +6,161 @@ if not modules then modules = { } end modules ['data-tex'] = { license = "see context related readme files" } --- special functions that deal with io - -local format, lower = string.format, string.lower -local unpack = unpack or table.unpack - local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end) -local texiowrite_nl = (texio and texio.write_nl) or print -local texiowrite = (texio and texio.write) or print +local report_tex = logs.reporter("resolvers","tex") -local finders, openers, loaders = resolvers.finders, resolvers.openers, resolvers.loaders +local resolvers = resolvers -function finders.generic(tag,filename,filetype) - local foundname = resolvers.find_file(filename,filetype) - if foundname and foundname ~= "" then - if trace_locating then - logs.report("fileio","%s finder: file '%s' found",tag,filename) - end - return foundname - else - if trace_locating then - logs.report("fileio","%s finder: unknown file '%s'",tag,filename) - end - return unpack(finders.notfound) - end -end +local sequencers = utilities.sequencers +local methodhandler = resolvers.methodhandler +local splitlines = string.splitlines +local utffiletype = unicode.filetype ---~ local lpegmatch = lpeg.match ---~ local getlines = lpeg.Ct(lpeg.patterns.textline) +local fileprocessor = nil +local lineprocessor = nil -local input_translator, utf_translator, user_translator = nil, nil, nil +local textfileactions = sequencers.reset { + arguments = "str,filename", + returnvalues = "str", + results = "str", +} -function resolvers.install_text_filter(name,func) - if name == "input" then input_translator = func - elseif name == "utf" then utf_translator = func - elseif name == "user" then user_translator = func end -end +local textlineactions = sequencers.reset { + arguments = "str,filename,linenumber,noflines", + returnvalues = "str", + results = "str", +} -function openers.text_opener(filename,file_handle,tag) - local u = unicode.utftype(file_handle) - local t = { } - if u > 0 then - if trace_locating then - logs.report("fileio","%s opener, file '%s' opened using method '%s'",tag,filename,unicode.utfname[u]) - end - local l - if u > 2 then - l = unicode.utf32_to_utf8(file_handle:read("*a"),u==4) - else - l = unicode.utf16_to_utf8(file_handle:read("*a"),u==2) - end - file_handle:close() - t = { - utftype = u, -- may go away - lines = l, - current = 0, -- line number, not really needed - handle = nil, - noflines = #l, - close = function() - if trace_locating then - logs.report("fileio","%s closer, file '%s' closed",tag,filename) - end - logs.show_close(filename) - t = nil - end, - reader = function(self) - self = self or t - local current, lines = self.current, self.lines - if current >= #lines then - return nil - else - current = current + 1 - self.current = current - local line = lines[current] - if not line then - return nil - elseif line == "" then - return "" - else - if input_translator then - line = input_translator(line) - end - if utf_translator then - line = utf_translator(line) - end - if user_translator then - line = user_translator(line) - end - return line - end - end - end - } +local helpers = resolvers.openers.helpers +local appendgroup = sequencers.appendgroup + +helpers.textfileactions = textfileactions +helpers.textlineactions = textlineactions + +appendgroup(textfileactions,"before") -- user +appendgroup(textfileactions,"system") -- private +appendgroup(textfileactions,"after" ) -- user + +appendgroup(textlineactions,"before") -- user +appendgroup(textlineactions,"system") -- private +appendgroup(textlineactions,"after" ) -- user + +function helpers.textopener(tag,filename,filehandle) + local lines + local t_filehandle = type(filehandle) + if not filehandle then + lines = io.loaddata(filename) + elseif t_filehandle == "string" then + lines = filehandle + elseif t_filehandle == "table" then + lines = filehandle else + lines = filehandle:read("*a") + filehandle:close() + end + if type(lines) == "string" then + local coding = utffiletype(lines) if trace_locating then - logs.report("fileio","%s opener, file '%s' opened",tag,filename) + report_tex("%s opener, '%s' opened using method '%s'",tag,filename,coding) end - -- todo: file;name -> freeze / eerste regel scannen -> freeze - --~ local data = lpegmatch(getlines,file_handle:read("*a")) - --~ local n = 0 - t = { - reader = function() -- self - local line = file_handle:read() - --~ n = n + 1 - --~ local line = data[n] - --~ print(line) - if not line then - return nil - elseif line == "" then - return "" - else - if input_translator then - line = input_translator(line) - end - if utf_translator then - line = utf_translator(line) - end - if user_translator then - line = user_translator(line) - end - return line - end - end, - close = function() - if trace_locating then - logs.report("fileio","%s closer, file '%s' closed",tag,filename) - end - logs.show_close(filename) - file_handle:close() - t = nil - collectgarbage("step") -- saves some memory - end, - handle = function() - return file_handle - end, - noflines = function() - t.noflines = io.noflines(file_handle) - return t.noflines - end - } - end - return t -end - -function openers.generic(tag,filename) - if filename and filename ~= "" then - local f = io.open(filename,"r") - if f then - logs.show_open(filename) -- todo - if trace_locating then - logs.report("fileio","%s opener, file '%s' opened",tag,filename) + if coding == "utf-16-be" then + lines = unicode.utf16_to_utf8_be(lines) + elseif coding == "utf-16-le" then + lines = unicode.utf16_to_utf8_le(lines) + elseif coding == "utf-32-be" then + lines = unicode.utf32_to_utf8_be(lines) + elseif coding == "utf-32-le" then + lines = unicode.utf32_to_utf8_le(lines) + else -- utf8 or unknown + if textfileactions.dirty then -- maybe use autocompile + fileprocessor = sequencers.compile(textfileactions) end - return openers.text_opener(filename,f,tag) + lines = fileprocessor(lines,filename) or lines + lines = splitlines(lines) end + elseif trace_locating then + report_tex("%s opener, '%s' opened",tag,filename) end - if trace_locating then - logs.report("fileio","%s opener, file '%s' not found",tag,filename) + local noflines = #lines + if lines[noflines] == "" then -- maybe some special check is needed + lines[noflines] = nil end - return unpack(openers.notfound) -end - -function loaders.generic(tag,filename) - if filename and filename ~= "" then - local f = io.open(filename,"rb") - if f then - logs.show_load(filename) + logs.show_open(filename) + return { + filename = filename, + noflines = noflines, + currentline = 0, + close = function() if trace_locating then - logs.report("fileio","%s loader, file '%s' loaded",tag,filename) + report_tex("%s closer, '%s' closed",tag,filename) end - local s = f:read("*a") - if garbagecollector and garbagecollector.check then garbagecollector.check(#s) end - f:close() - if s then - return true, s, #s + logs.show_close(filename) + t = nil + end, + reader = function(self) + self = self or t + local currentline, noflines = self.currentline, self.noflines + if currentline >= noflines then + return nil + else + currentline = currentline + 1 + self.currentline = currentline + local content = lines[currentline] + if not content then + return nil + elseif content == "" then + return "" + else + if textlineactions.dirty then + lineprocessor = sequencers.compile(textlineactions) -- maybe use autocompile + end + return lineprocessor(content,filename,currentline,noflines) or content + end end end - end - if trace_locating then - logs.report("fileio","%s loader, file '%s' not found",tag,filename) - end - return unpack(loaders.notfound) + } end -function finders.tex(filename,filetype) - return finders.generic('tex',filename,filetype) +function resolvers.findtexfile(filename,filetype) + return methodhandler('finders',filename,filetype) end -function openers.tex(filename) - return openers.generic('tex',filename) +function resolvers.opentexfile(filename) + return methodhandler('openers',filename) end -function loaders.tex(filename) - return loaders.generic('tex',filename) +function resolvers.openfile(filename) + local fullname = methodhandler('finders',filename) + return fullname and fullname ~= "" and methodhandler('openers',fullname) or nil end -function resolvers.findtexfile(filename, filetype) - return resolvers.methodhandler('finders',filename, filetype) +function resolvers.loadtexfile(filename,filetype) + -- todo: optionally apply filters + local ok, data, size = resolvers.loadbinfile(filename, filetype) + return data or "" end -function resolvers.opentexfile(filename) - return resolvers.methodhandler('openers',filename) -end +resolvers.texdatablob = resolvers.loadtexfile -function resolvers.openfile(filename) - local fullname = resolvers.findtexfile(filename) - if fullname and (fullname ~= "") then - return resolvers.opentexfile(fullname) +local function installhandler(namespace,what,where,func) + if not func then + where, func = "after", where + end + if where == "before" or where == "after" then + sequencers.appendaction(namespace,where,func) else - return nil + report_tex("installing input %s handlers in %s is not possible",what,tostring(where)) end end -function resolvers.texdatablob(filename, filetype) - local ok, data, size = resolvers.loadbinfile(filename, filetype) - return data or "" -end +function resolvers.installinputlinehandler(...) installhandler(helpers.textlineactions,"line",...) end +function resolvers.installinputfilehandler(...) installhandler(helpers.textfileactions,"file",...) end -resolvers.loadtexfile = resolvers.texdatablob +-- local basename = file.basename +-- resolvers.installinputlinehandler(function(str,filename,linenumber,noflines) +-- report_tex("[lc] file: %s, line: %s of %s, length: %s",basename(filename),linenumber,noflines,#str) +-- end) +-- resolvers.installinputfilehandler(function(str,filename) +-- report_tex("[fc] file: %s, length: %s",basename(filename),#str) +-- end) |