diff options
Diffstat (limited to 'Master/texmf-dist/scripts/luaotfload/luaotfload-tool.lua')
-rwxr-xr-x | Master/texmf-dist/scripts/luaotfload/luaotfload-tool.lua | 751 |
1 files changed, 224 insertions, 527 deletions
diff --git a/Master/texmf-dist/scripts/luaotfload/luaotfload-tool.lua b/Master/texmf-dist/scripts/luaotfload/luaotfload-tool.lua index 801ae72a284..fd84fa4701d 100755 --- a/Master/texmf-dist/scripts/luaotfload/luaotfload-tool.lua +++ b/Master/texmf-dist/scripts/luaotfload/luaotfload-tool.lua @@ -4,11 +4,13 @@ -- DESCRIPTION: database functionality -- REQUIREMENTS: luaotfload 2.2 -- AUTHOR: Khaled Hosny, Élie Roux, Philipp Gesang --- VERSION: 2.3b +-- VERSION: 2.4 -- LICENSE: GPL v2 --- MODIFIED: 2013-06-02 19:23:54+0200 +-- MODIFIED: 2013-07-28 13:12:04+0200 ----------------------------------------------------------------------- +local version = "2.4" --- <int: major>.<int: minor><alpha: fixes> + --[[doc-- This file was originally written (as \fileent{mkluatexfontdb.lua}) by @@ -42,19 +44,13 @@ kpse.set_program_name "luatex" local ioopen = io.open local iowrite = io.write local kpsefind_file = kpse.find_file -local lfsattributes = lfs.attributes -local lfsisfile = lfs.isfile -local lfsreadlink = lfs.readlink -local md5sumhexa = md5.sumhexa local next = next local osdate = os.date -local osremove = os.remove local ostype = os.type local stringexplode = string.explode local stringformat = string.format local stringlower = string.lower local stringrep = string.rep -local stringsub = string.sub local tableconcat = table.concat local texiowrite_nl = texio.write_nl local texiowrite = texio.write @@ -75,7 +71,7 @@ else -- 5.2 end -local C, Cg, Ct, P, S = lpeg.C, lpeg.Cg, lpeg.Ct, lpeg.P, lpeg.S +local C, Ct, P, S = lpeg.C, lpeg.Ct, lpeg.P, lpeg.S local lpegmatch = lpeg.match local loader_file = "luatexbase.loader.lua" @@ -106,11 +102,19 @@ to be the more appropriate. config = config or { } local config = config -config.luaotfload = config.luaotfload or { } -config.luaotfload.names_dir = config.luaotfload.names_dir or "names" -config.luaotfload.cache_dir = config.luaotfload.cache_dir or "fonts" -config.luaotfload.index_file = config.luaotfload.index_file +local luaotfloadconfig = config.luaotfload or { } +config.luaotfload = luaotfloadconfig +luaotfloadconfig.version = luaotfloadconfig.version or version +luaotfloadconfig.names_dir = luaotfloadconfig.names_dir or "names" +luaotfloadconfig.cache_dir = luaotfloadconfig.cache_dir or "fonts" +luaotfloadconfig.index_file = luaotfloadconfig.index_file or "luaotfload-names.lua" +luaotfloadconfig.formats = luaotfloadconfig.formats + or "otf,ttf,ttc,dfont" +luaotfloadconfig.reload = false +if not luaotfloadconfig.strip then + luaotfloadconfig.strip = true +end do -- we don’t have file.basename and the likes yet, so inline parser ftw local slash = P"/" @@ -124,9 +128,9 @@ do -- we don’t have file.basename and the likes yet, so inline parser ftw local self = lpegmatch(p_basename, stringlower(arg[0])) if self == "luaotfload-tool" then - config.luaotfload.self = "luaotfload-tool" + luaotfloadconfig.self = "luaotfload-tool" else - config.luaotfload.self = "mkluatexfontdb" + luaotfloadconfig.self = "mkluatexfontdb" end end @@ -136,26 +140,34 @@ config.lualibs.prefer_merged = true config.lualibs.load_extended = true require "lualibs" ---- dofile "util-jsn.lua" --- awaiting fix - -local lua_of_json = utilities.json.tolua -local ioloaddata = io.loaddata local tabletohash = table.tohash -local fileiswritable = file.iswritable -local fileisreadable = file.isreadable +local stringsplit = string.split --[[doc-- \fileent{luatex-basics-gen.lua} calls functions from the \luafunction{texio.*} library; too much for our taste. We intercept them with dummies. + +Also, it sets up dummies in place of the tables created by the Context +libraries. Since we have loaded the lualibs already this would cause +collateral damage for some libraries whose namespace would be +overridden. We employ our usual backup-restore strategy to work around +this. (Postponing the loading of the lualibs code is not an option +because the functionality is needed by basics-gen itself.) --doc]]-- local dummy_function = function ( ) end -local backup_write, backup_write_nl = texio.write, texio.write_nl +local backup = { + write = texio.write, + write_nl = texio.write_nl, + utilities = utilities, +} texio.write, texio.write_nl = dummy_function, dummy_function require"luaotfload-basics-gen.lua" -texio.write, texio.write_nl = backup_write, backup_write_nl + +texio.write, texio.write_nl = backup.write, backup.write_nl +utilities = backup.utilities require"luaotfload-override.lua" --- this populates the logs.* namespace require"luaotfload-database" @@ -163,15 +175,15 @@ require"alt_getopt" local names = fonts.names -local status_file = "luaotfload-status" -local status = require (status_file) +local status_file = "luaotfload-status" +local luaotfloadstatus = require (status_file) +luaotfloadconfig.status = luaotfloadstatus -local version = "2.3b" - -local sanitize_string = names.sanitize_string +local sanitize_fontname = names.sanitize_fontname local pathdata = names.path local names_plain = pathdata.index.lua +local names_gzip = names_plain .. ".gz" local names_bin = pathdata.index.luc local help_messages = { @@ -179,7 +191,7 @@ local help_messages = { Usage: %s [OPTIONS...] -Operations on the LuaTeX font database. +Operations on the Luaotfload font names database. This tool is part of the luaotfload package. Valid options are: @@ -195,7 +207,8 @@ This tool is part of the luaotfload package. Valid options are: -V --version print version and exit -h --help print this message --diagnose=CHECK run a self test procedure; one of "files", - "permissions", or "repository" + "environment", "index", "permissions", or + "repository" --alias=<name> force behavior of "luaotfload-tool" or legacy "mkluatexfontdb" @@ -204,10 +217,15 @@ This tool is part of the luaotfload package. Valid options are: DATABASE -u --update update the database + -n --no-reload suppress db update + --no-strip keep redundant information in db -f --force force re-indexing all fonts + -c --no-compress do not gzip index file (text version only) -l --flush-lookups empty lookup cache of font requests -D --dry-run skip loading of fonts, just scan + --formats=[+|-]EXTENSIONS set, add, or subtract formats to index -p --prefer-texmf prefer fonts in the TEXMF over system fonts + --max-fonts=N process at most N font files --find="font name" query the database for a font name -F --fuzzy look for approximate matches if --find fails @@ -242,7 +260,7 @@ The font cache will be written to Usage: %s [OPTION]... -Rebuild or update the LuaTeX font database. +Rebuild or update the Luaotfload font names database. Valid options: -f --force force re-indexing all fonts @@ -263,6 +281,7 @@ The font database will be saved to short = [[ Usage: luaotfload-tool [--help] [--version] [--verbose=<lvl>] [--update] [--force] [--prefer-texmf] + [--dry-run] [--formats=<extension list>] [--find=<font name>] [--fuzzy] [--info] [--inspect] [--list=<criterion>] [--fields=<field list>] [--cache=<directive>] [--flush-lookups] @@ -275,25 +294,25 @@ Enter 'luaotfload-tool --help' for a larger list of options. local help_msg = function (version) local template = help_messages[version] iowrite(stringformat(template, - config.luaotfload.self, - names_plain, + luaotfloadconfig.self, +-- names_plain, + names_gzip, names_bin, caches.getwritablepath ( - config.luaotfload.cache_dir))) + luaotfloadconfig.cache_dir))) end local version_msg = function ( ) - texiowrite_nl(stringformat( - "%s version %q\n" .. -- no \z due to 5.1 compatibility - "revision %q\n" .. - "database version %q\n" .. - "Lua interpreter: %s; version %q\n", - config.luaotfload.self, - version, - status.notes.revision, - names.version, - runtime[1], - runtime[2])) + local out = function (...) texiowrite_nl (stringformat (...)) end + out ("%s version %q", luaotfloadconfig.self, version) + out ("revision %q", luaotfloadstatus.notes.revision) + out ("database version %q", names.version) + out ("Lua interpreter: %s; version %q", runtime[1], runtime[2]) + out ("Luatex SVN revision %d", status.luatex_svn) + out ("Luatex version %.2f.%d", + status.luatex_version / 100, + status.luatex_revision) + out "" end @@ -479,7 +498,7 @@ local general_fields = { { "design_range_bottom", "l", "design size min" }, { "design_range_top", "l", "design size max" }, { "fontstyle_id", "l", "font style id" }, - { "fontstyle_name", "l", "font style name" }, + { "fontstyle_name", "S", "font style name" }, { "strokewidth", "l", "stroke width" }, { "units_per_em", "l", "units per em" }, { "ascent", "l", "ascender height" }, @@ -499,13 +518,39 @@ local display_general = function (fullinfo) local val if mode == "l" then val = fullinfo[key] + elseif mode == "S" then --- style names table + local data = fullinfo[key] + if type (data) == "table" then + if #data > 0 then + for n = 1, #data do + local nth = data[n] + if nth.lang == 1033 then + val = nth.name + goto found + end + end + val = next (data).name + else + val = "" + end + ::found:: + else + val = data + end elseif mode == "n" then local v = fullinfo[key] if v then val = #fullinfo[key] end elseif mode == "d" then - val = osdate("%F %T", fullinfo[key]) + if ostype == "unix" then + val = osdate("%F %T", fullinfo[key]) + else + --- the MS compiler doesn’t support C99, so + --- strftime is missing some functionality; + --- see loslib.c for details. + val = osdate("%Y-%m-d %H:%M:%S", fullinfo[key]) + end end if not val then val = "<none>" @@ -520,7 +565,6 @@ local print_features = function (features) for script, languages in next, data do local field = stringformat(key_fmt, script).. fieldseparator .. " " local wd_field = #field - --inspect(languages.list) local lines = reflow(languages.list, textwidth - wd_field) local indent = stringrep(" ", wd_field) texiowrite_nl(field) @@ -577,11 +621,20 @@ end local display_features = function (gsub, gpos) texiowrite_nl "" - print_heading("Features", 2) - print_heading("GSUB Features", 3) - display_feature_set(gsub) - print_heading("GPOS Features", 3) - display_feature_set(gpos) + + if gsub or gpos then + print_heading("Features", 2) + + if gsub then + print_heading("GSUB Features", 3) + display_feature_set(gsub) + end + + if gpos then + print_heading("GPOS Features", 3) + display_feature_set(gpos) + end + end end local show_full_info = function (path, subfont, warnings) @@ -615,7 +668,7 @@ subfont_by_name = function (lst, askedname, n) local font = lst[n] if font then - if sanitize_string(font.fullname) == askedname then + if sanitize_fontname (font.fullname) == askedname then return font end return subfont_by_name (lst, askedname, n+1) @@ -632,10 +685,10 @@ The font info knows two levels of detail: --doc]]-- local show_font_info = function (basename, askedname, detail, warnings) - local filenames = names.data.filenames + local filenames = names.data().files local index = filenames.base[basename] local fullname = filenames.full[index] - askedname = sanitize_string(askedname) + askedname = sanitize_fontname (askedname) if not fullname then -- texmf fullname = resolvers.findfile(basename) end @@ -690,6 +743,7 @@ local action_sequence = { "blacklist", "cache", "flush", "generate", "list", "query", } + local action_pending = tabletohash(action_sequence, false) action_pending.loglevel = true --- always set the loglevel @@ -718,8 +772,8 @@ end actions.blacklist = function (job) names.read_blacklist() local n = 0 - for n, entry in next, table.sortedkeys(fonts.names.blacklist) do - texiowrite_nl(stringformat("(%d %s)", n, entry)) + for n, entry in next, table.sortedkeys(names.blacklist) do + iowrite (stringformat("(%d %s)\n", n, entry)) end return true, false end @@ -729,8 +783,7 @@ actions.generate = function (job) fontnames = names.update(fontnames, job.force_reload, job.dry_run) logs.names_report("info", 2, "db", "Fonts in the database: %i", #fontnames.mappings) - local success = names.save(fontnames) - if success then + if names.data() then return true, true end return false, false @@ -769,16 +822,37 @@ end actions.query = function (job) + require "luaotfload-features" + local query = job.query + local tmpspec = { name = query, lookup = "name", - specification = "name:" .. query, + specification = query, optsize = 0, + features = { }, } - local foundname, subfont, success = - fonts.names.resolve(nil, nil, tmpspec) + tmpspec = names.handle_request (tmpspec) + + if not tmpspec.size then + tmpspec.size = 655360 --- assume 10pt + end + + local foundname, subfont, success + + if tmpspec.lookup == "name" + or tmpspec.lookup == "anon" --- not *exactly* as resolvers.anon + then + foundname, subfont = names.resolve_name (tmpspec) + if foundname then + foundname, _, success = names.crude_file_lookup (foundname) + end + elseif tmpspec.lookup == "file" then + foundname, _, success = + names.crude_file_lookup (tmpspec.name) + end if success then logs.names_report(false, 0, @@ -792,15 +866,18 @@ actions.query = function (job) "Resolved file name %q", foundname) end if job.show_info then - show_font_info(foundname, query, job.full_info, job.warnings) + show_font_info (foundname, query, job.full_info, job.warnings) + iowrite "\n" end else logs.names_report(false, 0, - "resolve", "Cannot find %q.", query) + "resolve", "Cannot find %q in index.", query) + logs.names_report(false, 0, + "resolve", "Hint: use the --fuzzy option to display suggestions.", query) if job.fuzzy == true then logs.names_report(false, 0, "resolve", "Looking for close matches, this may take a while ...") - local success = fonts.names.find_closest(query, job.fuzzy_limit) + local _success = names.find_closest(query, job.fuzzy_limit) end end return true, true @@ -813,22 +890,31 @@ end local get_fields get_fields = function (entry, fields, acc, n) if not acc then - return get_fields(entry, fields, { }, 1) + return get_fields (entry, fields, { }, 1) end - local field = fields[n] + local field = fields [n] if field then - local value = entry[field] - acc[#acc+1] = value or false - return get_fields(entry, fields, acc, n+1) + local chain = stringsplit (field, "->") + local tmp = entry + for i = 1, #chain - 1 do + tmp = tmp [chain [i]] + if not tmp then + --- invalid field + break + end + end + if tmp then + local value = tmp [chain [#chain]] + acc[#acc+1] = value or false + else + acc[#acc+1] = false + end + return get_fields (entry, fields, acc, n+1) end return acc end -local comma = P"," -local noncomma = 1-comma -local split_comma = Ct((C(noncomma^1) + comma)^1) - local separator = "\t" --- could be “,” for csv local format_fields format_fields = function (fields, acc, n) @@ -864,22 +950,27 @@ set_primary_field = function (fields, addme, acc, n) return acc end +local splitcomma = names.patterns.splitcomma + actions.list = function (job) local criterion = job.criterion - local asked_fields = job.asked_fields + local name_index = names.data () + if asked_fields then - asked_fields = lpegmatch(split_comma, asked_fields) - else + asked_fields = lpegmatch(splitcomma, asked_fields) + end + + if not asked_fields then --- some defaults - asked_fields = { "fullname", "version", } + asked_fields = { "plainname", "version", } end - if not names.data then - names.data = names.load() + if not name_index then + name_index = names.load() end - local mappings = names.data.mappings + local mappings = name_index.mappings local nmappings = #mappings if criterion == "*" then @@ -917,7 +1008,15 @@ actions.list = function (job) local categories, by_category = { }, { } for i=1, nmappings do local entry = mappings[i] - local value = entry[criterion] + local tmp = entry + local chain = stringsplit (criterion, "->") + for i = 1, #chain - 1 do + tmp = tmp [chain [i]] + if not tmp then + break + end + end + local value = tmp and tmp [chain [#chain]] or "<none>" if value then --value = tostring(value) local entries = by_category[value] @@ -951,447 +1050,15 @@ actions.list = function (job) end end + texiowrite_nl "" + return true, true end -do - local out = function (...) - logs.names_report (false, 0, "diagnose", ...) - end - - local verify_files = function (errcnt, status) - out "================ verify files =================" - local hashes = status.hashes - local notes = status.notes - if not hashes or #hashes == 0 then - out ("FAILED: cannot read checksums from %s.", status_file) - return 1/0 - elseif not notes then - out ("FAILED: cannot read commit metadata from %s.", - status_file) - return 1/0 - end - - out ("Luaotfload revision %s.", notes.revision) - out ("Committed by %s.", notes.committer) - out ("Timestamp %s.", notes.timestamp) - - local nhashes = #hashes - out ("Testing %d files for integrity.", nhashes) - for i = 1, nhashes do - local fname, canonicalsum = unpack (hashes[i]) - local location = kpsefind_file (fname) - or kpsefind_file (fname, "texmfscripts") - if not location then - errcnt = errcnt + 1 - out ("FAILED: file %s missing.", fname) - else - out ("File: %s.", location) - local raw = ioloaddata (location) - if not raw then - errcnt = errcnt + 1 - out ("FAILED: file %d not readable.", fname) - else - local sum = md5sumhexa (raw) - if sum ~= canonicalsum then - errcnt = errcnt + 1 - out ("FAILED: checksum mismatch for file %s.", - fname) - out ("Expected %s.", canonicalsum) - out ("Got %s.", sum) - else - out ("Ok, %s passed.", fname) - end - end - end - end - return errcnt - end - - local get_tentative_attributes = function (file) - if not lfsisfile (file) then - local chan = ioopen (file, "w") - if chan then - chan:close () - local attributes = lfsattributes (file) - os.remove (file) - return attributes - end - end - end - - local p_permissions = Ct(Cg(Ct(C(1) * C(1) * C(1)), "u") - * Cg(Ct(C(1) * C(1) * C(1)), "g") - * Cg(Ct(C(1) * C(1) * C(1)), "o")) - - local analyze_permissions = function (raw) - return lpegmatch (p_permissions, raw) - end - - local trailingslashes = P"/"^1 * P(-1) - local stripslashes = C((1 - trailingslashes)^0) - - local get_permissions = function (t, location) - if stringsub (location, #location) == "/" then - --- strip trailing slashes (lfs idiosyncrasy on Win) - location = lpegmatch (stripslashes, location) - end - local attributes = lfsattributes (location) - - if not attributes and t == "f" then - attributes = get_tentative_attributes (location) - if not attributes then - return false - end - end - - local permissions - - if fileisreadable (location) then - --- link handling appears to be unnecessary because - --- lfs.attributes() will return the information on - --- the link target. - if mode == "link" then --follow and repeat - location = lfsreadlink (location) - attributes = lfsattributes (location) - end - end - - permissions = analyze_permissions (attributes.permissions) - - return { - location = location, - mode = attributes.mode, - owner = attributes.uid, --- useless on windows - permissions = permissions, - attributes = attributes, - } - end - - local check_conformance = function (spec, permissions, errcnt) - local uid = permissions.attributes.uid - local gid = permissions.attributes.gid - local raw = permissions.attributes.permissions - - out ("Owner: %d, group %d, permissions %s.", uid, gid, raw) - if ostype == "unix" then - if uid == 0 or gid == 0 then - out "Owned by the superuser, permission conflict likely." - errcnt = errcnt + 1 - end - end - - local user = permissions.permissions.u - if spec.r == true then - if user[1] == "r" then - out "Readable: ok." - else - out "Not readable: permissions need fixing." - errcnt = errcnt + 1 - end - end - - if spec.w == true then - if user[2] == "w" - or fileiswritable (permissions.location) then - out "Writable: ok." - else - out "Not writable: permissions need fixing." - errcnt = errcnt + 1 - end - end - - return errcnt - end - - local path = names.path - - local desired_permissions = { - { "d", {"r","w"}, function () return caches.getwritablepath () end }, - { "d", {"r","w"}, path.globals.prefix }, - { "f", {"r","w"}, path.index.lua }, - { "f", {"r","w"}, path.index.luc }, - { "f", {"r","w"}, path.lookups.lua }, - { "f", {"r","w"}, path.lookups.luc }, - } - - local check_permissions = function (errcnt) - out [[=============== file permissions ==============]] - for i = 1, #desired_permissions do - local t, spec, path = unpack (desired_permissions[i]) - if type (path) == "function" then - path = path () - end - - spec = tabletohash (spec) - - out ("Checking permissions of %s.", path) - - local permissions = get_permissions (t, path) - if permissions then - --inspect (permissions) - errcnt = check_conformance (spec, permissions, errcnt) - else - errcnt = errcnt + 1 - end - end - return errcnt - end - - local check_upstream - - if kpsefind_file ("https.lua", "lua") == nil then - check_upstream = function (errcnt) - out [[============= upstream repository ============= - WARNING: Cannot retrieve repository data. - Github API access requires the luasec library. - Grab it from <https://github.com/brunoos/luasec> - and retry.]] - return errcnt - end - else - --- github api stuff begin - local https = require "ssl.https" - - local gh_api_root = [[https://api.github.com]] - local release_url = [[https://github.com/lualatex/luaotfload/releases]] - local luaotfload_repo = [[lualatex/luaotfload]] - local user_agent = [[lualatex/luaotfload integrity check]] - local shortbytes = 8 - - local gh_shortrevision = function (rev) - return stringsub (rev, 1, shortbytes) - end - - local gh_encode_parameters = function (parameters) - local acc = {} - for field, value in next, parameters do - --- unsafe, non-urlencoded coz it’s all ascii chars - acc[#acc+1] = field .. "=" .. value - end - return "?" .. tableconcat (acc, "&") - end - - local gh_make_url = function (components, parameters) - local url = tableconcat ({ gh_api_root, - unpack (components) }, - "/") - if parameters then - url = url .. gh_encode_parameters (parameters) - end - return url - end - - local alright = [[HTTP/1.1 200 OK]] - - local gh_api_request = function (...) - local args = {...} - local nargs = #args - local final = args[nargs] - local request = { - url = "", - headers = { ["user-agent"] = user_agent }, - } - if type (final) == "table" then - args[nargs] = nil - request = gh_make_url (args, final) - else - request = gh_make_url (args) - end - - out ("Requesting <%s>.", request) - local response, code, headers, status - = https.request (request) - if status ~= alright then - out "Request failed!" - return false - end - return response - end - - local gh_api_checklimit = function (headers) - local rawlimit = gh_api_request "rate_limit" - local limitdata = lua_of_json (rawlimit) - if not limitdata and limitdata.rate then - out "Cannot parse API rate limit." - return false - end - limitdata = limitdata.rate - - local limit = tonumber (limitdata.limit) - local left = tonumber (limitdata.remaining) - local reset = tonumber (limitdata.reset) - - out ("%d of %d Github API requests left.", left, limit) - if left == 0 then - out ("Cannot make any more API requests.") - out ("Try again later at %s.", osdate ("%F %T", reset)) - end - return true - end - - local gh_tags = function () - out "Fetching tags from repository, please stand by." - local rawtags = gh_api_request ("repos", - luaotfload_repo, - "tags") - local taglist = lua_of_json (rawtags) - if not taglist or #taglist == 0 then - out "Cannot parse response." - return false - end - - local ntags = #taglist - out ("Repository contains %d tags.", ntags) - local _idx, latest = next (taglist) - out ("The most recent release is %s (revision %s).", - latest.name, - gh_shortrevision (latest.commit.sha)) - return latest - end - - local gh_compare = function (head, base) - if base == nil then - base = "HEAD" - end - out ("Fetching comparison between %s and %s, \z - please stand by.", - gh_shortrevision (head), - gh_shortrevision (base)) - local comparison = base .. "..." .. head - local rawstatus = gh_api_request ("repos", - luaotfload_repo, - "compare", - comparison) - local status = lua_of_json (rawstatus) - if not status then - out "Cannot parse response for status request." - return false - end - return status - end - - local gh_news = function (since) - local compared = gh_compare (since) - if not compared then - return false - end - local behind_by = compared.behind_by - local ahead_by = compared.ahead_by - local status = compared.status - out ("Comparison state: %s.", status) - if behind_by > 0 then - out ("Your Luaotfload is %d \z - revisions behind upstream.", - behind_by) - return behind_by - elseif status == "ahead" then - out "Since you are obviously from the future \z - I assume you already know the repository state." - else - out "Everything up to date. \z - Luaotfload is in sync with upstream." - end - return false - end - - local gh_catchup = function (current, latest) - local compared = gh_compare (latest, current) - local ahead_by = tonumber (compared.ahead_by) - if ahead_by > 0 then - local permalink_url = compared.permalink_url - out ("Your Luaotfload is %d revisions \z - behind the most recent release.", - ahead_by) - out ("To view the commit log, visit <%s>.", - permalink_url) - out ("You can grab an up to date tarball at <%s>.", - release_url) - return true - else - out "There weren't any new releases in the meantime." - out "Luaotfload is up to date." - end - return false - end - - check_upstream = function (current) - out "============= upstream repository =============" - local _succ = gh_api_checklimit () - local behind = gh_news (current) - if behind then - local latest = gh_tags () - local _behind = gh_catchup (current, - latest.commit.sha, - latest.name) - end - end - - --- trivium: diff since the first revision as pushed by Élie - --- in 2009 - --- local firstrevision = "c3ccb3ee07e0a67171c24960966ae974e0dd8e98" - --- check_upstream (firstrevision) - end - --- github api stuff end - - local anamneses = { "files", "repository", "permissions" } - - actions.diagnose = function (job) - local errcnt = 0 - local asked = job.asked_diagnostics - if asked == "all" or asked == "thorough" then - asked = tabletohash (anamneses, true) - else - asked = lpegmatch(split_comma, asked) - asked = tabletohash (asked, true) - end - - if asked.files == true then - errcnt = verify_files (errcnt, status) - asked.files = nil - end - if asked.permissions == true then - errcnt = check_permissions (errcnt) - asked.permissions = nil - end - if asked.repository == true then - check_upstream (status.notes.revision) - asked.repository = nil - end - - local rest = next (asked) - if rest ~= nil then --> something unknown - out ("Unknown diagnostic %q.", rest) - end - if errcnt == 0 then --> success - out ("Everything appears to be in order, \z - you may sleep well.") - return true, false - end - out ( [[=============================================== - WARNING - =============================================== - - The diagnostic detected %d errors. - - This version of luaotfload may have been - tampered with. Modified versions of the - luaotfload source are unsupported. Read the log - carefully and get a clean version from CTAN or - github: - - × http://ctan.org/tex-archive/macros/luatex/generic/luaotfload - × https://github.com/lualatex/luaotfload/releases - - If you are uncertain as to how to proceed, then - ask on the lualatex mailing list: - - http://www.tug.org/mailman/listinfo/lualatex-dev - - =============================================== -]], errcnt) - return true, false - end +actions.diagnose = function (job) + --- diagnostics are loaded on demand + local diagnose = require "luaotfload-diagnostics.lua" + return diagnose (job) end --- stuff to be carried out prior to exit @@ -1433,12 +1100,14 @@ local process_cmdline = function ( ) -- unit -> jobspec local long_options = { alias = 1, cache = 1, + ["no-compress"] = "c", diagnose = 1, ["dry-run"] = "D", ["flush-lookups"] = "l", fields = 1, find = 1, force = "f", + formats = 1, fuzzy = "F", help = "h", info = "i", @@ -1446,16 +1115,21 @@ local process_cmdline = function ( ) -- unit -> jobspec limit = 1, list = 1, log = 1, + ["max-fonts"] = 1, + ["no-reload"] = "n", + ["no-strip"] = 0, + ["skip-read"] = "R", ["prefer-texmf"] = "p", quiet = "q", ["show-blacklist"] = "b", + stats = "S", update = "u", - verbose = 1 , + verbose = 1, version = "V", warnings = "w", } - local short_options = "bDfFiIlpquvVhw" + local short_options = "bcDfFiIlnpqRSuvVhw" local options, _, optarg = alt_getopt.get_ordered_opts (arg, short_options, long_options) @@ -1471,7 +1145,7 @@ local process_cmdline = function ( ) -- unit -> jobspec if result.log_level > 0 then result.log_level = result.log_level + 1 else - result.log_level = 2 + result.log_level = 1 end elseif v == "V" then action_pending["version"] = true @@ -1512,7 +1186,7 @@ local process_cmdline = function ( ) -- unit -> jobspec result.show_info = true result.full_info = true elseif v == "alias" then - config.luaotfload.self = optarg[n] + luaotfloadconfig.self = optarg[n] elseif v == "l" then action_pending["flush"] = true elseif v == "list" then @@ -1526,16 +1200,39 @@ local process_cmdline = function ( ) -- unit -> jobspec elseif v == "D" then result.dry_run = true elseif v == "p" then - config.luaotfload.prioritize = "texmf" + names.set_location_precedence { + "local", "texmf", "system" + } elseif v == "b" then action_pending["blacklist"] = true elseif v == "diagnose" then action_pending["diagnose"] = true result.asked_diagnostics = optarg[n] + elseif v == "formats" then + names.set_font_filter (optarg[n]) + elseif v == "n" then + luaotfloadconfig.update_live = false + elseif v == "S" then + luaotfloadconfig.statistics = true + elseif v == "R" then + --- dev only, undocumented + luaotfloadconfig.skip_read = true + elseif v == "c" then + luaotfloadconfig.compress = false + elseif v == "no-strip" then + luaotfloadconfig.strip = false + elseif v == "max-fonts" then + local n = optarg[n] + if n then + n = tonumber(n) + if n and n > 0 then + luaotfloadconfig.max_fonts = n + end + end end end - if config.luaotfload.self == "mkluatexfontdb" then + if luaotfloadconfig.self == "mkluatexfontdb" then --- TODO drop legacy ballast after 2.4 result.help_version = "mkluatexfontdb" action_pending["generate"] = true result.log_level = math.max(1, result.log_level) |