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
|
if not modules then modules = { } end modules ['m-database'] = {
version = 1.001,
comment = "companion to m-database.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
copyright = "PRAGMA ADE / ConTeXt Development Team",
license = "see context related readme files"
}
local sub, gmatch = string.sub, string.gmatch
local concat = table.concat
local lpegpatterns, lpegmatch, lpegsplitat = lpeg.patterns, lpeg.match, lpeg.splitat
local lpegP, lpegC, lpegS, lpegCt, lpegCc, lpegCs = lpeg.P, lpeg.C, lpeg.S, lpeg.Ct, lpeg.Cc, lpeg.Cs
local stripstring = string.strip
moduledata.database = moduledata.database or { }
moduledata.database.csv = moduledata.database.csv or { }
-- One also needs to enable context.trace, here we only plug in some code (maybe
-- some day this tracker will also toggle the main context tracer.
local trace_flush = false trackers.register("module.database.flush", function(v) trace_flush = v end)
local report_database = logs.reporter("database")
local context = context
local l_tab = lpegpatterns.tab
local l_space = lpegpatterns.space
local l_comma = lpegpatterns.comma
local l_empty = lpegS("\t\n\r ")^0 * lpegP(-1)
local v_yes = interfaces.variables.yes
local separators = { -- not interfaced
tab = l_tab,
tabs = l_tab^1,
comma = l_comma,
space = l_space,
spaces = l_space^1,
}
function moduledata.database.csv.process(settings)
local data
if settings.type == "file" then
local filename = resolvers.finders.byscheme("any",settings.database)
data = filename ~= "" and io.loaddata(filename)
data = data and string.splitlines(data)
else
data = buffers.getlines(settings.database)
end
if data and #data > 0 then
local catcodes = tonumber(settings.catcodes) or tex.catcodetable
context.pushcatcodes(catcodes)
if trace_flush then
context.pushlogger(report_database)
end
local separatorchar, quotechar, commentchar = settings.separator, settings.quotechar, settings.commentchar
local before, after = settings.before or "", settings.after or ""
local first, last = settings.first or "", settings.last or ""
local left, right = settings.left or "", settings.right or ""
local setups = settings.setups or ""
local strip = settings.strip == v_yes or false
local command = settings.command or ""
separatorchar = (not separatorchar and ",") or separators[separatorchar] or separatorchar
local separator = type(separatorchar) == "string" and lpegS(separatorchar) or separatorchar
local whatever = lpegC((1 - separator)^0)
if quotechar and quotechar ~= "" then
local quotedata = nil
for chr in gmatch(quotechar,".") do
local quotechar = lpegP(chr)
local quoteword = lpegCs(((l_space^0 * quotechar)/"") * (1 - quotechar)^0 * ((quotechar * l_space^0)/""))
if quotedata then
quotedata = quotedata + quoteword
else
quotedata = quoteword
end
end
whatever = quotedata + whatever
end
local checker = commentchar ~= "" and lpegS(commentchar)
if strip then
whatever = whatever / stripstring
end
if left ~= "" then
whatever = lpegCc(left) * whatever
end
if right ~= "" then
whatever = whatever * lpegCc(right)
end
if command ~= "" then
whatever = lpegCc("{") * whatever * lpegCc("}")
end
whatever = whatever * (separator/"" * whatever)^0
if first ~= "" then
whatever = lpegCc(first) * whatever
end
if last ~= "" then
whatever = whatever * lpegCc(last)
end
if command ~= "" then
whatever = lpegCs(lpegCc(command) * whatever)
else
whatever = lpegCs(whatever)
end
local found = false
for i=1,#data do
local line = data[i]
if not lpegmatch(l_empty,line) and (not checker or not lpegmatch(checker,line)) then
if not found then
if setups ~= "" then
context.begingroup()
context.setups { setups }
end
context(before)
found = true
end
context(lpegmatch(whatever,line))
end
end
if found then
context(after)
if setups ~= "" then
context.endgroup()
end
end
context.popcatcodes()
if trace_flush then
context.poplogger()
end
else
-- message
end
end
|