summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/context/base/data-tex.lua
blob: f5c986d7708fd5f6fabc4b8972b4d258e112ca12 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
if not modules then modules = { } end modules ['data-tex'] = {
    version   = 1.001,
    comment   = "companion to luat-lib.mkiv",
    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
    copyright = "PRAGMA ADE / ConTeXt Development Team",
    license   = "see context related readme files"
}

local char = string.char
local insert, remove = table.insert, table.remove

local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)

local report_tex = logs.reporter("resolvers","tex")

local resolvers = resolvers

local sequencers    = utilities.sequencers
local methodhandler = resolvers.methodhandler
local splitlines    = string.splitlines
local utffiletype   = utf.filetype

-- local fileprocessor = nil
-- local lineprocessor = nil

local textfileactions = sequencers.new {
    arguments    = "str,filename,coding",
    returnvalues = "str",
    results      = "str",
}

local textlineactions = sequencers.new {
    arguments    = "str,filename,linenumber,noflines,coding",
    returnvalues = "str",
    results      = "str",
}

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

local ctrl_d = char( 4) -- unix
local ctrl_z = char(26) -- windows

resolvers.inputstack = resolvers.inputstack or { }

local inputstack = resolvers.inputstack

function helpers.textopener(tag,filename,filehandle,coding)
    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") -- io.readall(filehandle) ... but never that large files anyway
     -- lines = io.readall(filehandle)
        filehandle:close()
    end
    if type(lines) == "string" then
        local coding = coding or utffiletype(lines) -- so we can signal no regime
        if trace_locating then
            report_tex("%a opener: %a opened using method %a",tag,filename,coding)
        end
        if coding == "utf-16-be" then
            lines = utf.utf16_to_utf8_be(lines)
        elseif coding == "utf-16-le" then
            lines = utf.utf16_to_utf8_le(lines)
        elseif coding == "utf-32-be" then
            lines = utf.utf32_to_utf8_be(lines)
        elseif coding == "utf-32-le" then
            lines = utf.utf32_to_utf8_le(lines)
        else -- utf8 or unknown (could be a mkvi file)
            local runner = textfileactions.runner
            if runner then
                lines = runner(lines,filename,coding) or lines
            end
            lines = splitlines(lines)
        end
    elseif trace_locating then
        report_tex("%a opener: %a opened",tag,filename)
    end
    local noflines = #lines
    if lines[noflines] == "" then -- maybe some special check is needed
        lines[noflines] = nil
    end
    logs.show_open(filename)
    insert(inputstack,filename)
    return {
        filename    = filename,
        noflines    = noflines,
        currentline = 0,
        close       = function()
            if trace_locating then
                report_tex("%a closer: %a closed",tag,filename)
            end
            logs.show_close(filename)
            remove(inputstack)
            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 ""
             -- elseif content == ctrl_d or ctrl_z then
             --     return nil -- we need this as \endinput does not work in prints
                else
                    local runner = textlineactions.runner
                    if runner then
                        return runner(content,filename,currentline,noflines,coding) or content
                    else
                        return content
                    end
                end
            end
        end
    }
end

function resolvers.findtexfile(filename,filetype)
    return methodhandler('finders',filename,filetype)
end

function resolvers.opentexfile(filename)
    return methodhandler('openers',filename)
end

function resolvers.openfile(filename)
    local fullname = methodhandler('finders',filename)
    return fullname and fullname ~= "" and methodhandler('openers',fullname) or nil
end

function resolvers.loadtexfile(filename,filetype)
    -- todo: optionally apply filters
    local ok, data, size = resolvers.loadbinfile(filename, filetype)
    return data or ""
end

resolvers.texdatablob = resolvers.loadtexfile

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
        report_tex("installing input %a handlers in %a is not possible",what,tostring(where))
    end
end

function resolvers.installinputlinehandler(...) installhandler(helpers.textlineactions,"line",...) end
function resolvers.installinputfilehandler(...) installhandler(helpers.textfileactions,"file",...) end

-- local basename = file.basename
-- resolvers.installinputlinehandler(function(str,filename,linenumber,noflines)
--     report_tex("[lc] file %a, line %a of %a, length %a",basename(filename),linenumber,noflines,#str)
-- end)
-- resolvers.installinputfilehandler(function(str,filename)
--     report_tex("[fc] file %a, length %a",basename(filename),#str)
-- end)