扩展标识符字符 |
|
alpha
。
通常,分发使用除 C
区域设置以外的区域设置的 Lua 程序存在问题,因为它会使文件依赖于区域设置。但是,通过一些技巧,可以将读取文件的各种 Lua 函数替换为区域设置感知的函数。
以下示例仅使 require
成为区域设置感知的,但这是最困难的情况;替换 loadfile
要容易得多。它假设文件以标准的 Unix "shebang" 行开头,类似于
#!/bin/env LC_CTYPE=pt_BR lua
下面定义的加载器检查 shebang 行中任何类似于 LC_CTYPE 定义的内容,并在解析文件时相应地设置区域设置。这还没有经过充分测试,但似乎很有用,值得记录。
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