Модуль:Песочница/Pok: различия между версиями
Pok (обсуждение | вклад) Нет описания правки |
Pok (обсуждение | вклад) Нет описания правки |
||
| Строка 5: | Строка 5: | ||
local function normalize_value(v) | local function normalize_value(v) | ||
if type(v) == "string" then | if type(v) == "string" then | ||
if v == "" then return nil end | |||
return v | return v | ||
elseif type(v) == "table" then | elseif type(v) == "table" then | ||
if v[1] and v[1] ~= "" then return tostring(v[1]) end | |||
if v[1] and v[1] ~= "" then return v[1] end | |||
for _, val in pairs(v) do | for _, val in pairs(v) do | ||
if type(val) == "string" and val ~= "" then return val end | if type(val) == "string" and val ~= "" then return val end | ||
if type(val) ~= "nil" then return tostring(val) end | |||
end | end | ||
return nil | return nil | ||
| Строка 17: | Строка 18: | ||
end | end | ||
return nil | return nil | ||
end | |||
local function serial(obj, depth, seen) | |||
depth = depth or 0 | |||
seen = seen or {} | |||
if type(obj) ~= "table" then return tostring(obj) end | |||
if seen[obj] then return "<cycle>" end | |||
if depth > 5 then return "{...}" end | |||
seen[obj] = true | |||
local parts = {} | |||
for k, v in pairs(obj) do | |||
local ks = tostring(k) | |||
local vs = serial(v, depth + 1, seen) | |||
table.insert(parts, ks .. "=" .. vs) | |||
end | |||
return "{" .. table.concat(parts, ", ") .. "}" | |||
end | end | ||
function p.set_path(frame) | function p.set_path(frame) | ||
local arg | local arg | ||
-- support: #invoke:GetField|set_path|VALUE (frame.args[1]) | |||
if type(frame) == "table" and frame.args then | |||
if frame.args[1] then arg = frame.args[1] end | |||
if (not arg or arg == "") then | |||
if (not arg or arg == "") then | local ok, a = pcall(function() return frame:getArgument(1) end) | ||
if ok and a and a ~= "" then arg = a end | |||
arg = nil | end | ||
if (not arg or arg == "") then | |||
local ok, a = pcall(function() return frame:getArgument("path") end) | |||
if ok and a and a ~= "" then arg = a end | |||
end | |||
if (not arg or arg == "") then | |||
local ok, a = pcall(function() return frame:getArgument("GetFieldPath") end) | |||
if ok and a and a ~= "" then arg = a end | |||
end | |||
elseif type(frame) == "string" then | |||
arg = frame | |||
elseif frame ~= nil then | |||
-- maybe called without frame but with second arg: p.set_path(nil, "X") | |||
if arg == nil and type(frame) ~= "table" then | |||
arg = tostring(frame) | |||
end | |||
end | end | ||
local val = normalize_value(arg) | local val = normalize_value(arg) | ||
if val and val ~= "" then | if val and val ~= "" then | ||
CURRENT_PROJECT = val | CURRENT_PROJECT = val | ||
return "" | return "OK:" .. tostring(CURRENT_PROJECT) | ||
end | |||
-- nothing set — return diagnostic snapshot to help debug | |||
local info = "NOT_SET" | |||
if type(frame) == "table" then | |||
local a = frame.args and serial(frame.args) or "(no frame.args)" | |||
info = info .. "; frame.args=" .. a | |||
else | |||
info = info .. "; frame_type=" .. type(frame) .. "; frame_val=" .. tostring(frame) | |||
end | end | ||
return | return info | ||
end | end | ||
function p._debug_get_cached(frame) | function p._debug_get_cached() | ||
local | if CURRENT_PROJECT == nil then return "(nil)" end | ||
if not | return tostring(CURRENT_PROJECT) | ||
-- | end | ||
if | |||
function p.inspect(frame) | |||
local out = {} | |||
local f = frame or mw.getCurrentFrame() | |||
if not f then return "NO_FRAME_AVAILABLE" end | |||
local function push(s) table.insert(out, s) end | |||
local depth = 0 | |||
while f and depth < 20 do | |||
local header = string.format("FRAME depth=%d", depth) | |||
push(header) | |||
-- try to read positional args table if present | |||
if f.args then | |||
push(" .args = " .. serial(f.args)) | |||
else | |||
push(" .args = (no args table)") | |||
end | end | ||
-- try reading some common named args via getArgument (safe) | |||
local ok1, a1 = pcall(function() return f:getArgument("1") end) | |||
local okn, an = pcall(function() return f:getArgument("name") end) | |||
local okN, aN = pcall(function() return f:getArgument("Название") end) | |||
push(" getArgument('1') = " .. (ok1 and tostring(a1) or "(err)")) | |||
push(" getArgument('name') = " .. (okn and tostring(an) or "(err)")) | |||
push(" getArgument('Название') = " .. (okN and tostring(aN) or "(err)")) | |||
-- also dump callable fields existence | |||
push(" has:getParent = " .. tostring(type(f.getParent) == "function")) | |||
push(" has:callParserFunction = " .. tostring(type(f.callParserFunction) == "function")) | |||
f = (type(f.getParent) == "function") and f:getParent() or nil | |||
depth = depth + 1 | |||
end | end | ||
push("CURRENT_PROJECT = " .. tostring(CURRENT_PROJECT)) | |||
return table.concat(out, "\n") | |||
end | end | ||
| Строка 64: | Строка 126: | ||
local project = pp and normalize_value(pp) or CURRENT_PROJECT | local project = pp and normalize_value(pp) or CURRENT_PROJECT | ||
if (not project or project == "") and fp then | if (not project or project == "") and fp then | ||
local ok, res = pcall(function() return fp:callParserFunction{ name = "var", args = { "GetFieldPath" } } end) | local ok, res = pcall(function() return fp:callParserFunction{ name = "var", args = { "GetFieldPath" } } end) | ||
if ok and res and res ~= "" then project = res end | if ok and res and res ~= "" then project = res end | ||