summaryrefslogtreecommitdiff
path: root/tex/context/modules/mkiv/m-database.lua
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/modules/mkiv/m-database.lua')
-rw-r--r--tex/context/modules/mkiv/m-database.lua132
1 files changed, 132 insertions, 0 deletions
diff --git a/tex/context/modules/mkiv/m-database.lua b/tex/context/modules/mkiv/m-database.lua
new file mode 100644
index 000000000..91e9636ee
--- /dev/null
+++ b/tex/context/modules/mkiv/m-database.lua
@@ -0,0 +1,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