summaryrefslogtreecommitdiff
path: root/support/make4ht/make4ht-lib.lua
blob: 91418d18b5a1f1164a89abb80f8bfaf46917e15d (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
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
-- Simple make system for tex4ht
--kpse.set_program_name("luatex")
-- module(...,package.seeall)
local m = {}
local log = logging.new "make4ht-lib"

Make = {}
--Make.params = {}
Make.build_seq = {}
-- Patterns for matching output filenames
Make.matches = {}
Make.image_patterns = {}
Make.run_count = {}

Make.add = function(self,name,fn,par,rep)
	local par = par or {}
	self.params = self.params or {}
	Make[name] = function(self,p,typ)
		local params = {}
		for k,v in pairs(self.params) do params[k] = v end
		for k,v in pairs(par) do params[k] = v; log:info("setting param "..k) end
		local typ = typ or "make"
		local p = p or {}
		local fn = fn
		for k,v in pairs(p) do
			params[k]=v
			log:info("Adding: ",k,v)
		end
		-- print( fn % params)
		local command = {
			name=name,
			type=typ,
			command = fn,
			params = params,
			repetition = rep
		}
		table.insert(self.build_seq,command)
	end
end

Make.length = function(self)
	return #self.build_seq
end

Make.match = function(self, pattern, command, params) 
	local params = params or {}
	table.insert(self.matches,{pattern = pattern, command = command, params = params})
end

Make.run_command = function(self,filename,s)
	local command = s.command
	local params  = s.params
	params["filename"] = filename
	log:info("parse_lg process file: "..filename)
	--for k,v in pairs(params) do print(k..": "..v) end
	if type(command) == "function" then
		return command(filename,params)
	elseif type(command) == "string" then
		local run = command % params
		log:info("Execute: " .. run)
    return mkutils.execute(run)
	end
	return false, "parse_lg: Command is not string or function"
end

Make.image = function(self, pattern, command, params)
	local tab = {
		pattern = pattern,
		command = command,
		params  = params
	}
	table.insert(self.image_patterns, tab)
end

Make.image_convert =  function(self, images)
	local image_patterns = self.image_patterns or {}
	for i, r in pairs(image_patterns) do
		local p = self.params or {}
		local v = r.params or {}
		for k,v in pairs(v) do
			p[k]= v
		end
		image_patterns[i].params = p
	end
	for _,i in ipairs(images) do
		local output = i.output
		for _, x in ipairs(image_patterns) do
			local pattern = x.pattern
			if output:match(pattern) then
				local command = x.command
				local p = x.params or {}
				p.output = output
				p.page= i.page
				p.source = i.source
				if type(command) == "function" then
					command(p)
				elseif type(command) == "string" then
					local c = command % p
					log:info("Make4ht convert: "..c)
					mkutils.execute(c)
				end
				break
			end
		end
	end
end

Make.file_matches = function(self, files)
	local statuses = {}
	-- First make params for all matchers
	for k,v in ipairs(self.matches) do
		local v = self.matches[k].params or {}
		local p = self.params or {}
		for i,j in pairs(p) do
			v[i] = j
		end
		self.matches[k].params = v
	end
	-- Loop over files, run command on matched
	for _, file in ipairs(files)do
		statuses[file] = {}
		for _, s in ipairs(self.matches) do
			local pattern= s.pattern
			if file:match(pattern) then 
				local status, msg = self:run_command(file,s)
				msg = msg or "No message given"
				table.insert(statuses[file],status)
				if status == false then
					log:info(msg)
					break
				end
			end
		end
	end
	return statuses
end

-- add files from the mk4 file
-- we must add them to the table generated from the lg file, so they can be processed later
--
Make.add_file = function(self, filename)
  -- self.lgfile should be present, as it is created once the lg_file was parsed for the first time
  local lg = self.lgfile or {}
  local files = lg.files or {}
  -- run filters on the file
  local filtertable = {filename}
  -- should we care about return status?
  self:file_matches(filtertable)
  -- break if the file is present already 
  -- start at the end, it it was added by a build file, the file will be likely at the end
  for i = #files,1,-1  do 
    if files[i] == filename then return false, "File was already added" end
  end
  -- save the added file to the lg_file
  table.insert(lg.files, filename)
  self.lg = lg
end

Make.run = function(self) 
	local return_codes = {}
  local params = self.params or {}
	for _,v in ipairs(self.build_seq) do
		--print("sekvence: "..v.name)
		for p,n in pairs(v.params) do params[p] = n end
		--for c,_ in pairs(params) do print("build param: "..c) end
		if type(v.command)=="function" then 
			table.insert(return_codes,{name=v.name,status = v.command(params)})
		elseif type(v.command) =="string" then
			local command = v.command % params
			-- Some commands should be executed only limited times, typicaly once
			-- tex4ht or t4ht for example
			local run_count = self.run_count[v.command] or 0
			run_count = run_count + 1
			self.run_count[v.command] = run_count
			local repetition = v.repetition
			if repetition and run_count > repetition then 
				log:warning (command .." can be executed only "..repetition .."x")
			else
			  log:info("executing: " .. command)
        local status = mkutils.execute(command)
			  table.insert(return_codes,{name=v.name,status=status})
			end
		else
			log:warning("Unknown command type, must be string or function - " ..v.name..": "..type(v.command))
		end
		local correct_exit = params.correct_exit or nil
		if correct_exit then
			local last_return = return_codes[#return_codes] or {}
			local current_status = last_return.status or 0
			if current_status ~= correct_exit then
				local last_name = last_return.name or "unknown"
				log:fatal("Fatal error. Command "..last_name .." returned exit code "..current_status)
				os.exit(1)
			end
		end
	end
	local lgfile = params.input and params.input .. ".lg" or nil 
	if lgfile then
   	self.lgfile = self.lgfile or mkutils.parse_lg(lgfile)
    local lg = self.lgfile
		-- First convert images from lg files
		self:image_convert(lg["images"])
		-- Then run file matchers on lg files and converted images
		local files = lg["files"]
		for _,v in ipairs(lg["images"]) do 
			local v = v.output
			-- print(v)
			table.insert(files,v) 
		end
		self:file_matches(files)
	else
		log:warning("No lg file. tex4ht run failed?")
	end
	return return_codes
end

m.Make = Make

return m

--[[Make:add("hello", "hello ${world}", {world = "world"})
Make:add("ajaj", "ajaj")
Make:hello()
Make:hello{world="světe"}
Make:hello()
Make:run()
--]]