Memperlihatkan isi tabel LUA.


--[===[

MODULE "LISTTABLE"

"eo.wiktionary.org/wiki/Modulo:listtable" <!--2024-Oct-18-->

Purpose: show all content of a table, even a metaized one,
         even recursively up to 7 levels

Required submodules / Bezonataj submoduloj /
Submodul yang diperlukan / Behoevda submoduler:
* none

Incoming: * when called from a template or from a
            wiki page (directly or via template):
            * name of data module to be imported via "loadData",
              with namespace prefix
          * when called from a module:
            * table to get analyzed packed in an extra table on key "xx"

Example of calling from wiki page:

  {{#invoke:listtable|ek|Module:loaddata-tblalfabetoj}}

Example of calling from module:

  qlisttable = require('Module:listtable')
  strmyreport = qlisttable.ek { ['xx'] = tabdubious }

]===]

local exporttable = {}

------------------------------------------------------------------------

---- HIGH LEVEL STRING FUNCTIONS [I] ----

------------------------------------------------------------------------

-- Local function LFIFONTSIZETIT

-- called from "lfhtablstlev" (level 0...13) and
-- from "lfhtablist" (special level -1)

local function lfifontsizetit (strtexto, numlevel)
  local strsize = '200' -- preASSume -- for special level -1
  if (numlevel==0) then
    strsize = '150'
  end--if
  if (numlevel==1) then
    strsize = '130'
  end--if
  if (numlevel==2) then
    strsize = '110'
  end--if
  if (numlevel>2) then
    strsize = '90'
  end--if
  strtexto = '<b><span style="font-size:' .. strsize .. '%;">' .. strtexto .. '</span></b>'
  return strtexto
end--function lfifontsizetit

------------------------------------------------------------------------

local function lfifont90nbsize (strtexxto)
  strtexxto = '<span style="font-size:90%;">' .. strtexxto .. '</span>'
  return strtexxto
end--function lfifont90nbsize

------------------------------------------------------------------------

local function lfileftlevel (numleewel)
  local strlfandstars = string.char(10)
  while true do
    strlfandstars = strlfandstars .. '*' -- ONE star at level ZERO needed too
    if (numleewel==0) then
      break
    end--if
    numleewel = numleewel - 1
  end--while
  return strlfandstars
end--function lfileftlevel

------------------------------------------------------------------------

local function lfimini3ksani (strdangstring, booutf8keep)

-- no values $C0, $C1, $F5...$FF in a UTF8 stream

  local strnowsafe = ''

  local num39len = 0
  local num39index = 1 -- ONE-based
  local numsigno = 0
  local numprevious = 0

  local boohtmlenc = false
  local boovisienc = false
  local bookeepuni = false

  if (type(strdangstring)~='string') then
    strdangstring = '??'
  end--if
  booutf8keep = (booutf8keep==true)

  num39len = string.len (strdangstring)
  while true do
      if (num39index>num39len) then -- ONE-based
        break
      end--if
      numsigno = string.byte (strdangstring,num39index,num39index)
      boohtmlenc = false -- reset on
      boovisienc = false -- every iteration
      bookeepuni = (booutf8keep and (numsigno>=128) and (numsigno<=245) and (numsigno~=192) and (numsigno~=193))
      if (not bookeepuni) then
        boohtmlenc = ((numsigno<=42) or (numsigno==58) or (numsigno==60) or (numsigno==62) or (numsigno==91) or (numsigno==93) or (numsigno>=123))
        boovisienc = ((numsigno<=31) or (numsigno>=127)) -- overrides "boohtmlenc"
      end--if
      if ((numsigno==32) and ((numprevious==32) or (num39index==1) or (num39index==num39len))) then
        boovisienc = true -- overrides "boohtmlenc"
      end--if
      if (boovisienc) then
        strnowsafe = strnowsafe .. '{' .. tostring (numsigno) .. '}'
      else
        if (boohtmlenc) then
          strnowsafe = strnowsafe .. '&#' .. tostring (numsigno) .. ';'
        else
          strnowsafe = strnowsafe .. string.char (numsigno)
        end--if
      end--if
      if ((num39len>3000) and (num39index==1000)) then
        num39index = num39len - 1000
        strnowsafe = strnowsafe .. '" ... "'
      else
        num39index = num39index + 1 -- ONE-based
      end--if
      numprevious = numsigno
  end--while

  return strnowsafe

end--function lfimini3ksani

------------------------------------------------------------------------

---- HIGH LEVEL FUNCTIONS [H] ----

------------------------------------------------------------------------

-- Local function LFHREPORTVARI

-- Input  : * booutfg8keep -- true to keep UTF8 intact, else dec-encoded

-- Called from 3 places in "lfhtablstlev".

local function lfhreportvari (varanytype, booutfg8keep)

  local strtypeofit = ''
  local strdescription = ''

  strtypeofit = type(varanytype)
  strdescription = 'type ' .. strtypeofit
  if ((strtypeofit=='boolean') or (strtypeofit=='number')) then
    strdescription = strdescription .. ' and value ' .. tostring (varanytype)
  end--if
  if (strtypeofit=='string') then
    strdescription = strdescription .. ' and value "' .. lfimini3ksani(varanytype,booutfg8keep) .. '"'
  end--if (strtypeofit=='string') then

  return strdescription

end--function lfhreportvari

------------------------------------------------------------------------

-- Local function LFHALLTOSTRING

-- Called only from "lfhcompareidiotsafe".

local function lfhalltostring (varwhatever)
  local strtypeofstuff = ''
  strtypeofstuff = type(varwhatever)
  if (strtypeofstuff=='number') then
    strtypeofstuff = '0'
  end--if
  if (strtypeofstuff=='string') then
    strtypeofstuff = '1'
  end--if
  strtypeofstuff = strtypeofstuff .. tostring(varwhatever)
  return strtypeofstuff
end--function lfhalltostring

------------------------------------------------------------------------

-- Local function LFHCOMPAREIDIOTSAFE

-- The sortorder is:
-- * number
-- * string
-- * everything else (boolean -> function -> table)

-- For example 5 will be less than "4".

-- Only for one of two uses of "table.sort" in "lfhtableanal".

local function lfhcompareidiotsafe (varaa, varbb)
  local booaaisless = false
  booaaisless = (lfhalltostring(varaa)<lfhalltostring(varbb))
  return booaaisless
end--function lfhcompareidiotsafe

------------------------------------------------------------------------

-- Local function LFHTABLEANAL

-- we must use "in pairs" since the incoming table could be metaized

-- numeric keys out of range or non-integer as well as string keys out
-- of range land among other keys

local function lfhtableanal (tabnko)

  local taballkeystring = {} -- ONE-based
  local taballcetvalues = {} -- ONE-based

  local numkatrol = 0
  local numkeynumber = 0 -- count of numeric keys only integer and in range
  local numkeystring = 0 -- count of string keys only in range
  local numkeycetera = 0 -- count of other keys
  local numkey77min = 999999
  local numkey77max = -999999

  local boodone = false

  for k9k,v9v in pairs(tabnko) do
    boodone = false
    if (type(k9k)=='number') then
      if ((k9k==math.floor(k9k)) and (k9k>=-999000) and (k9k<=999000)) then -- protect against insanity
        numkey77min = math.min (numkey77min,k9k)
        numkey77max = math.max (numkey77max,k9k)
        numkeynumber = numkeynumber + 1
        boodone = true
      end--if
    end--if
    if (type(k9k)=='string') then
      numkatrol = string.len(k9k)
      if ((numkatrol~=0) and (numkatrol<=50)) then -- protect against insanity
        taballkeystring [numkeystring+1] = k9k -- ONE-based for "table.sort"
        numkeystring = numkeystring + 1
        boodone = true
      end--if
    end--if
    if (not boodone) then
      taballcetvalues [numkeycetera+1] = v9v -- ONE-based for "table.sort"
      numkeycetera = numkeycetera + 1 -- here we directly store the value !!!
    end--if
  end--for

  table.sort(taballkeystring) -- all are strings -- otherwise the sortorder is messy
  table.sort(taballcetvalues,lfhcompareidiotsafe) -- various types -- otherwise the sortorder is messy

  return numkeynumber, numkey77min, numkey77max, numkeystring, numkeycetera, taballkeystring, taballcetvalues

end--function lfhtableanal

------------------------------------------------------------------------

local function lfhtablstlev (tabobscure, numincomlevel, booutf8preserve)

-- numeric keys -> string keys -> other keys

  local varta3mp = 0

  local tablisto = {}
  local tabvaluo = {}

  local strte7mp = ''
  local strgg = ''
  local strkeystring = ''
  local strli7mit = ' <b>limit of 7 nesting levels reached, deeper content is written in the stars</b>' -- begins with space

  local numtitlevel = 0
  local numindax = 0
  local numjumlahnum = 0
  local numqqmin = 0
  local numqqmax = 0
  local numjumlahstr = 0
  local numjumlahcet = 0

  numtitlevel = numincomlevel * 2 -- consuming 2 star levels per table level

  numjumlahnum, numqqmin, numqqmax, numjumlahstr, numjumlahcet, tablisto, tabvaluo = lfhtableanal(tabobscure)

  strte7mp = 'The table (level ' .. tostring(numincomlevel) .. ')'
  if ((numjumlahnum==0) and (numjumlahstr==0) and (numjumlahcet==0)) then
    strte7mp = strte7mp .. ' is empty'
  else
    strte7mp = strte7mp .. ' contains '
    if (numjumlahnum==0) then
      strte7mp = strte7mp .. 'NO numeric keys'
    end--if
    if (numjumlahnum==1) then
      strte7mp = strte7mp .. 'a single numeric key equal ' .. tostring (numqqmin)
    end--if
    if (numjumlahnum>=2) then
      strte7mp = strte7mp .. tostring (numjumlahnum) .. ' numeric keys ranging from ' .. tostring (numqqmin) .. ' to ' .. tostring (numqqmax)
    end--if
    strte7mp = strte7mp .. ' and ' .. tostring (numjumlahstr) .. ' string keys and ' .. tostring (numjumlahcet) .. ' other keys'
  end--if
  strgg = lfileftlevel(numtitlevel) .. lfifontsizetit((strte7mp .. '.'),numtitlevel)

  if (numjumlahnum~=0) then
    strgg = strgg .. lfileftlevel(numtitlevel) .. lfifontsizetit('Numeric keys:',numtitlevel)
    numindax = numqqmin
    while true do
      if (numindax>numqqmax) then
        break
      end--if
      varta3mp = tabobscure[numindax]
      if (varta3mp~=nil) then -- holes well possible
        strte7mp = tostring (numindax) .. ' -> ' .. lfhreportvari(varta3mp,booutf8preserve) -- no quot for key
        strgg = strgg .. lfileftlevel(numtitlevel+1) .. lfifont90nbsize(strte7mp)
        if (type(varta3mp)=='table') then
          if (numincomlevel<=6) then
            strgg = strgg .. lfhtablstlev (varta3mp,(numincomlevel+1),booutf8preserve) -- REKURSI
          else
            strgg = strgg .. strli7mit
          end--if
        end--if
      end--if (varta3mp~=nil) then
      numindax = numindax + 1
    end--while
  end--if (numjumlahnum~=0) then

  if (numjumlahstr~=0) then
    strgg = strgg .. lfileftlevel(numtitlevel) .. lfifontsizetit('String keys:',numtitlevel)
    numindax = 0
    while true do
      if (numindax>=numjumlahstr) then -- index is ZERO-based
        break
      end--if
      strkeystring = tablisto [numindax+1] -- ONE-based for "table.sort"
      if (type(strkeystring)=='string') then -- always true ??
        varta3mp = tabobscure[strkeystring]
        if (varta3mp~=nil) then -- always true ??
          strte7mp = '"' .. lfimini3ksani(strkeystring,booutf8preserve) .. '" -> ' .. lfhreportvari(varta3mp,booutf8preserve)
          strgg = strgg .. lfileftlevel(numtitlevel+1) .. lfifont90nbsize(strte7mp)
          if (type(varta3mp)=='table') then
            if (numincomlevel<=6) then
              strgg = strgg .. lfhtablstlev (varta3mp,(numincomlevel+1),booutf8preserve) -- REKURSI
            else
              strgg = strgg .. strli7mit
            end--if
          end--if
        end--if (varta3mp~=nil) then
      end--if
      numindax = numindax + 1
    end--while
  end--if (numjumlahstr~=0) then

  if (numjumlahcet~=0) then -- no recursion here, all keys reported as "??"
    strgg = strgg .. lfileftlevel(numtitlevel) .. lfifontsizetit('Other keys:',numtitlevel)
    numindax = 0
    while true do
      if (numindax>=numjumlahcet) then -- index is ZERO-based
        break
      end--if
      varta3mp = tabvaluo [numindax+1] -- ONE-based for "table.sort"
      if (varta3mp~=nil) then -- always true ??
        strte7mp = '?? -> ' .. lfhreportvari(varta3mp,booutf8preserve)
        strgg = strgg .. lfileftlevel(numtitlevel+1) .. lfifont90nbsize(strte7mp)
      end--if (varta3mp~=nil) then
      numindax = numindax + 1
    end--while
  end--if (numjumlahcet~=0) then

  if (numincomlevel==0) then
    strgg = strgg .. string.char(10) -- terminate very last line
  end--if

  return strgg

end--function lfhtablstlev

------------------------------------------------------------------------

-- Local function LFHTABLIST

-- List all content of a table in a structured layout.

-- Depends on functions :
-- [H] lfhreportvari lfhalltostring lfhcompareidiotsafe
-- [H] lfhtableanal lfhtablstlev
-- [I] lfifontsizetit lfifont90nbsize lfileftlevel lfimini3ksani

local function lfhtablist (tabveryobscure, strtitofreport)
  local numlennel = 0
  local strhh = ''
  if (type(strtitofreport=='string')) then
    numlennel = string.len(strtitofreport)
    if ((numlennel~=0) and (numlennel<=100)) then -- got valid title
      strhh = lfifontsizetit(strtitofreport,-1) .. '<br>' -- special level
    end--if
  end--if
  strhh = strhh .. lfhtablstlev (tabveryobscure,0,false) -- HARDCODED here -- do NOT preserve UTF8
  return strhh
end--function lfhtablist

------------------------------------------------------------------------

---- VARIABLES [R] ----

------------------------------------------------------------------------

function exporttable.ek (arxframent)

  -- general unknown type and special type "args" AKA "arx"

  local vartymp = 0
  local arxsomons = 0 -- metaized "args" from our own or caller's "frame"

  -- general str

  local strimptarget = ''
  local strimperror = ''
  local strtajtlo = ''
  local strreport = ''

  -- general num

  local numerr = 0

  -- general boo

  local boofrommodu = false
  local boogotit = false

------------------------------------------------------------------------

---- MAIN [Z] ----

------------------------------------------------------------------------

  ---- MAYBE CALLED FROM A MODULE ----

  vartymp = arxframent.xx
  boofrommodu = (type(vartymp)=='table')

  ---- ARX FROM TEMPLATE ----

  if (not boofrommodu) then

    arxsomons = arxframent.args -- "args" from our own "frame"
    if (type(arxsomons)~='table') then
      arxsomons = {} -- guard against indexing error from our own
      numerr = 1 -- #E01 internal
    end--if
    if (arxsomons['caller']=='true') then
      arxsomons = arxframent:getParent().args -- "args" from caller's "frame"
    end--if
    if (type(arxsomons)~='table') then
      arxsomons = {} -- guard against indexing error again
      numerr = 1 -- #E01 internal
    end--if

  end--if

  ---- IMPORT VIA LOADDATA ----

  if ((not boofrommodu) and (numerr==0)) then

    strimptarget = arxsomons[1]
    if (type(strimptarget)=='string') then
      boogotit,vartymp = pcall(mw.loadData,strimptarget) -- could crash here
      if (boogotit) then
        boogotit = (type(vartymp)=='table') -- unlikely to fail here
      else
        strimperror = tostring(vartymp) -- seize error message
      end--if
    end--if

    if (not boogotit) then
      numerr = 2 -- #E02
    end--if

  end--if

  ---- LIST ----

  -- just calling big function "lfhtablist"

  if (numerr==0) then
    if (boofrommodu) then
      strtajtlo = 'Table coming from calling module'
    else
      strtajtlo = 'Table imported from data module "' .. strimptarget .. '"'
    end--if
    strreport = lfhtablist(vartymp, strtajtlo)
  else
    strreport = 'ERR: ' .. tostring(numerr)
    if (strimperror~='') then
      strreport = strreport .. ' import error: "' .. strimperror .. '"'
    end--if
  end--if

  ---- RETURN THE JUNK STRING ----

  return strreport

end--function exporttable.ek

  ---- RETURN THE JUNK LUA TABLE ----

return exporttable