Модуль:Песочница/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
        -- если таблица, попробуем взять первый элемент либо первый named value
         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
     if frame then
     -- support: #invoke:GetField|set_path|VALUE  (frame.args[1])
        -- стандартный путь: позиционный первый аргумент
    if type(frame) == "table" and frame.args then
        if frame.args and frame.args[1] then arg = frame.args[1] end
        if frame.args[1] then arg = frame.args[1] end
        -- если не получилось — пробуем getArgument
         if (not arg or arg == "") then
         if (not arg or arg == "") then arg = frame:getArgument(1) or frame:getArgument("path") or frame:getArgument("GetFieldPath") end
            local ok, a = pcall(function() return frame:getArgument(1) end)
     else
            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 v = CURRENT_PROJECT
    if CURRENT_PROJECT == nil then return "(nil)" end
     if not v then
    return tostring(CURRENT_PROJECT)
         -- попробуем получить через frame (на случай #vardefine/var)
end
         if frame and frame.callParserFunction then
 
             local ok, res = pcall(function() return frame:callParserFunction{ name = "var", args = { "GetFieldPath" } } end)
function p.inspect(frame)
             if ok and res and res ~= "" then v = res end
     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
     if type(v) == "table" then
     push("CURRENT_PROJECT = " .. tostring(CURRENT_PROJECT))
        local parts = {}
    return table.concat(out, "\n")
        for k, val in pairs(v) do
            table.insert(parts, tostring(k) .. "=" .. tostring(val))
        end
        return "table: {" .. table.concat(parts, ", ") .. "}"
    end
    return tostring(v or "(nil)")
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
        -- попытка через #var
         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