扩展标识符字符

lua-users home
wiki

在讨论了 '?' 和 '!' 作为 Lua 标识符中的合法字符的可能性之后,我意识到可以通过更改区域设置来实现,因为 Lua 是区域设置感知的。只需要创建一个区域设置,其 LC_CTYPE 将 '?' 和 '!' 识别为 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

最近更改 · 偏好设置
编辑 · 历史记录
最后编辑于 2007 年 7 月 13 日上午 6:10 GMT (差异)