diff options
-rw-r--r-- | luaotfload-database.lua | 144 |
1 files changed, 98 insertions, 46 deletions
diff --git a/luaotfload-database.lua b/luaotfload-database.lua index 7baa92a..9eb5b1f 100644 --- a/luaotfload-database.lua +++ b/luaotfload-database.lua @@ -33,12 +33,11 @@ local iolines = io.lines local ioopen = io.open local kpseexpand_path = kpse.expand_path local kpseexpand_var = kpse.expand_var -local kpselookup = kpse.lookup local kpsefind_file = kpse.find_file +local kpselookup = kpse.lookup local kpsereadable_file = kpse.readable_file -local lfsisdir = lfs.isdir -local lfsisfile = lfs.isfile local lfsattributes = lfs.attributes +local lfsdir = lfs.dir local mathabs = math.abs local mathmin = math.min local stringfind = string.find @@ -49,9 +48,7 @@ local stringlower = string.lower local stringsub = string.sub local stringupper = string.upper local tableconcat = table.concat -local tablecopy = table.copy local tablesort = table.sort -local tabletofile = table.tofile local texiowrite_nl = texio.write_nl local utf8gsub = unicode.utf8.gsub local utf8lower = unicode.utf8.lower @@ -60,18 +57,22 @@ local utf8lower = unicode.utf8.lower local dirglob = dir.glob local dirmkdirs = dir.mkdirs local filebasename = file.basename -local filenameonly = file.nameonly -local filedirname = file.dirname local filecollapsepath = file.collapsepath or file.collapse_path +local filedirname = file.dirname local fileextname = file.extname local fileiswritable = file.iswritable local filejoin = file.join +local filenameonly = file.nameonly local filereplacesuffix = file.replacesuffix local filesplitpath = file.splitpath or file.split_path +local lfsisdir = lfs.isdir +local lfsisfile = lfs.isfile local stringis_empty = string.is_empty local stringsplit = string.split local stringstrip = string.strip local tableappend = table.append +local tablecopy = table.copy +local tabletofile = table.tofile local tabletohash = table.tohash --- the font loader namespace is “fonts”, same as in Context @@ -1206,8 +1207,8 @@ do return path end --[[doc-- - Cygwin used to be treated different from windows and dos. This - special treatment was removed with a patch submitted by Ken Brown. + The special treatment for cygwin was removed with a patch submitted + by Ken Brown. Reference: http://cygwin.com/ml/cygwin/2013-05/msg00006.html --doc]]-- @@ -1301,12 +1302,12 @@ end --- unit -> unit read_blacklist = function () local files = { - kpselookup("luaotfload-blacklist.cnf", {all=true, format="tex"}) + kpselookup ("luaotfload-blacklist.cnf", + {all=true, format="tex"}) } local blacklist = { } local whitelist = { } - --- TODO lpegify if files and type(files) == "table" then for _,v in next, files do for line in iolines(v) do @@ -1331,10 +1332,59 @@ read_blacklist = function () names.blacklist = create_blacklist(blacklist, whitelist) end -local font_extensions = { "otf", "ttf", "ttc", "dfont" } -local font_extensions_set = {} -for key, value in next, font_extensions do - font_extensions_set[value] = true +local font_extensions = { "otf", "ttf", "ttc", "dfont" } +local font_extensions_set = tabletohash (font_extensions) +local p_font_extensions +do + local extns + --tablesort (font_extensions) --- safeguard + for i=#font_extensions, 1, -1 do + local e = font_extensions[i] + if not extns then + extns = P(e) + else + extns = extns + P(e) + end + end + extns = extns * P(-1) + p_font_extensions = (1 - extns)^1 * extns +end + +local process_dir_tree +process_dir_tree = function (acc, dirs) + if not next (dirs) then --- done + return acc + end + + local dir = dirs[#dirs] + dirs[#dirs] = nil + + local newdirs, newfiles = { }, { } + local blacklist = names.blacklist + for ent in lfsdir (dir) do + --- filter right away + if ent ~= "." and ent ~= ".." and not blacklist[ent] then + local fullpath = dir .. "/" .. ent + if lfsisdir (fullpath) + and not lpegmatch (p_blacklist, fullpath) + then + newdirs[#newdirs+1] = fullpath + elseif lfsisfile (fullpath) then + if lpegmatch (p_font_extensions, stringlower(ent)) then + newfiles[#newfiles+1] = fullpath + end + end + end + end + return process_dir_tree (tableappend (acc, newfiles), + tableappend (dirs, newdirs)) +end + +--- string -> string list +local find_font_files = function (root) + if lfsisdir (root) then + return process_dir_tree ({}, { root }) + end end --[[doc-- @@ -1350,42 +1400,45 @@ end --doc]]-- --- string -> dbobj -> dbobj -> bool -> bool -> (int * int) -local scan_dir = function (dirname, fontnames, newfontnames, dry_run, texmf) - if lpegmatch(p_blacklist, dirname) then +local scan_dir = function (dirname, fontnames, newfontnames, + dry_run, texmf) + if lpegmatch (p_blacklist, dirname) then + report ("both", 3, "db", + "Skipping blacklisted directory %s", dirname) --- ignore return 0, 0 end - - local n_scanned, n_new = 0, 0 --- total of fonts collected - report("both", 3, "db", "Scanning directory %s", dirname) - for _,i in next, font_extensions do - for _,ext in next, { i, stringupper(i) } do - local escapeddir = preescape_path (dirname) - local found = dirglob (stringformat("%s/**.%s$", - escapeddir, ext)) - local n_found = #found - --- note that glob fails silently on broken symlinks, which - --- happens sometimes in TeX Live. - report("both", 4, "db", "%s '%s' fonts found", n_found, ext) - n_scanned = n_scanned + n_found - for j=1, n_found do - local fullname = found[j] - fullname = path_normalize(fullname) - 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, texmf) - if new == true then - n_new = n_new + 1 - end - end + local found = find_font_files (dirname) + if not found then + report ("both", 3, "db", + "No such directory: “%s”; skipping.", dirname) + return 0, 0 + end + report ("both", 3, "db", "Scanning directory %s", dirname) + + local n_new = 0 --- total of fonts collected + local n_found = #found + report ("both", 4, "db", "%d font files detected", n_found) + for j=1, n_found do + local fullname = found[j] + fullname = path_normalize(fullname) + 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, texmf) + if new == true then + n_new = n_new + 1 end end end - report("both", 4, "db", "%d fonts found in '%s'", n_scanned, dirname) - return n_scanned, n_new + + report("both", 4, "db", "%d fonts found in '%s'", n_found, dirname) + return n_found, n_new end --- dbobj -> dbobj -> bool? -> (int * int) @@ -1404,7 +1457,6 @@ local scan_texmf_fonts = function (fontnames, newfontnames, dry_run) fontdirs = fontdirs .. stringgsub(kpseexpand_path("$TTFONTS"), "^%.", "") 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, dry_run, true) n_scanned = n_scanned + found n_new = n_new + new |