Skip to content

Commit

Permalink
luaish included as soar/srlua test
Browse files Browse the repository at this point in the history
  • Loading branch information
stevedonovan committed May 31, 2012
1 parent 4544f47 commit f0bbe0d
Show file tree
Hide file tree
Showing 4 changed files with 960 additions and 0 deletions.
173 changes: 173 additions & 0 deletions luaish/config.lua
@@ -0,0 +1,173 @@
--- Reads configuration files into a Lua table.
-- Understands INI files, classic Unix config files, and simple
-- delimited columns of values.
--
-- # test.config
-- # Read timeout in seconds
-- read.timeout=10
-- # Write timeout in seconds
-- write.timeout=5
-- #acceptable ports
-- ports = 1002,1003,1004
--
-- -- readconfig.lua
-- require 'pl'
-- local t = config.read 'test.config'
-- print(pretty.write(t))
--
-- ### output #####
-- {
-- ports = {
-- 1002,
-- 1003,
-- 1004
-- },
-- write_timeout = 5,
-- read_timeout = 10
-- }
--
-- See the Guide for further @{06-data.md.Reading_Configuration_Files|discussion}
--
-- Dependencies: none
-- @module pl.config

local type,tonumber,ipairs,io, table = _G.type,_G.tonumber,_G.ipairs,_G.io,_G.table

local function split(s,re)
local res = {}
local t_insert = table.insert
re = '[^'..re..']+'
for k in s:gmatch(re) do t_insert(res,k) end
return res
end

local function strip(s)
return s:gsub('^%s+',''):gsub('%s+$','')
end

local function strip_quotes (s)
return s:gsub("['\"](.*)['\"]",'%1')
end

local config = {}

--- like io.lines(), but allows for lines to be continued with '\'.
-- @param file a file-like object (anything where read() returns the next line) or a filename.
-- Defaults to stardard input.
-- @return an iterator over the lines, or nil
-- @return error 'not a file-like object' or 'file is nil'
function config.lines(file)
local f,openf,err
local line = ''
if type(file) == 'string' then
f,err = io.open(file,'r')
if not f then return nil,err end
openf = true
else
f = file or io.stdin
if not file.read then return nil, 'not a file-like object' end
end
if not f then return nil, 'file is nil' end
return function()
local l = f:read()
while l do
-- does the line end with '\'?
local i = l:find '\\%s*$'
if i then -- if so,
line = line..l:sub(1,i-1)
elseif line == '' then
return l
else
l = line..l
line = ''
return l
end
l = f:read()
end
if openf then f:close() end
end
end

--- read a configuration file into a table
-- @param file either a file-like object or a string, which must be a filename
-- @param cnfg a configuration table that may contain these fields:
-- <ul>
-- <li> variablilize make names into valid Lua identifiers (default true)</li>
-- <li> convert_numbers try to convert values into numbers (default true)</li>
-- <li> trim_space ensure that there is no starting or trailing whitespace with values (default true)</li>
-- <li> trim_quotes remove quotes from strings (default false)</li>
-- <li> list_delim delimiter to use when separating columns (default ',')</li>
-- </ul>
-- @return a table containing items, or nil
-- @return error message (same as @{config.lines}
function config.read(file,cnfg)
local f,openf,err
cnfg = cnfg or {}
local function check_cnfg (var,def)
local val = cnfg[var]
if val == nil then return def else return val end
end
local t = {}
local top_t = t
local variablilize = check_cnfg ('variabilize',true)
local list_delim = check_cnfg('list_delim',',')
local convert_numbers = check_cnfg('convert_numbers',true)
local trim_space = check_cnfg('trim_space',true)
local trim_quotes = check_cnfg('trim_quotes',false)
local ignore_assign = check_cnfg('ignore_assign',false)
local keysep = check_cnfg('keysep','=')
local keypat = keysep == ' ' and '%s+' or '%s*'..keysep..'%s*'

local function process_name(key)
if variablilize then
key = key:gsub('[^%w]','_')
end
return key
end

local function process_value(value)
if list_delim and value:find(list_delim) then
value = split(value,list_delim)
for i,v in ipairs(value) do
value[i] = process_value(v)
end
elseif convert_numbers and value:find('^[%d%+%-]') then
local val = tonumber(value)
if val then value = val end
end
if type(value) == 'string' then
if trim_space then value = strip(value) end
if trim_quotes then value = strip_quotes(value) end
end
return value
end

local iter,err = config.lines(file)
if not iter then return nil,err end
for line in iter do
-- strips comments
local ci = line:find('%s*[#;]')
if ci then line = line:sub(1,ci-1) end
-- and ignore blank lines
if line:find('^%s*$') then
elseif line:find('^%[') then -- section!
local section = process_name(line:match('%[([^%]]+)%]'))
t = top_t
t[section] = {}
t = t[section]
else
line = line:gsub('^%s*','')
local i1,i2 = line:find(keypat)
if i1 and not ignore_assign then -- key,value assignment
local key = process_name(line:sub(1,i1-1))
local value = process_value(line:sub(i2+1))
t[key] = value
else -- a plain list of values...
t[#t+1] = process_value(line)
end
end
end
return top_t
end

return config

0 comments on commit f0bbe0d

Please sign in to comment.