Difference between revisions of "Module:Calculated table"
m (Fix bug) |
(Add option to format cells) |
||
Line 53: | Line 53: | ||
i = i + 2 | i = i + 2 | ||
end | end | ||
− | return p._table(frame.args[1], frame.args[2], {style = frame.args.style}, unpack(frame.args, 3)) | + | return p._table(frame.args[1], frame.args[2], {style = frame.args.style, format = frame.args.format}, unpack(frame.args, 3)) |
end | end | ||
Line 82: | Line 82: | ||
end | end | ||
table.insert(result, heading) | table.insert(result, heading) | ||
+ | end | ||
+ | local format = function(s) return s end | ||
+ | if type(opts.format) == "function" then | ||
+ | format = opts.format | ||
+ | elseif type(opts.format) == "string" then | ||
+ | local formatstr = opts.format | ||
+ | format = function(s) return formatstr:format(s) end | ||
end | end | ||
for j, row in ipairs(calculations) do | for j, row in ipairs(calculations) do | ||
Line 88: | Line 95: | ||
for i, col in ipairs(row) do | for i, col in ipairs(row) do | ||
table.insert(result, " || ") | table.insert(result, " || ") | ||
− | table.insert(result, col) | + | table.insert(result, format(col)) |
end | end | ||
end | end |
Revision as of 03:50, 1 July 2015
Documentation for this module may be created at Module:Calculated table/doc
local p = {} -- This is a simple Reverse Polish Notation evaluator. -- It's not infix because edsrzf is lazy and didn't want to write an infix -- parser. -- If you'd like to write one and replace this one, please feel free. local function evaluate(expr, env) local stack = {} local i = 1 while i <= #expr do local c = expr:sub(i, i) if c == '*' then local x = table.remove(stack) local y = table.remove(stack) table.insert(stack, x*y) elseif c == '/' then local x = table.remove(stack) local y = table.remove(stack) table.insert(stack, x/y) elseif c == '-' then local x = table.remove(stack) local y = table.remove(stack) table.insert(stack, x-y) elseif c == '+' then local x = table.remove(stack) local y = table.remove(stack) table.insert(stack, x+y) elseif tonumber(c) then local match = expr:match("^%d+", i) i = i + #match - 1 -- We'll add 1 more below table.insert(stack, tonumber(match)) elseif c:match("%a") then local match = expr:match("^%a+", i) i = i + #match - 1 -- We'll add 1 more below table.insert(stack, env[match]) end i = i + 1 end return table.remove(stack) end -- eval_func returns a function that evaluates the expression with a given environment. local function eval_func(expr) return function(env) return evaluate(expr, env) end end function p.table(frame) local i = 4 while i <= #frame.args do frame.args[i] = eval_func(frame.args[i]) i = i + 2 end return p._table(frame.args[1], frame.args[2], {style = frame.args.style, format = frame.args.format}, unpack(frame.args, 3)) end function p._table(base_heading, rows, opts, ...) local headings = {base_heading} local calculations = {} for j = 1, rows do calculations[j] = {} end local i = 1 while i < arg.n do table.insert(headings, arg[i]) local formula = arg[i+1] for j, row in ipairs(calculations) do row[(i+1)/2] = formula({x = j}) end i = i + 2 end local result = {"{| "} local style = opts.style if style then table.insert(result, style) end table.insert(result, "\n|-\n| ") for i, heading in ipairs(headings) do if i > 1 then table.insert(result, " || ") end table.insert(result, heading) end local format = function(s) return s end if type(opts.format) == "function" then format = opts.format elseif type(opts.format) == "string" then local formatstr = opts.format format = function(s) return formatstr:format(s) end end for j, row in ipairs(calculations) do table.insert(result, "\n|-\n| ") table.insert(result, j) for i, col in ipairs(row) do table.insert(result, " || ") table.insert(result, format(col)) end end table.insert(result, "\n|}") return table.concat(result) end return p