Modulo:mdev32kat

Memtesto disponeblas sur la dokumentaĵa subpaĝo

--[===[

MODULE "MDEV32KAT" (deveno 3 2 kategorioj)

"eo.wiktionary.org/wiki/Modulo:mdev32kat" <!--2021-Jan-15-->

Purpose: brews 2 category includes from 2 language codes

Utilo: kreas 2 kategorienmetojn el 2 lingvokodoj

Manfaat: membutat 2 masukan kategori dari 2 kode bahasa

Syfte: skapar 2 kategoriinlaeggningar ...

Used by templates / Uzata far sxablonoj / Digunakan oleh templat:
- deveno3 (EO)

Required submodules / Bezonataj submoduloj / Submodul yang diperlukan:
- "mpiktbllki" in turn requiring "mbllingvoj" (EO)
- "mtbllingvoj" in turn requiring template "tbllingvoj" (EO)

Incoming: - 2 anonymous obligatory parameters
              - lemma language code (kapvorta)
              - origin language code (devena)
          - 2 named optional parameters somewhat hidden
              - "noc=" only possible value is "true" (any other value
                ignored), "true" causes empty result, forward "nocat="
                to this one if desired
              - "detrc=" only possible value is "true"

Returned: - one string with 2 category includes or empty on error or
            if "noc=" is "true"

: ---------------------------------------

* #T00 ("en", missing param)
* expected result: empty
* actual result via debu: "{{debu|{{#invoke:mdev32kat|ek|en}}|nw}}"

:* #T01 ("en|eo|vo", three params)
:* expected result: empty
:* actual result via debu: "{{debu|{{#invoke:mdev32kat|ek|en|eo|vo}}|nw}}"

* #T02 ("en|art", invalid code latter)
* expected result: empty
* actual result via debu: "{{debu|{{#invoke:mdev32kat|ek|en|art}}|nw}}"

:* #T03 ("deu|en", invalid code former)
:* expected result: empty
:* actual result via debu: "{{debu|{{#invoke:mdev32kat|ek|deu|en}}|nw}}"

* #T04 ("en|zzz", unknown code latter)
* expected result: empty
* actual result via debu: "{{debu|{{#invoke:mdev32kat|ek|en|zzz}}|nw}}"

:* #T05 ("zzz|en", unknown code former)
:* expected result: empty
:* actual result via debu: "{{debu|{{#invoke:mdev32kat|ek|zzz|en}}|nw}}"

* #T06 ("en|grc|noc=true", suppression)
* expected result: empty
* actual result via debu: "{{debu|{{#invoke:mdev32kat|ek|en|grc|noc=true}}|nw}}"

: ---------------------------------------

* #T10 ("en|grc")
* expected result: 2 cats ("El la greka" ...)
* actual result via debu: "{{debu|{{#invoke:mdev32kat|ek|en|grc}}|nw}}"

:* #T11 ("grc|en", silly example)
:* expected result: 2 cats ("El la angla" ...)
:* actual result via debu: "{{debu|{{#invoke:mdev32kat|ek|grc|en}}|nw}}"

* #T12 ("en|vo", silly example)
* expected result: 2 cats ("El Volapuko" ...)
* actual result via debu: "{{debu|{{#invoke:mdev32kat|ek|en|vo}}|nw}}"

:* #T13 ("vo|en")
:* expected result: 2 cats (more sane example) ("El la angla" ...)
:* actual result via debu: "{{debu|{{#invoke:mdev32kat|ek|vo|en}}|nw}}"

* #T14 ("vo|eo")
* expected result: 2 cats (more sane example) ("El Esperanto" ...)
* actual result via debu: "{{debu|{{#invoke:mdev32kat|ek|vo|eo}}|nw}}"

: ---------------------------------------

* note that all tests depend on "debu"
* note that all tests cannot be reasonably executed on the docs subpage without help of "pate" or "debu"

: ---------------------------------------

]===]

local dev32kat = {}

---- CONSTANTS ----

  -- uncommentable EO vs ID constant strings (core site-related features)

  local constrplki = "Modulo:mpiktbllki"  -- EO
  -- local constrplki = "Modul:mpiktbllki"   -- ID
  local constrkatp = "Kategorio:"         -- EO
  -- local constrkatp = "Kategori:"          -- ID

  -- constant table (ban list)

  -- add only obviously invalid access codes (2-letter or 3-letter)

  -- length of the list is NOT stored anywhere, the processing stops
  -- when type "nil" is encountered

  -- "en.wiktionary.org/wiki/Wiktionary:Language_treatment" excluded languages
  -- "en.wikipedia.org/wiki/Spurious_languages"
  -- "iso639-3.sil.org/code/art" only valid in ISO 639-2
  -- "iso639-3.sil.org/code/zxx" "No linguistic content"

  local contabisbanned = {}
  contabisbanned = {'dc', 'll', 'art','deu','eng','epo','fra','lat','por','rus','spa','swe','tup','zxx'} -- 1...14

  -- constant table (3 integers for preliminary parameter check)

  local contabparam = {}
  contabparam[0] = 2   -- minimal number of anon parameters
  contabparam[1] = 2   -- maximal number of anon parameters
  contabparam[2] = 160 -- maximal length of single para (min is hardcoded ONE)

