diff options
| -rw-r--r-- | luaotfload-database.lua | 210 | ||||
| -rw-r--r-- | luaotfload-override.lua | 11 | ||||
| -rwxr-xr-x | luaotfload-tool.lua | 78 | ||||
| -rw-r--r-- | luaotfload-tool.rst | 20 | ||||
| -rw-r--r-- | luaotfload.dtx | 40 | 
5 files changed, 295 insertions, 64 deletions
diff --git a/luaotfload-database.lua b/luaotfload-database.lua index 33b6b29..60a7977 100644 --- a/luaotfload-database.lua +++ b/luaotfload-database.lua @@ -239,7 +239,7 @@ end  local crude_file_lookup  local crude_file_lookup_verbose  local find_closest -local flush_cache +local flush_lookup_cache  local font_fullinfo  local load_names  local load_lookups @@ -259,8 +259,8 @@ local fonts_reloaded = false  --- limit output when approximate font matching (luaotfload-tool -F)  local fuzzy_limit = 1 --- display closest only ---- unit -> dbobj -load_names = function ( ) +--- bool? -> dbobj +load_names = function (dry_run)      local starttime = os.gettimeofday()      local foundname, data = load_lua_file(names.path.path) @@ -273,7 +273,7 @@ load_names = function ( )          report("both", 0, "db",              [[Font names database not found, generating new one.               This can take several minutes; please be patient.]]) -        data = update_names(fontnames_init(false)) +        data = update_names(fontnames_init(false), nil, dry_run)          local success = save_names(data)          if not success then              report("both", 0, "db", "Database creation unsuccessful.") @@ -868,7 +868,9 @@ end  --- we return true if the fond is new or re-indexed  --- string -> dbobj -> dbobj -> bool  local load_font = function (fullname, fontnames, newfontnames) -    if not fullname then return false end +    if not fullname then +        return false +    end      local newmappings   = newfontnames.mappings      local newstatus     = newfontnames.status @@ -1070,15 +1072,20 @@ for key, value in next, font_extensions do     font_extensions_set[value] = true  end ---- string -> dbobj -> dbobj -> bool -> (int * int) -local scan_dir = function (dirname, fontnames, newfontnames) -    --[[ -    This function scans a directory and populates the list of fonts +--[[doc-- + +    scan_dir() scans a directory and populates the list of fonts      with all the fonts it finds. -    - dirname is the name of the directory to scan -    - names is the font database to fill -> no such term!!! -    - texmf used to be a boolean saying if we are scanning a texmf directory -    ]] + +        · dirname   : name of the directory to scan +        · fontnames : current font db object +        · newnames  : font db object to fill +        · dry_run   : don’t touch anything + +--doc]]-- + +--- string -> dbobj -> dbobj -> bool -> (int * int) +local scan_dir = function (dirname, fontnames, newfontnames, dry_run)      local n_scanned, n_new = 0, 0   --- total of fonts collected      report("both", 2, "db", "scanning directory %s", dirname)      for _,i in next, font_extensions do @@ -1092,9 +1099,16 @@ local scan_dir = function (dirname, fontnames, newfontnames)              for j=1, n_found do                  local fullname = found[j]                  fullname = path_normalize(fullname) -                report("both", 4, "db", "loading font “%s”", fullname) -                local new = load_font(fullname, fontnames, newfontnames) -                if new then n_new = n_new + 1 end +                local new +                if dry_run == true then +                    report("both", 1, "db", "would have been loading “%s”", fullname) +                else +                    report("both", 4, "db", "loading font “%s”", fullname) +                    local new = load_font(fullname, fontnames, newfontnames) +                    if new == true then +                        n_new = n_new + 1 +                    end +                end              end          end      end @@ -1102,7 +1116,8 @@ local scan_dir = function (dirname, fontnames, newfontnames)      return n_scanned, n_new  end -local function scan_texmf_fonts(fontnames, newfontnames) +--- dbobj -> dbobj -> bool? -> (int * int) +local scan_texmf_fonts = function (fontnames, newfontnames, dry_run)      local n_scanned, n_new = 0, 0      --[[      This function scans all fonts in the texmf tree, through kpathsea @@ -1118,7 +1133,7 @@ local function scan_texmf_fonts(fontnames, newfontnames)      if not stringis_empty(fontdirs) then          for _,d in next, filesplitpath(fontdirs) do              report("info", 4, "db", "Entering directory %s", d) -            local found, new = scan_dir(d, fontnames, newfontnames) +            local found, new = scan_dir(d, fontnames, newfontnames, dry_run)              n_scanned = n_scanned + found              n_new     = n_new     + new          end @@ -1352,6 +1367,7 @@ do --- closure for read_fonts_conf()  end --- read_fonts_conf closure  --- TODO stuff those paths into some writable table +--- unit -> string list  local function get_os_dirs()      if os.name == 'macosx' then          return { @@ -1374,7 +1390,8 @@ local function get_os_dirs()      return {}  end -local function scan_os_fonts(fontnames, newfontnames) +--- dbobj -> dbobj -> bool? -> (int * int) +local scan_os_fonts = function (fontnames, newfontnames, dry_run)      local n_scanned, n_new = 0, 0      --[[      This function scans the OS fonts through @@ -1384,23 +1401,27 @@ local function scan_os_fonts(fontnames, newfontnames)      ]]      report("info", 2, "db", "Scanning OS fonts...")      report("info", 3, "db", "Searching in static system directories...") -    for _,d in next, get_os_dirs() do -        local found, new = scan_dir(d, fontnames, newfontnames) +    for _, d in next, get_os_dirs() do +        local found, new = scan_dir(d, fontnames, newfontnames, dry_run)          n_scanned = n_scanned + found          n_new     = n_new     + new      end      return n_scanned, n_new  end -flush_cache = function () +--- unit -> (bool, lookup_cache) +flush_lookup_cache = function ()      if not names.lookups then names.lookups = load_lookups() end      names.lookups = { }      collectgarbage"collect"      return true, names.lookups  end ---- dbobj -> bool -> dbobj -update_names = function (fontnames, force) +--- force:      dictate rebuild from scratch +--- dry_dun:    don’t write to the db, just scan dirs + +--- dbobj? -> bool? -> bool? -> dbobj +update_names = function (fontnames, force, dry_run)      if config.luaotfload.update_live == false then          report("info", 2, "db",                 "skipping database update") @@ -1421,7 +1442,7 @@ update_names = function (fontnames, force)          fontnames = fontnames_init(false)      else          if not fontnames then -            fontnames = load_names() +            fontnames = load_names(dry_run)          end          if fontnames.version ~= names.version then              report("both", 1, "db", "No font names database or old " @@ -1433,11 +1454,11 @@ update_names = function (fontnames, force)      read_blacklist()      local scanned, new -    scanned, new = scan_texmf_fonts(fontnames, newfontnames) +    scanned, new = scan_texmf_fonts(fontnames, newfontnames, dry_run)      n_scanned = n_scanned + scanned      n_new     = n_new     + new -    scanned, new = scan_os_fonts(fontnames, newfontnames) +    scanned, new = scan_os_fonts(fontnames, newfontnames, dry_run)      n_scanned = n_scanned + scanned      n_new     = n_new     + new @@ -1510,7 +1531,130 @@ save_names = function (fontnames)      return false  end ---- is this used anywhere? +--[[doc-- + +    Below set of functions is modeled after mtx-cache. + +--doc]]-- + +--- string -> string -> string list -> string list -> string list -> unit +local print_cache = function (category, path, luanames, lucnames, rest) +    local report_indeed = function (...) +        report("info", 0, "cache", ...) +    end +    report_indeed("Luaotfload cache: %s", category) +    report_indeed("location: %s", path) +    report_indeed("[raw]       %4i", #luanames) +    report_indeed("[compiled]  %4i", #lucnames) +    report_indeed("[other]     %4i", #rest) +    report_indeed("[total]     %4i", #luanames + #lucnames + #rest) +end + +--- string -> string -> string list -> bool -> bool +local purge_from_cache = function (category, path, list, all) +    report("info", 2, "cache", "Luaotfload cache: %s %s", +        (all and "erase" or "purge"), category) +    report("info", 2, "cache", "location: %s",path) +    local n = 0 +    for i=1,#list do +        local filename = list[i] +        if string.find(filename,"luatex%-cache") then -- safeguard +            if all then +                report("info", 5, "cache", "removing %s", filename) +                os.remove(filename) +                n = n + 1 +            else +                local suffix = file.suffix(filename) +                if suffix == "lua" then +                    local checkname = file.replacesuffix( +                        filename, "lua", "luc") +                    if lfs.isfile(checkname) then +                        report("info", 5, "cache", "removing %s", filename) +                        os.remove(filename) +                        n = n + 1 +                    end +                end +            end +        end +    end +    report("info", 2, "cache", "removed lua files : %i", n) +    return true +end +--- string -> string list -> int -> string list -> string list -> string list -> +---     (string list * string list * string list * string list) +local collect_cache collect_cache = function (path, all, n, luanames, +                                              lucnames, rest) +    if not all then +        local all = dirglob(path .. "/**/*") +        local luanames, lucnames, rest = { }, { }, { } +        return collect_cache(nil, all, 1, luanames, lucnames, rest) +    end + +    local filename = all[n] +    if filename then +        local suffix = file.suffix(filename) +        if suffix == "lua" then +            luanames[#luanames+1] = filename +        elseif suffix == "luc" then +            lucnames[#lucnames+1] = filename +        else +            rest[#rest+1] = filename +        end +        return collect_cache(nil, all, n+1, luanames, lucnames, rest) +    end +    return luanames, lucnames, rest, all +end + +--- unit -> unit +local purge_cache = function ( ) +    local writable_path = caches.getwritablepath() +    local luanames, lucnames, rest = collect_cache(writable_path) +    if logs.get_loglevel() > 1 then +        print_cache("writable path", writable_path, luanames, lucnames, rest) +    end +    local success = purge_from_cache("writable path", writable_path, luanames, false) +    return success +end + +--- unit -> unit +local erase_cache = function ( ) +    local writable_path = caches.getwritablepath() +    local luanames, lucnames, rest, all = collect_cache(writable_path) +    if logs.get_loglevel() > 1 then +        print_cache("writable path", writable_path, luanames, lucnames, rest) +    end +    local success = purge_from_cache("writable path", writable_path, all, true) +    return success +end + +local separator = function ( ) +    report("info", 0, string.rep("-", 67)) +end + +--- unit -> unit +local show_cache = function ( ) +    local readable_paths = caches.getreadablepaths() +    local writable_path  = caches.getwritablepath() +    local luanames, lucnames, rest = collect_cache(writable_path) + +    separator() +    print_cache("writable path", writable_path, luanames, lucnames, rest) +    texiowrite_nl"" +    for i=1,#readable_paths do +        local readable_path = readable_paths[i] +        if readable_path ~= writable_path then +            local luanames, lucnames = collect_cache(readable_path) +            print_cache("readable path", +                readable_path,luanames,lucnames,rest) +        end +    end +    separator() +    return true +end + +--- is this used anywhere? we decided to comment it for the +--- time being. +--- https://github.com/lualatex/luaotfload/pull/61  --scan_external_dir = function (dir)  --    local old_names, new_names  --    if fonts_loaded then @@ -1524,8 +1668,11 @@ end  --    return n_scanned, n_new  --end +-----------------------------------------------------------------------  --- export functionality to the namespace “fonts.names” -names.flush_cache                 = flush_cache +----------------------------------------------------------------------- + +names.flush_lookup_cache          = flush_lookup_cache  names.save_lookups                = save_lookups  names.load                        = load_names  names.save                        = save_names @@ -1534,6 +1681,11 @@ names.update                      = update_names  names.crude_file_lookup           = crude_file_lookup  names.crude_file_lookup_verbose   = crude_file_lookup_verbose +--- font cache +names.purge_cache    = purge_cache +names.erase_cache    = erase_cache +names.show_cache     = show_cache +  --- replace the resolver from luatex-fonts  if config.luaotfload.resolver == "cached" then      report("both", 2, "cache", "caching of name: lookups active") diff --git a/luaotfload-override.lua b/luaotfload-override.lua index f143009..99a6611 100644 --- a/luaotfload-override.lua +++ b/luaotfload-override.lua @@ -30,14 +30,25 @@ We recreate the verbosity levels previously implemented in font-nms:  local loglevel = 1 --- default  local logout   = "log" +--- int -> bool  local set_loglevel = function (n)      if type(n) == "number" then          loglevel = n      end +    return true  end +logs.setloglevel    = set_loglevel  logs.set_loglevel   = set_loglevel  logs.set_log_level  = set_loglevel --- accomodating lazy typists +--- unit -> int +local get_loglevel = function ( ) +    return loglevel +end +logs.getloglevel    = get_loglevel +logs.get_loglevel   = get_loglevel +logs.get_log_level  = get_loglevel +  local set_logout = function (s)      if s == "stdout" then          logout = "term" diff --git a/luaotfload-tool.lua b/luaotfload-tool.lua index 93d6acf..882a296 100755 --- a/luaotfload-tool.lua +++ b/luaotfload-tool.lua @@ -155,7 +155,8 @@ This tool is part of the luaotfload package. Valid options are:    -u --update                  update the database    -f --force                   force re-indexing all fonts -  -c --flush-cache             empty cache of font requests +  -l --flush-lookups           empty lookup cache of font requests +  -D --dry-run                 skip loading of fonts, just scan    --find="font name"           query the database for a font name    -F --fuzzy                   look for approximate matches if --find fails @@ -171,6 +172,12 @@ The font database will be saved to     %s     %s +------------------------------------------------------------------------------- +                                   FONT CACHE + +  --cache=<directive>          operate on font cache, where <directive> is +                               “show”, “purge”, or “erase” +  ]],      mkluatexfontdb = [[ @@ -246,7 +253,8 @@ set.  --]]--  local action_sequence = { -    "loglevel", "help", "version", "flush", "generate", "list", "query" +    "loglevel", "help",     "version", "cache", +    "flush",    "generate", "list",    "query",  }  local action_pending  = table.tohash(action_sequence, false) @@ -275,7 +283,7 @@ end  actions.generate = function (job)      local fontnames, savedname -    fontnames = names.update(fontnames, job.force_reload) +    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) @@ -286,17 +294,36 @@ actions.generate = function (job)  end  actions.flush = function (job) -    local success, lookups = names.flush_cache() +    local success, lookups = names.flush_lookup_cache()      if success then          local success = names.save_lookups()          if success then -            logs.names_report("info", 2, "cache", "Cache emptied") +            logs.names_report("info", 2, "cache", "Lookup cache emptied")              return true, true          end      end      return false, false  end +local cache_directives = { +    ["purge"] = names.purge_cache, +    ["erase"] = names.erase_cache, +    ["show"]  = names.show_cache, +} + +actions.cache = function (job) +    local directive = cache_directives[job.cache] +    if not directive or type(directive) ~= "function" then +        logs.names_report("info", 2, "cache", +                          "Invalid font cache directive %s.", job.cache) +        return false, false +    end +    if directive() then +        return true, true +    end +    return false, false +end +  actions.query = function (job)      local query = job.query @@ -507,24 +534,26 @@ local process_cmdline = function ( ) -- unit -> jobspec      }      local long_options = { -        alias            = 1, -        ["flush-cache"]  = "c", -        fields           = 1, -        find             = 1, -        force            = "f", -        fuzzy            = "F", -        help             = "h", -        info             = "i", -        limit            = 1, -        list             = 1, -        log              = 1, -        quiet            = "q", -        update           = "u", -        verbose          = 1  , -        version          = "V", +        alias              = 1, +        cache              = 1, +        ["dry-run"]        = "D", +        ["flush-lookups"]  = "l", +        fields             = 1, +        find               = 1, +        force              = "f", +        fuzzy              = "F", +        help               = "h", +        info               = "i", +        limit              = 1, +        list               = 1, +        log                = 1, +        quiet              = "q", +        update             = "u", +        verbose            = 1  , +        version            = "V",      } -    local short_options = "cfFiquvVh" +    local short_options = "DfFilquvVh"      local options, _, optarg =          alt_getopt.get_ordered_opts (arg, short_options, long_options) @@ -573,13 +602,18 @@ local process_cmdline = function ( ) -- unit -> jobspec              result.show_info = true          elseif v == "alias" then              config.luaotfload.self = optarg[n] -        elseif v == "c" then +        elseif v == "l" then              action_pending["flush"] = true          elseif v == "list" then              action_pending["list"] = true              result.criterion = optarg[n]          elseif v == "fields" then              result.asked_fields = optarg[n] +        elseif v == "cache" then +            action_pending["cache"] = true +            result.cache = optarg[n] +        elseif v == "D" then +            result.dry_run = true          end      end diff --git a/luaotfload-tool.rst b/luaotfload-tool.rst index 6fc6138..9ea267b 100644 --- a/luaotfload-tool.rst +++ b/luaotfload-tool.rst @@ -17,11 +17,13 @@ SYNOPSIS  **luaotfload** [ -cfFiquvVh ] -**luaotfload** --update [ --force ] [ --quiet ] [ --verbose ] +**luaotfload** --update [ --force ] [ --quiet ] [ --verbose ] [ --dry-run ]  **luaotfload** --find=FONTNAME [ --fuzzy ] [ --info ] -**luaotfload** --flush-cache +**luaotfload** --flush-lookups + +**luaotfload** --cache=DIRECTIVE  **luaotfload** --list=CRITERION[:VALUE] [ --fields=F1,F2,...,Fn ] @@ -53,6 +55,8 @@ update mode  --update, -u            Update the database; indexes new fonts.  --force, -f             Force rebuilding of the database; re-indexes                          all fonts. +--dry-run, -D           Don’t load fonts, scan directories only. +                        (For debugging file system related issues.)  query mode  ----------------------------------------------------------------------- @@ -79,9 +83,17 @@ query mode                          printed.  The default is *fullname,version*.                          (Only meaningful with ``--list``.) -lookup cache +font and lookup caches  ----------------------------------------------------------------------- ---flush-cache           Clear font name lookup cache (experimental). +--flush-lookups         Clear font name lookup cache (experimental). + +--cache=DIRECTIVE       Cache control, where *DIRECTIVE* is one of the +                        following: + +                        1) ``purge`` -> delete Lua files from cache; +                        2) ``erase`` -> delete Lua and Luc files from +                           cache; +                        3) ``show``  -> print stats.  miscellaneous  ----------------------------------------------------------------------- diff --git a/luaotfload.dtx b/luaotfload.dtx index 75d1221..785a879 100644 --- a/luaotfload.dtx +++ b/luaotfload.dtx @@ -146,14 +146,15 @@ and the derived files  \usepackage{hologo} -\newcommand\TEX     {\TeX\xspace} -\newcommand\LUA     {Lua\xspace} -\newcommand\PDFTEX  {pdf\TeX\xspace} -\newcommand\LUATEX  {Lua\TeX\xspace} -\newcommand\XETEX   {\XeTeX\xspace} -\newcommand\LATEX   {\LaTeX\xspace} -\newcommand\CONTEXT {Con\TeX t\xspace} -\newcommand\OpenType{\identifier{Open\kern-.25ex Type}\xspace} +\newcommand\TEX      {\TeX\xspace} +\newcommand\LUA      {Lua\xspace} +\newcommand\PDFTEX   {pdf\TeX\xspace} +\newcommand\LUATEX   {Lua\TeX\xspace} +\newcommand\XETEX    {\XeTeX\xspace} +\newcommand\LATEX    {\LaTeX\xspace} +\newcommand\LUALATEX {Lua\LaTeX\xspace} +\newcommand\CONTEXT  {Con\TeX t\xspace} +\newcommand\OpenType {\identifier{Open\kern-.25ex Type}\xspace}  \def\definehighlight[#1][#2]%   {\ifcsname #1\endcsname\else @@ -258,7 +259,7 @@ and the derived files  % functionality like ligatures, old-style numbers, small capitals,  % etc., and support more complex writing systems like Arabic and  % Indic\footnote{% -%   Unfortunately, \identifier{luaotfload} doesn't support Indic +%   Unfortunately, \identifier{luaotfload} doesn‘t support many Indic  %   scripts right now.  %   Assistance in implementing the prerequisites is greatly  %   appreciated. @@ -282,6 +283,27 @@ and the derived files  % Additionally, it provides means for accessing fonts known to the operating  % system conveniently by indexing the metadata.  % +% +% \section{Thanks} +% +% \identifier{Luaotfload} is part of \LUALATEX, the community-driven +% project to provide a foundation for using the \LATEX format with the +% full capabilites of the \LUATEX engine. +% As such, the distinction between end users, contributors, and project +% maintainers is intentionally kept less strict, lest we unduly +% personalize the common effort. +% +% Nevertheless, the current maintainers would like to express their +% gratitude to Khaled Hosny, Akira Kakuto, Hironori Kitagawa and Dohyun +% Kim. +% Their contributions -- be it patches, advice, or systematic +% testing -- made the switch from version 1.x to 2.2 possible. +% Also, Hans Hagen, the author of the font loader, made porting the +% code to \LATEX a breeze due to the extra effort he invested into +% isolating it from the rest of \CONTEXT, not to mention his assistance +% in the task and willingness to respond to our suggestions. +% +%  % \section{Loading Fonts}  %  % \identifier{luaotfload} supports an extended font request syntax:  | 
