summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilipp Gesang <phg42.2a@gmail.com>2014-04-21 21:40:21 +0200
committerPhilipp Gesang <phg42.2a@gmail.com>2014-04-21 21:40:21 +0200
commita84ec1cd4b7cc06fec1d2cf5e5f5e0cbd9115637 (patch)
tree05c63b5fd96f66a1874e081ac4239db6b1655896
parent70a6425e1b6041d5c476117fa7c5a3acb9bc386a (diff)
downloadluaotfload-a84ec1cd4b7cc06fec1d2cf5e5f5e0cbd9115637.tar.gz
[conf,tool] integrate configuration parser
-rw-r--r--src/luaotfload-configuration.lua255
-rwxr-xr-xsrc/luaotfload-tool.lua41
2 files changed, 288 insertions, 8 deletions
diff --git a/src/luaotfload-configuration.lua b/src/luaotfload-configuration.lua
new file mode 100644
index 0000000..973810a
--- /dev/null
+++ b/src/luaotfload-configuration.lua
@@ -0,0 +1,255 @@
+#!/usr/bin/env texlua
+-------------------------------------------------------------------------------
+-- FILE: luaotfload-configuration.lua
+-- DESCRIPTION: config file reader
+-- REQUIREMENTS: Luaotfload > 2.4
+-- AUTHOR: Philipp Gesang (Phg), <phg42.2a@gmail.com>
+-- VERSION: same as Luaotfload
+-- CREATED: 2014-04-21 14:03:52+0200
+-------------------------------------------------------------------------------
+--
+
+if not modules then modules = { } end modules ["luaotfload-configuration"] = {
+ version = "2.5",
+ comment = "part of Luaotfload",
+ author = "Philipp Gesang",
+ copyright = "Luaotfload Development Team",
+ license = "GNU GPL v2.0"
+}
+
+luaotfload = luaotfload or { }
+luaotfload.config = luaotfload.config or { }
+
+local string = string
+local stringsub = string.sub
+local stringexplode = string.explode
+
+local io = io
+local ioloaddata = io.loaddata
+
+local os = os
+local osgetenv = os.getenv
+
+local lpeg = require "lpeg"
+local lpegmatch = lpeg.match
+
+local kpse = kpse
+local kpselookup = kpse.lookup
+
+local lfs = lfs
+local lfsisfile = lfs.isfile
+local lfsisdir = lfs.isdir
+
+local file = file
+local filejoin = file.join
+
+local parsers = luaotfload.parsers
+local config = luaotfload.config
+local log = luaotfload.log
+local logreport = log.report
+
+local config_parser = parsers.config
+
+-------------------------------------------------------------------------------
+--- SETTINGS
+-------------------------------------------------------------------------------
+
+local path_t = 0
+local kpse_t = 1
+
+local config_paths = {
+ --- needs adapting for those other OS
+ { path_t, "./luaotfloadrc" },
+ { path_t, "~/.config/luaotfload/luaotfloadrc" },
+ { path_t, "~/.luaotfloadrc" },
+ { kpse_t, "luaotfloadrc" },
+ { kpse_t, "luaotfload.conf" },
+}
+
+-------------------------------------------------------------------------------
+--- OPTION SPECIFICATION
+-------------------------------------------------------------------------------
+
+local string_t = "string"
+local table_t = "table"
+local boolean_t = "boolean"
+local function_t = "function"
+
+local option_spec = {
+ db = {
+ formats = {
+ --- e.g. "otf ttf" -> { "otf", "ttf" }
+ in_t = string_t,
+ out_t = table_t,
+ transform = function (str) return stringexplode (str, " +") end
+ },
+ reload = {
+ in_t = boolean_t,
+ },
+ },
+}
+
+-------------------------------------------------------------------------------
+--- MAIN FUNCTIONALITY
+-------------------------------------------------------------------------------
+
+--[[doc--
+
+ tilde_expand -- Rudimentary tilde expansion; covers just the “substitute ‘~’
+ by the current users’s $HOME” part.
+
+--doc]]--
+
+local tilde_expand = function (p)
+ if #p > 2 then
+ if stringsub (p, 1, 2) == "~/" then
+ local homedir = osgetenv "HOME"
+ if homedir and lfsisdir (homedir) then
+ p = filejoin (homedir, stringsub (p, 3))
+ end
+ end
+ end
+ return p
+end
+
+local resolve_config_path = function ()
+ inspect (config_paths)
+ for i = 1, #config_paths do
+ local t, p = unpack (config_paths[i])
+ local fullname
+ if t == kpse_t then
+ fullname = kpse.lookup (p)
+ logreport ("both", 6, "conf", "kpse lookup: %s -> %s.", p, fullname)
+ elseif t == path_t then
+ local expanded = tilde_expand (p)
+ if lfsisfile (expanded) then
+ fullname = expanded
+ end
+ logreport ("both", 6, "conf", "path lookup: %s -> %s.", p, fullname)
+ end
+ if fullname then
+ logreport ("both", 3, "conf", "Reading configuration file at %q.", fullname)
+ return fullname
+ end
+ end
+ logreport ("both", 2, "conf", "No configuration file found.")
+ return false
+end
+
+local add_config_paths = function (t)
+ if not next (t) then
+ return
+ end
+ local result = { }
+ for i = 1, #t do
+ local path = t[i]
+ result[#result + 1] = { path_t, path }
+ end
+ config_paths = table.append (result, config_paths)
+end
+
+local process_options = function (opts)
+ local new = { }
+ for i = 1, #opts do
+ local section = opts[i]
+ local title = section.section.title
+ local vars = section.variables
+
+ if not title then --- trigger warning: arrow code ahead
+ logreport ("both", 2, "conf", "Section %d lacks a title; skipping.", i)
+ elseif not vars then
+ logreport ("both", 2, "conf", "Section %d (%s) lacks a variable section; skipping.", i, title)
+ else
+ local spec = option_spec[title]
+ if not spec then
+ logreport ("both", 2, "conf", "Section %d (%s) unknown; skipping.", i, title)
+ else
+ local newsection = new[title]
+ if not newsection then
+ newsection = { }
+ new[title] = newsection
+ end
+
+ for var, val in next, vars do
+ local vspec = spec[var]
+ local t_val = type (val)
+ if t_val ~= vspec.in_t then
+ logreport ("both", 2, "conf",
+ "Section %d (%s): type mismatch of input value %q (%q, %s != %s); ignoring.",
+ i, title,
+ var, tostring (val), t_val, vspec.in_t)
+ else --- type matches
+ local transform = vspec.transform
+ if transform then
+ local dval
+ local t_transform = type (transform)
+ if t_transform == function_t then
+ dval = transform (val)
+ elseif t_transform == table_t then
+ dval = transform[val]
+ end
+ if dval then
+ local out_t = vspec.out_t
+ if out_t then
+ local t_dval = type (dval)
+ if t_dval == out_t then
+ newsection[var] = dval
+ else
+ logreport ("both", 2, "conf",
+ "Section %d (%s): type mismatch of derived value of %q (%q, %s != %s); ignoring.",
+ i, title,
+ var, tostring (dval), t_dval, out_t)
+ end
+ else
+ newsection[var] = dval
+ end
+ else
+ logreport ("both", 2, "conf",
+ "Section %d (%s): value of %q could not be derived via %s from input %q; ignoring.",
+ i, title, var, t_transform, tostring (val))
+ end
+ else --- insert as is
+ newsection[var] = val
+ end
+ end
+ end
+ end
+ end
+ end
+ return new
+end
+
+local read = function (extra)
+ if extra then
+ add_config_paths (extra)
+ end
+
+ local readme = resolve_config_path ()
+ if readme == false then
+ logreport ("both", 2, "conf", "No configuration file.")
+ return false
+ end
+
+ local raw = ioloaddata (readme)
+ if not raw then
+ logreport ("both", 2, "conf", "Error reading the configuration file %q.", readme)
+ return false
+ end
+
+ local parsed = lpegmatch (parsers.config, raw)
+ if not parsed then
+ logreport ("both", 2, "conf", "Error parsing configuration file %q.", readme)
+ return false
+ end
+
+ local ret, msg = process_options (parsed)
+ if not ret then
+ logreport ("both", 2, "conf", "File %q is not a valid configuration file.", readme)
+ logreport ("both", 2, "conf", "Error: %s", msg)
+ return false
+ end
+ return ret
+end
+
+config.read = read
+
diff --git a/src/luaotfload-tool.lua b/src/luaotfload-tool.lua
index 1923040..5893d42 100755
--- a/src/luaotfload-tool.lua
+++ b/src/luaotfload-tool.lua
@@ -45,7 +45,6 @@ kpse.set_program_name "luatex"
--doc]]--
-local ioopen = io.open
local iowrite = io.write
local kpsefind_file = kpse.find_file
local mathfloor = math.floor
@@ -149,7 +148,8 @@ texio.write, texio.write_nl = backup.write, backup.write_nl
utilities = backup.utilities
require"luaotfload-log.lua" --- this populates the luaotfload.log.* namespace
-require"luaotfload-parsers" --- fonts.conf and request syntax
+require"luaotfload-parsers" --- fonts.conf, configuration, and request syntax
+require"luaotfload-configuration" --- configuration file handling
require"luaotfload-database"
require"alt_getopt"
@@ -736,13 +736,14 @@ set.
--]]--
local action_sequence = {
- "loglevel", "help", "version", "diagnose",
- "blacklist", "cache", "flush", "bisect",
- "generate", "list", "query",
+ "loglevel", "config", "help", "version",
+ "diagnose", "blacklist", "cache", "flush",
+ "bisect", "generate", "list", "query",
}
local action_pending = tabletohash(action_sequence, false)
+action_pending.config = true --- always read the configuration
action_pending.loglevel = true --- always set the loglevel
action_pending.generate = false --- this is the default action
@@ -755,6 +756,16 @@ actions.loglevel = function (job)
return true, true
end
+actions.config = function (job)
+ local config = luaotfload.config.read (job.extra_config)
+ --if job.print_config == true then
+ if true then
+ -- inspect (config)
+ return true, false
+ end
+ return true, true
+end
+
actions.version = function (job)
version_msg()
return true, false
@@ -1386,8 +1397,9 @@ local process_cmdline = function ( ) -- unit -> jobspec
}
local long_options = {
+ ["bisect"] = 1,
cache = 1,
- ["no-compress"] = "c",
+ conf = 1,
diagnose = 1,
["dry-run"] = "D",
["flush-lookups"] = "l",
@@ -1404,11 +1416,12 @@ local process_cmdline = function ( ) -- unit -> jobspec
["local"] = "L",
log = 1,
["max-fonts"] = 1,
- ["bisect"] = 1,
+ ["no-compress"] = "c",
["no-reload"] = "n",
["no-strip"] = 0,
["skip-read"] = "R",
["prefer-texmf"] = "p",
+ ["print-conf"] = 0,
quiet = "q",
["show-blacklist"] = "b",
stats = "S",
@@ -1520,8 +1533,20 @@ local process_cmdline = function ( ) -- unit -> jobspec
end
end
elseif v == "bisect" then
- result.bisect = optarg[n]
+ result.bisect = optarg[n]
action_pending.bisect = true
+ elseif v == "conf" then
+ local extra = stringexplode (optarg[n], ",+")
+ if extra then
+ local extra_config = result.extra_config
+ if extra_config then
+ table.append (extra_config, extra)
+ else
+ result.extra_config = extra
+ end
+ end
+ elseif v == "print-conf" then
+ result.print_config = true
end
end