Extending Identifier Characters |
|
alpha
.
In general, there is a problem with distributing Lua programs which use a locale other than the C
locale, because it makes the files locale-dependent. However, with a bit of hackery, it's possible to replace the various Lua functions which read files with functions which are locale-aware.
The following example only causes require
to be locale aware, but that's the most difficult case; replace loadfile
is quite a bit easier. It assumes that files start with a standard Unix "shebang" line which looks something like:
#!/bin/env LC_CTYPE=pt_BR lua
The loader defined below checks for anything that looks like a LC_CTYPE definition in the shebang line, and sets the locale accordingly while parsing the file. This has not been tested very much, but it seemed useful enough to record.
local pkg = require"package" local function findfile(pname, pathtype) local path = pkg[pathtype] local fname = pname:gsub("%.", "/") local errs = {} for seg in path:gmatch"[^;]+" do local fname = seg:gsub("%?", fname) local file, err = io.open(fname) if file then return file, fname else errs[#errs+1] = ("\n\tno file '%s'"):format(fname) end end return nil, table.concat(errs) end local yield = coroutine.yield local function Reader(file) return coroutine.wrap(function() local data = file:read(1) if data ~= '#' then yield(data) yield(file:read"*a") else file:seek("set") local lines = file:lines() local shebang = lines() local ctype = shebang:match"LC_CTYPE=(%S+)" if ctype then os.setlocale(ctype, "ctype") end yield"\n" for l in lines do yield(l.."\n") end end end) end local function myloader(pname) local file, fname = findfile(pname, "path") if file then local locale = os.setlocale(nil, "ctype") local chunk, err = load(Reader(file), "@"..fname) os.setlocale(locale, "ctype") file:close() if chunk then return chunk else error(("error loading '%s' from '%s':\n\t%s"):format(pname, fname, err), 0) end else return fname end end pkg.loaders[2] = myloader