diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/luaotfload-configuration.lua | 255 | ||||
| -rwxr-xr-x | src/luaotfload-tool.lua | 41 | 
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  | 
