MODULO
Memtesto ne disponeblas.
Ĉi tiu modulo estas uzata sur la ĉefpaĝo kaj protektitaVi povas inspekti la protokolon pri protektoj.
Se vi konas la eblajn sekvojn kaj havas sufiĉajn rajtojn, tiam vi povas zorgeme ekredakti.
Se vi ne kuraĝas aŭ ne rajtas redakti tiam vi povas proponi la deziratan ŝanĝon en la diskutejo.

--[===[

MODULE "MPICKLINES" (pick lines)

"eo.wiktionary.org/wiki/Modulo:mpicklines" <!--2019-Nov-09-->

Purpose: picks a part of a text defined by line indexes, intended
         for news but usable for other purposes as well

Utilo: elprenas parton de teksto difinita per linioindeksoj, intencita
       por novajxoj sed uzebla ankaux alimaniere

Manfaat: ...

Syfte: plockar fram en del av en text definierad med hjaelp av radindex,
       avsett foer nyheter men anvaendbar aeven foer andra syften

Used by templates / Uzata far sxablonoj:
- novajxoj

Required submodules / Bezonataj submoduloj:
- none / neniuj

Incoming: - nothing (seized from caller's frame instead)

Returned: - picked text or (customizable) error message

Parameters seized from the caller's frame:
          - 3 anonymous obligatory parameters
              - name of the source template holding the
                incoming text (5...100 octet:s) with namespace
                prefix, for example "Templat:kabar-sumber"
              - earliest line to pick (ZERO-based, 0...99'999)
              - last line to pick (ZERO-based, 0...99'999)
          - 1 named optional parameter "err="
            - alternative output string to replace the "=" error
              message (1...64 char:s, default is "=") (this works even
              for errors coming from anonymous parameters)

An error is generated if:
- more or less than 3 anonymous obligatory parameters have been supplied
- the template name is obviously faulty
- earliest line index or last line index is faulty or out of range
- "last line index" < "earliest line index" (but they may be equal)
- pointed source template does not exist
- text from the source template, even after stripping of blank
  lines, is empty (<4 octet:s)
- text from the source template is faulty (see below)
- text from the source template is too short and end of
  text is reached before earliest line index, ie
  "amount of lines" <= "earliest line index" (must be bigger)
It is NOT per se an error if "amount of lines" < "last line index".

Example:
- 3 incoming lines
- earliest line index can be ZERO to 2
- (0,2) returns all 3 lines
- (0,5) returns all 3 lines
- (2,5) returns 1 line
- (3,5) is an error

Text structure:
Every line must begin with "* " (star and space) and end with an EOL.
Trailing spaces are NOT tolerated. Minimum line length is 3 octet:s
including the "* " but excluding EOL, maximum line length is 400 octet:s.
Blank lines, even multiple, are allowed at beginning and end of the text.
Single blank lines are allowed anywhere in the text. All blank lines
are skipped from counting. Multiple blank lines are prohibited inside
the text. All text, even outside of the selection is checked.

]===]

local picklines = {}

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

---- ORDINARY LOCAL LOW LEVEL FUNCTIONS ----

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

-- Local function LFDECINP

-- Convert string (1...13 octet:s) with decimal digits to positive
-- integer number (0...4'000'000'000) ignoring possible inside apo:s

-- 65'536 good -- 655'36 ugly but accepted -- 6''''55''''36 ugly but accepted
-- '65536 rejected -- 65536' rejected

-- Input  : - strin

-- Output : - numaout (4'294'967'295 on error)

local function lfdecinp (strin)
  local numaout = 0
  local numleen = 0
  local numinxx = 1 -- ONE-based -- counts up
  local numokkt = 0
  numleen = string.len (strin)
  if ((numleen<1) or (numleen>13)) then
    numaout  = 4294967295 -- damn
  else
    while (true) do
      numokkt = string.byte (strin,numinxx,numinxx)
      if (numokkt==39) then
        if ((numinxx==1) or (numinxx==numleen)) then
          numaout  = 4294967295
          break -- damn (may not begin or end with apo)
        end--if
      else
        if ((numokkt<48) or (numokkt>57) or (numaout>400000000)) then
          numaout  = 4294967295
          break -- damn (bad char or out of range)
        end--if
        numaout = numaout * 10 + (numokkt - 48)
      end--if
      if (numinxx==numleen) then
        break -- done (hopefully success, but not yet sure)
      end--if
      numinxx = numinxx + 1
    end--while
    if (numaout>4000000000) then
      numaout  = 4294967295 -- damn (out of range)
    end--if
  end--if
  return numaout
end--function lfdecinp

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

---- MAIN EXPORTED FUNCTION ----

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

function picklines.ek (arxframent)

  -- general unknown type

  local vartmp = 0     -- variable without type

  -- special type "args" AKA "arx"

  local arxcaller = 0  -- metaized "args" from caller's "frame" (NOT our own)

  -- general "str"

  local strtplnam = ""  -- name of the source template from args[1]
  local strerrequ = "=" -- default or alterna string to replace "=" on error
  local strtmp    = ""
  local strtext   = ""  -- huge string from the source template
  local strret    = ""  -- output string

  -- general "num"

  local numlong   = 0  -- length of parameter
  local numearl   = 0  -- earliest line from args[2]
  local numlast   = 0  -- last line from args[3]
  local numbegwh  = 0  -- ONE-based -- of whole text after stripping
  local numlaswh  = 0  -- ONE-based -- of whole text after stripping
  local numbegse  = 0  -- ONE-based -- of selection
  local numlasse  = 0  -- ONE-based -- of selection
  local numlinx   = 0  -- line index -- ZERO-based -- counts up
  local numokix   = 0  -- overall octet index -- ONE-based -- counts up
  local numokyx   = 0  -- additional octet index -- ONE-based -- counts up
  local numoct    = 0  -- temp some cool char
  local numokt    = 0  -- temp some silly char
  local numoqt    = 0  -- temp some great char

  -- general "boo"

  local booerr    = false  -- fatal error flag

  ---- GET THE ARXCALLER ----

  arxcaller = arxframent:getParent().args -- "args" from caller's "frame"

  ---- SEIZE 3 OBLIGATORY ANONYMOUS PARAMETERS SUBMITTED TO CALLER ----

  while (true) do -- fake loop
    if ((arxcaller[1]==nil) or (arxcaller[2]==nil) or (arxcaller[3]==nil) or (arxcaller[4])) then
      booerr = true -- need 3 obligatory params, 4 are not appreciated
      break -- to join mark
    end--if
    strtplnam = arxcaller[1] -- string 5...100 -- #1
    numlong = string.len (strtplnam)
    if ((numlong<5) or (numlong>100)) then
      booerr = true -- must be 5...100 octet:s
      break -- to join mark
    end--if
    strtmp =  arxcaller[2] -- string 1...6 -- #2
    numlong = string.len (strtmp)
    if ((numlong<1) or (numlong>6)) then
      booerr = true -- must be 1....6 octet:s
      break -- to join mark
    end--if
    numearl = lfdecinp (strtmp)
    if (numearl>99999) then
      booerr = true -- damn again
      break -- to join mark
    end--if
    strtmp =  arxcaller[3] -- string 1...6 -- #3
    numlong = string.len (strtmp)
    if ((numlong<1) or (numlong>6)) then
      booerr = true -- must be 1....6 octet:s
      break -- to join mark
    end--if
    numlast = lfdecinp (strtmp)
    if ((numlast<numearl) or (numlast>99999)) then
      booerr = true -- damn again
      break -- to join mark
    end--if
    break -- finally to join mark
  end--while -- fake loop -- join mark

  ---- SEIZE 1 OPTIONAL NAMED PARAMETER SUBMITTED TO CALLER ----

  if (booerr==false) then
    vartmp = arxcaller["err"]
    if (type(vartmp)=="string") then
      numlong = string.len (vartmp)
      if ((numlong>0) and (numlong<65)) then
        strerrequ = vartmp -- 1...64 octet:s
      end--if
    end--if
  end--if

  ---- CHECK WHETHER THE POINTED TEMPLATE EXISTS AT ALL AND EXPAND IT ----

  -- we do NOT assign "booerr" to "true" but may leave "strtext" empty instead

  if (booerr==false) then
    strtext = ""
    strtmp = arxframent:callParserFunction ('#ifexist:'..strtplnam,'1','0')
    if (strtmp=='1') then
      vartmp = arxframent:expandTemplate { title = strtplnam }
      if ((type(vartmp))=='string') then
        strtext = vartmp -- may be empty
      end--if
    end--if (strtmp=='1') then
  end--if

  ---- STRIP OFF SOME BLANK LINES AND REJECT POSSIBLE EMPTY STUFF ----

  -- note that incoming "strtext" may be empty as hell, or become empty
  -- or too short only during stripping

  -- we always add an EOL to the text and keep one EOL left at
  -- the end after stripping

  -- numbegwh, numlaswh -- whole text

  -- "+3" check means at least 4 octet:s inclusive

  if (booerr==false) then
    strtext = strtext .. string.char (10)
    numbegwh = 1 -- ONE-based
    numlaswh = string.len (strtext) -- ONE-based -- may NOT be 0 due added EOL
    while (true) do
      if ((numbegwh+3)>numlaswh) then
        booerr = true -- damn again -- empty NOT appreciated !!!
        break
      end--if
      numoct = string.byte (strtext,numbegwh,numbegwh)
      numokt = string.byte (strtext,(numlaswh-1),(numlaswh-1)) -- keep 1 EOL
      if ((numoct~=10) and (numokt~=10)) then
        break -- done
      end--if
      if (numoct==10) then
        numbegwh = numbegwh + 1
      end--if
      if (numokt==10) then
        numlaswh = numlaswh - 1
      end--if
    end--while
  end--if

  ---- CARRY OUT THE HARD SEARCH WORK ----

  -- trailing spaces $20 are prohibited
  -- trailing UTF8 NBSP-spaces $A0 ($C2,$A0) are prohibited

  -- numbegwh, numlaswh -- whole text
  -- numbegse, numlasse -- selection

  -- both "numokix" and "numokyx" are ONE-based for "string.byte"

  -- "+3" check means at least 4 octet:s inclusive

  if (booerr==false) then
    numlinx = 0 -- line index -- ZERO-based
    numokix = numbegwh -- octet index -- ONE-based -- overall
    while (true) do
      if ((numokix+3)>numlaswh) then
        booerr = true -- damn -- need at least 4 octet:s left
        break
      end--if
      numoct = string.byte (strtext,numokix,numokix) -- "*"
      numokt = string.byte (strtext,(numokix+1),(numokix+1)) -- " "
      numoqt = string.byte (strtext,(numokix+2),(numokix+2)) -- NOT EOL," ","*"
      if ((numoct~=42) or (numokt~=32) or (numoqt==10) or (numoqt==32) or (numoqt==42)) then
        booerr = true -- damn
        break -- outer loop
      end--if
      numokyx = numokix + 3 -- 3 char:s already done
      while (true) do
        numoct = string.byte (strtext,numokyx,numokyx)
        if (numoct==10) then
          numokt = string.byte (strtext,(numokyx-1),(numokyx-1)) -- no underfl
          if ((numokt==32) or (numokt==160)) then
            booerr = true -- damn -- trailing whitespace
          end--if
          break -- inner loop -- good or bad -- found an EOL here
        end--if
        if ((numokyx-numokix)==400) then
          booerr = true -- damn -- line too long
          break -- inner loop
        end--if
        numokyx = numokyx + 1 -- looking for EOL ending the line
      end--while
      if (booerr==true) then
        break -- outer loop -- damn
      end--if
      if (numlinx==numearl) then
        numbegse = numokix -- note that we have "numlasse" if have "numbegse"
      end--if
      if ((numlinx>=numearl) and (numlinx<=numlast)) then
        numlasse = numokyx -- last inclusive, it is always an EOL, repeatedly
      end--if
      numlinx = numlinx + 1 -- one line checked and counted
      if (numokyx==numlaswh) then
        break -- outer loop -- this is THE ONLY HAPPY EXIT from the outer loop
      end--if
      numokix = numokyx + 1 -- jump over the EOL
      numoct = string.byte (strtext,numokix,numokix) -- maybe one more EOL
      if (numoct==10) then
        numokix = numokix + 1 -- jump over the extra EOL, legal blank line
      end--if
    end--while
    if (numbegse~=0) then -- note that we have "numlasse" if have "numbegse"
      strtext = string.sub (strtext,numbegse,numlasse) -- perform the cut
    else
      booerr = true -- damn -- final bad luck
    end--if
  end--if (booerr==false)

  ---- PREPARE ----

  if (booerr==true) then
    strret = strerrequ -- error -- string "strret" was preset to empty
  else
    strret = strtext -- cool
  end--if

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

  return strret

end--function

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

return picklines