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
|
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, format = string.sub, string.gmatch, string.format
local concat = table.concat
local lpegpatterns, lpegmatch, lpegsplitat = lpeg.patterns, lpeg.match, lpeg.splitat
local lpegP, lpegC, lpegS, lpegCt = lpeg.P, lpeg.C, lpeg.S, lpeg.Ct
local stripstring = string.strip
-- 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")
buffers.database = buffers.database or { }
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 buffers.database.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
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
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 = l_space^0 * quotechar * lpegC((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)
local splitter = lpegCt(whatever * (separator * whatever)^0)
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
local list = lpegmatch(splitter,line)
if not found then
if setups ~= "" then
context.begingroup()
context.setups { setups }
end
context(before)
found = true
end
if trace_flush then
local result, r = { }, 0
r = r + 1 ; result[r] = first
for j=1,#list do
local str = strip and stripstring(list[j]) or list[j]
r = r + 1 ; result[r] = left
if command == "" then
r = r + 1 ; result[r] = str
else
r = r + 1 ; result[r] = command
r = r + 1 ; result[r] = "{"
r = r + 1 ; result[r] = str
r = r + 1 ; result[r] = "}"
end
r = r + 1 ; result[r] = right
end
r = r + 1 ; result[r] = last
context(concat(result))
else
context(first)
for j=1,#list do
local str = strip and stripstring(list[j]) or list[j]
context(left)
if command == "" then
context(str)
else
context(command)
context(false,str)
end
context(right)
end
context(last)
end
end
end
if found then
context(after)
if setups ~= "" then
context.endgroup()
end
end
if trace_flush then
context.poplogger()
end
else
-- message
end
end
|