---- IMPORTS ----

local piktbllki = require(constrplki) -- can crash here

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

---- ORDINARY LOCAL STRING FUNCTIONS ----

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

-- test whether char is an ASCII digit "0"..."9", return bool

local function lftestnum (numkaad)
  local boodigit = false
  boodigit = ((numkaad>=48) and (numkaad<=57))
  return boodigit
end--function lftestnum

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

-- test whether char is an ASCII lowercase letter, return bool

local function lftestlc (numcode)
  local boolowerc = false
  boolowerc = ((numcode>=97) and (numcode<=122))
  return boolowerc
end--function lftestlc

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

---- ORDINARY LOCAL HIGH LEVEL FUNCTIONS ----

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

-- Local function LFCHKKODINV

-- Check whether a string (intended to be a language code) contains only 2
-- or 3 lowercase letters or maybe a digit in middle position or maybe
-- instead equals to "-" or "??" and maybe additionally is not
-- included on the ban list.

-- Input  : * strqooq -- string (empty is useless and returns
--                       "true" ie "bad" but can't cause any harm)
--          * numnokod -- "0" ... "3" how special codes "-" "??" should pass
--          * boodigit -- "true" to allow digit in middle position
--          * boonoban -- "true" to skip test against ban table

-- Output : * booisbadlk -- bool "true" if the string is evil

-- This sub depends on "STRING FUNCTIONS"\"lftestnum"
-- and "STRING FUNCTIONS"\"lftestlc".

-- We need const table "contabisbanned".

local function lfchkkodinv (strqooq, numnokod, boodigit, boonoban)
  local varomongkosong = "" -- for check against the ban list
  local booisbadlk = false -- pre-assume good
  local numchiiar = 0
  local numukurran = 0
  local numindeex = 0 -- ZERO-based
  while (true) do -- fake (outer) loop
    if ((strqooq=="-") and ((numnokod==1) or (numnokod==3))) then
      break -- to join mark -- good
    end--if
    if ((strqooq=="??") and ((numnokod==2) or (numnokod==3))) then
      break -- to join mark -- good
    end--if
    numukurran = string.len (strqooq)
    if ((numukurran<2) or (numukurran>3)) then
      booisbadlk = true
      break -- to join mark -- evil
    end--if
    numchiiar = string.byte (strqooq,1,1)
    if (lftestlc(numchiiar)==false) then
      booisbadlk = true
      break -- to join mark -- evil
    end--if
    numchiiar = string.byte (strqooq,numukurran,numukurran)
    if (lftestlc(numchiiar)==false) then
      booisbadlk = true
      break -- to join mark -- evil
    end--if
    if (numukurran==3) then
      numchiiar = string.byte (strqooq,2,2)
      if ((boodigit==false) or (lftestnum(numchiiar)==false)) then
        if (lftestlc(numchiiar)==false) then
          booisbadlk = true
          break -- to join mark -- evil
        end--if
      end--if ((boodigit==false) or (lftestnum(numchiiar)==false))
    end--if
    if (boonoban==false) then
      while (true) do -- ordinary inner loop
        varomongkosong = contabisbanned[numindeex+1] -- number of elem unknown
        if (type(varomongkosong)~="string") then
          break -- abort inner loop (then fake outer loop) due to end of table
        end--if
        numukurran = string.len (varomongkosong)
        if ((numukurran<2) or (numukurran>3)) then
          break -- abort inner loop (then fake outer loop) due to faulty table
        end--if
        if (strqooq==varomongkosong) then
          booisbadlk = true
          break -- abort inner loop (then fake outer loop) due to violation
        end--if
        numindeex = numindeex + 1 -- ZERO-based
      end--while -- ordinary inner loop
    end--if (boonoban==false) then
    break -- finally to join mark
  end--while -- fake loop -- join mark
  return booisbadlk
end--function lfchkkodinv

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

---- MAIN EXPORTED FUNCTION ----

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

function dev32kat.ek (arxframent)

  -- general unknown type

  local vartmp = 0     -- variable without type multipurpose

  -- special type "args" AKA "arx"

  local arxourown = 0  -- metaized "args" from our own "frame"

  -- general str

  local strtmp      = ""  -- temp

  local strvistrc   = ""  -- debug report requested by "detrc="
  local strinvkat   = ""  -- invisible category part
  local strret      = ""  -- final result string

  local strkodbah3  = ""  -- language code from arxourown[1] kapvorta
  local strkodbah4  = ""  -- language code from arxourown[2] devena
  local strnambah3  = ""  -- language name kapvorta
  local strnambah4  = ""  -- language name devena

  -- general num

  local numpindex = 0 -- number of anon params
  local numlong   = 0 -- for parameter processing
  local numtamp   = 0 -- for parameter processing
  local numoct    = 0

  -- general boo

  local booerr    = false
  local boonocat  = false  -- from "noc=true" forwarded
  local bootrace  = false  -- from "detrc=true"

  ---- GUARD AGAINST INTERNAL ERROR AND GET THE ARX ----

  if ((type(constrplki)=="nil") or (type(constrkatp)~="string")) then
    boerr = true
  else
    arxourown = arxframent.args -- "args" from our own "frame"
  end--if

  ---- PRELIMINARILY ANALYZE ANONYMOUS PARAMETERS ----

  -- this will catch holes, empty parameters, too long parameters,
  -- and wrong number of parameters

  -- below on exit var "numpindex" will contain number of
  -- prevalidated anonymous params

  -- this depends on 3 constants:
  -- * contabparam[0] minimal number
  -- * contabparam[1] maximal number
  -- * contabparam[2] maximal length (default 160)

  if (booerr==false) then
    numpindex = 0 -- ZERO-based
    numtamp = contabparam[1] -- maximal number of params
    while (true) do
      vartmp = arxourown [numpindex+1] -- can be "nil"
      if ((type(vartmp)~="string") or (numpindex>numtamp)) then
        break -- good or bad
      end--if
      numlong = string.len (vartmp)
      if ((numlong==0) or (numlong>contabparam[2])) then
        booerr = true
        break -- only bad here
      end--if
      numpindex = numpindex + 1 -- on exit has number of valid parameters
    end--while
    if ((numpindex<contabparam[0]) or (numpindex>numtamp)) then
      booerr = true
    end--if
  end--if

  ---- PROCESS 2 OBLIGATORY ANONYMOUS PARAMS INTO 2 STRINGS ----

  -- now var "numpindex" sudah contains number of prevalidated params
  -- always 2 and is useless

  -- here we validate and assign "strkodbah3" and "strkodbah4"

  -- "lfchkkodinv" returns "true" on failure (control
  -- code 0: neither "-" nor "??" is permitted)

  -- this depends directly on const bool "conboomiddig"

  -- this depends indirectly on const table "contabisbanned" via "lfchkkodinv"

  if (booerr==false) then
    strkodbah3 = arxourown[1] -- language code kapvorta
    booerr = booerr or (lfchkkodinv(strkodbah3,0,conboomiddig,false))
    strkodbah4 = arxourown[2] -- language code devena
    booerr = booerr or (lfchkkodinv(strkodbah4,0,conboomiddig,false))
  end--if

  strtmp = 'Done with anon parameters, got kav = "' .. strkodbah3 .. '" and dev = "' .. strkodbah4 .. '".'
  strvistrc = strvistrc .. "<br>" .. strtmp
  strtmp = 'Critical "booerr" flag is ' .. tostring (booerr)
  strvistrc = strvistrc .. "<br>" .. strtmp

  ---- PROCESS 2 HIDDEN NAMED PARAMS ----

  -- no error is possible here

  -- "detrc=" must be seized unconditionally even if we already suck

  if (arxourown['noc']=='true') then
    boonocat = true
  end--if
  if (arxourown['detrc']=='true') then
    bootrace = true
  end--if

  ---- PEEK THE LANGUAGE NAMES VIA SUBMODULE ----

  -- get name in site language ("c0") 2 times

  if (booerr==false) then
    strnambah3 = piktbllki.ek { args = { strkodbah3 , "0" } }
    if ((strnambah3=="=") or (strnambah3=="-")) then
      booerr = true
    else
      strnambah4 = piktbllki.ek { args = { strkodbah4 , "0" } }
      if ((strnambah4=="=") or (strnambah4=="-")) then
        booerr = true
      end--if
    end--if
  end--if

  if (bootrace) then
    strtmp = 'Peeking done, critical "booerr" flag is ' .. tostring (booerr)
    strvistrc = strvistrc .. "<br>" .. strtmp
  end--if

  ---- AUGMENT ONE LANGUAGE NAME IF NEEDED ----

  -- only "strnambah4" ie "devena" has to be augmented !!!

  if (booerr==false) then
    numlong = string.len (strnambah4)
    numoct = string.byte (strnambah4,numlong,numlong)
    if (numoct~=111) then -- "o"
      strnambah4 = "la " .. strnambah4
    end--if
  end--if

  ---- BREW THE INVISIBLE CATEGORY PART ----

  -- string "constrkatp" is cat prefix and includes the colon ":"

  if ((booerr==false) and (boonocat==false)) then
    strinvkat = '[[' .. constrkatp .. 'El ' .. strnambah4 .. ']]'
    strinvkat = strinvkat ..'[[' .. constrkatp .. 'El ' .. strnambah4 .. ' (' .. strnambah3 .. ')]]'
  end--if

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

  strret = strinvkat
  if (bootrace) then
    strret = "<br>" .. strvistrc .. "<br><br>" .. strret
  end--if
  return strret

end--function

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

return dev32kat