diff options
Diffstat (limited to 'Master/texmf-dist/scripts/lyluatex/lyluatex-options.lua')
-rwxr-xr-x | Master/texmf-dist/scripts/lyluatex/lyluatex-options.lua | 266 |
1 files changed, 0 insertions, 266 deletions
diff --git a/Master/texmf-dist/scripts/lyluatex/lyluatex-options.lua b/Master/texmf-dist/scripts/lyluatex/lyluatex-options.lua deleted file mode 100755 index 62ec72a3c3c..00000000000 --- a/Master/texmf-dist/scripts/lyluatex/lyluatex-options.lua +++ /dev/null @@ -1,266 +0,0 @@ --- luacheck: ignore ly warn info log self luatexbase internalversion font fonts tex token kpse status -local err, warn, info, log = luatexbase.provides_module({ - name = "lyluatex-options", - version = '1.0f', --LYLUATEX_VERSION - date = "2019/05/27", --LYLUATEX_DATE - description = "Module lyluatex-options.", - author = "The Gregorio Project − (see Contributors.md)", - copyright = "2015-2019 - jperon and others", - license = "MIT", -}) - ---[[ - This module provides functionality to handle package options and make them - configurable in a fine-grained fashion as - - package options - - local options (for individual instances of commands/environments) - - changed “from here on” within a document. - --- ]] - -local lib = require(kpse.find_file("lyluatex-lib.lua") or "lyluatex-lib.lua") -local optlib = {} -- namespace for the returned table -local Opts = {options = {}} -- Options class -Opts.__index = function (self, k) return self.options[k] or rawget(Opts, k) end -setmetatable(Opts, Opts) - - -function Opts:new(opt_prefix, declarations) ---[[ - Declare package options along with their default and - accepted values. To *some* extent also provide type checking. - - opt_prefix: the prefix/name by which the lyluatex-options module is - referenced in the parent LaTeX document (preamble or package). - This is required to write the code calling optlib.set_option into - the option declaration. - - declarations: a definition table stored in the calling module (see below) - Each entry in the 'declarations' table represents one package option, with each - value being an array (table with integer indexes instead of keys). For - details please refer to the manual. ---]] - local o = setmetatable( - { - declarations = declarations, - options = {} - }, - self - ) - local exopt = '' - for k, v in pairs(declarations) do - o.options[k] = v[1] or '' - tex.sprint(string.format([[ -\DeclareOptionX{%s}{\directlua{ - %s:set_option('%s', '\luatexluaescapestring{#1}') -}}%% -]], - k, opt_prefix, k - )) - exopt = exopt..k..'='..(v[1] or '')..',' - end - tex.sprint([[\ExecuteOptionsX{]]..exopt..[[}%%]], [[\ProcessOptionsX]]) - return o -end - -function Opts:check_local_options(opts, ignore_declarations) ---[[ - Parse the given options (options passed to a command/environment), - sanitize them against the global package options and return a table - with the local options that should then supersede the global options. - If ignore_declaration is given any non-false value the sanitization - step is skipped (i.e. local options are only parsed and duplicates - rejected). ---]] - local options = {} - local next_opt = opts:gmatch('([^,]+)') -- iterator over options - for opt in next_opt do - local k, v = opt:match('([^=]+)=?(.*)') - if k then - if v and v:sub(1, 1) == '{' then -- handle keys with {multiple, values} - while select(2, v:gsub('{', '')) ~= select(2, v:gsub('}', '')) do v = v..','..next_opt() end - v = v:sub(2, -2) -- remove { } - end - if not ignore_declarations then - k, v = self:sanitize_option(k:gsub('^%s', ''), v:gsub('^%s', '')) - end - if k then - if options[k] then err('Option %s is set two times for the same score.', k) - else options[k] = v - end - end - end - end - return options -end - -function Opts:is_neg(k) ---[[ - Type check for a 'negative' option. This is an existing option - name prefixed with 'no' (e.g. 'noalign') ---]] - local _, i = k:find('^no') - return i and lib.contains_key(self.declarations, k:sub(i + 1)) -end - -function Opts:sanitize_option(k, v) ---[[ - Check and (if necessary) adjust the value of a given option. - Reject undefined options - Check 'negative' options - Handle boolean options (empty strings or 'false'), set them to real booleans ---]] - local declarations = self.declarations - if k == '' or k == 'noarg' then return end - if not lib.contains_key(declarations, k) then err('Unknown option: '..k) end - -- aliases - if declarations[k] and declarations[k][2] == optlib.is_alias then - if declarations[k][1] == v then return - else k = declarations[k] end - end - -- boolean - if v == 'false' then v = false end - -- negation (for example, noindent is the negation of indent) - if self:is_neg(k) then - if v ~= nil and v ~= 'default' then - k = k:gsub('^no(.*)', '%1') - v = not v - else return - end - end - return k, v -end - -function Opts:set_option(k, v) ---[[ - Set an option for the given prefix to be in effect from this point on. - Raises an error if the option is not declared or does not meet the - declared expectations. (TODO: The latter has to be integrated by extracting - optlib.validate_option from optlib.validate_options and call it in - sanitize_option). ---]] - k, v = self:sanitize_option(k, v) - if k then - self.options[k] = v - self:validate_option(k) - end -end - -function Opts:validate_option(key, options_obj) ---[[ - Validate an (already sanitized) option against its expected values. - With options_obj a local options table can be provided, - otherwise the global options stored in OPTIONS are checked. ---]] - local package_opts = self.declarations - local options = options_obj or self.options - local unexpected - if options[key] == 'default' then - -- Replace 'default' with an actual value - options[key] = package_opts[key][1] - unexpected = options[key] == nil - end - if not lib.contains(package_opts[key], options[key]) and package_opts[key][2] then - -- option value is not in the array of accepted values - if type(package_opts[key][2]) == 'function' then package_opts[key][2](key, options[key]) - else unexpected = true - end - end - if unexpected then - err([[ - Unexpected value "%s" for option %s: - authorized values are "%s" - ]], - options[key], key, table.concat(package_opts[key], ', ') - ) - end -end - -function Opts:validate_options(options_obj) ---[[ - Validate the given set of options against the option declaration - table for the given prefix. - With options_obj a local options table can be provided, - otherwise the global options stored in OPTIONS are checked. ---]] - for k, _ in lib.orderedpairs(self.declarations) do - self:validate_option(k, options_obj) - end -end - - -function optlib.is_alias() ---[[ - This function doesn't do anything, but if an option is defined - as an alias, its second parameter will be this function, so the - test declarations[k][2] == optlib.is_alias in Opts:sanitize_options - will return true. ---]] -end - - -function optlib.is_dim(k, v) ---[[ - Type checking for options that accept a LaTeX dimension. - This can be - - a number (integer or float) - - a number with unit - - a (multiplied) TeX length - (see error message in code for examples) ---]] - if v == '' or v == false or tonumber(v) then return true end - local n, sl, u = v:match('^%d*%.?%d*'), v:match('\\'), v:match('%a+') - -- a value of number - backslash - length is a dimension - -- invalid input will be prevented in by the LaTeX parser already - if n and sl and u then return true end - if n and lib.contains(lib.TEX_UNITS, u) then return true end - err([[ -Unexpected value "%s" for dimension %s: -should be either a number (for example "12"), -a number with unit, without space ("12pt"), -or a (multiplied) TeX length (".8\linewidth") -]], - v, k - ) -end - - -function optlib.is_neg(k, _) ---[[ - Type check for a 'negative' option. At this stage, - we only check that it begins with 'no'. ---]] - return k:find('^no') -end - - -function optlib.is_num(_, v) ---[[ - Type check for number options ---]] - return v == '' or tonumber(v) -end - - -function optlib.is_str(_, v) ---[[ - Type check for string options ---]] - return type(v) == 'string' -end - - -function optlib.merge_options(base_opt, super_opt) ---[[ - Merge two tables. - Create a new table as a copy of base_opt, then merge with - super_opt. Entries in super_opt supersede (i.e. overwrite) - colliding entries in base_opt. ---]] - local result = {} - for k, v in pairs(base_opt) do result[k] = v end - for k, v in pairs(super_opt) do result[k] = v end - return result -end - - -optlib.Opts = Opts -return optlib |