擴充識別字元 |
|
字母
的地區設定即可。通常來說,散佈非 C
地區設定的 Lua 程式時會遇到一個問題,因為這會讓檔案依賴於地區設定。不過,利用一些小技巧,就可以用與地區設定有關的函式取代各種讀取檔案的 Lua 函式。
以下範例只會讓 require
與地區設定有關,但那是最困難的情況;取代 `loadfile` 要容易得多。它假設檔案以標準 Unix「shebang」行開頭,外觀類似於
#!/bin/env LC_CTYPE=pt_BR lua
下方定義的 loader 會在 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