Module:SimpleArgs

Jump to navigation Jump to search

Use[edit source]

Used by other modules.

Lua error in Module:TNT at line 157: attempt to index field 'data' (a nil value).

Functions[edit source]

  • Args are the arguments from the current frame.
  • Where is the name/s or order of the parameter.
  • The * mark indicates that it is an optional parameter). If you do not want to assign an optional non-correlative value you can assign the nil value.
Example: number_function (Args, ParId, LimInf*, LimSup*) -> number_function (args, 1, nil, 12) will verify that the number is not greater than 12.
Obviously it would be correct -> number_function (args, 1), without any verification of the values of the numbers.
  • Str (ing): String
  • Num (ber): Number.
  • Int (teger): Integer
  • Pos(itive)Num/Int: Positive/Integer number.
  • ZeroOrPos Num / Int: Zero or positive/Integer number.
  • Char (acter): Character.
  • Tab (ble): Table.

Main[edit source]

  • GetArgs (frame, HandleError*, SameSize*) - Returns arguments and its number.
If HandleError == true -> Error.handle = true
If SameSize == true -> Error.samesize = true

Handling of errors[edit source]

  • Error = {
handle = false,
yes = false,
msg = ,
samesize = false,
}
  • MsgError (S)

If handle = false when there is an input error. Thus: Lua error: error.

If handle = true, then the programmer will put in his/her module codereturn with the error, thus return MsgError(), returning the message with the font of a lua error. So: error. Check parameter by parameter is made if an error is not detected.

  • The error is recorded in a variable.
  • It is recorded that an error has been found and thus no more errors are checked in the rest of the parameters.
  • At the end of the check and input of variables the programmer should write: if SA.Error.yes then return SA.MsgError() end (where SA is defined as local SA = require "Module:SimpleArgs").

If handle = true and samesize = true then the returned message will be bolded and red in font. Thus: error.

See the examples

Other[edit source]

  • p.ParamsSep = '/' - Variable used for next function.
  • ConcatParams (tab) - Used when a parameter has more one name for same parameter.

Numbers checking[edit source]

They return the number N if this number are correct, otherwise returns an error message.

  • CheckNum (N, ParId, LimInf, LimSup)
  • CheckNumIsInt (N, ParId, LimInf*, LimSup*)
  • CheckNumIsPos (N, ParId, LimInf*, LimSup*)
  • CheckNumIsZeroOrPos (N, ParId, LimSup*)

Check if strings are numbers[edit source]

They return a number if the string is a correct number, otherwise returns an error message.

  • CheckSIsNum (S, ParId, LimInf*, LimSup*)
  • CheckSIsInt (S, ParId, LimInf*, LimSup*)
  • CheckSIsPosInt (S, ParId, LimInf*, LimSup*)
  • CheckSIsZeroOrPosInt (S, ParId, LimSup*)

Values from specific parameters of the frame[edit source]

The functions with an initial R indicate that the parameter is required. They return the value of the requested type of the parameter if it is correct, otherwise they return an error message. See the examples in Module:SimpleArgs/Tests/SVals

Strings[edit source]

  • Str_Par (Args, ParId, Default*)
  • RStr_Par (Args, ParId, OKEmpty*)
  • Char_Par (Args, ParId, Pattern, Default*)
  • RChar_Par (Args, ParId, Pattern)
  • NulOrWhitespace_Par (Args, ParId)
  • StrChkTab_Par (Args, ParId, Tab, CaseSens*, Default*)
  • RStrChkTab_Par (Args, ParId, Tab, CaseSens*)
  • StrIdxChkTab_Par (Args, ParId, Tab, CaseSens*, Default*)
  • RStrIdxChkTab_Par (Args, ParId, Tab, CaseSens*)

Numbers[edit source]

  • Num_Par (Args, ParId, Default*, LimInf*, LimSup*)
  • RNum_Par (Args, ParId, LimInf*, LimSup*)
  • PosNum_Par (Args, ParId, Default*, LimInf*, LimSup*)
  • RPosNum_Par (Args, ParId, LimInf*, LimSup*)
  • ZeroOrPosNum_Par (Args, ParId, Default*, LimInf*, LimSup*)
  • RZeroOrPosNum_Par (Args, ParId, LimInf*, LimSup*)
  • Int_Par (Args, ParId, Default*, LimInf*, LimSup*)
  • RInt_Par (Args, ParId, LimInf*, LimSup*)
  • PosInt_Par (Args, ParId, Default*, LimInf*, LimSup*)
  • RPosInt_Par (Args, ParId, LimInf*, LimSup*)
  • ZeroOrPosInt_Par (Args, ParId, Default*, LimSup*)
  • RZeroOrPosInt_Par (Args, ParId, LimSup*)

Boolean[edit source]

  • Bool_Par (Args, ParId, Default*)
  • RBool_Par (Args, ParId, Default*)

Index from a list[edit source]

  • StrIdxChkTab (Args, ParId, CaseSens, Default, ...)
  • RStrIdxChkTab (Args, ParId, CaseSens, ...)
  • StrIdxChkTabE (Args, ParId, CaseSens, Default, ...)
  • RStrIdxChkTabE (Args, ParId, CaseSens, ...)

Tables of strings or numbers[edit source]

MinItemNum and MaxItemNum, indicate the minimum and maximum number of elements inserted in the table.

When any of the values is not assigned, it will be operated according to OnEmpty: 0: It will be included. 1: Will not be included. 2. It will trigger an error and its message.

From one parameter[edit source]

For the same parameter with elements separated by Sep. Example, with "Sep" = ":" and the parameter = "12 : 1 : 1.3" returns {12, 1, 1.3}

  • StrTab_1Par (Args, ParId, Sep, MinItemNum*, MaxItemNum*, OnEmpty*)
  • NumTab_1Par (Args, ParId, Sep, MinItemNum*, MaxItemNum*, LimInf*, LimSup*, OnEmpty*)
  • PosNumTab_1Par (Args, ParId, Sep, MinItemNum*, MaxItemNum*, LimInf*, LimSup*, OnEmpty*)
  • ZeroOrPosNumTab_1Par (Args, ParId, Sep, MinItemNum*, MaxItemNum*, LimInf*, LimSup*, OnEmpty*)
  • IntTab_1Par (Args, ParId, Sep, MinItemNum*, MaxItemNum*, LimInf*, LimSup*, OnEmpty*)
  • PosIntTab_1Par (Args, ParId, Sep, MinItemNum*, MaxItemNum*, LimInf*, LimSup*, OnEmpty*)
  • ZeroOrPosIntTab_1Par (Args, ParId, Sep, MinItemNum*, MaxItemNum*, LimInf*, LimSup*, OnEmpty*)
Of several parameters[edit source]

The parameters can be:

  • A number, then it will take the parameters from the current parameter to the last parameter.
  • If it is a string, it must contain a $d that will be replaced by a correlative integer (from 1) until no parameter is found. Example: 'para $d', look for 'para 1', 'para 2', etc.
  • If it is a table, the same search will be done that the previous point for each one of the values. Example: {'para $d', param $d}, will search 'para 1' and 'param 1', then 'para 2' and 'param 2', etc.

The functions:

  • StrTab_NPar (Args, NArgs, ParId, MinItemNum*, MaxItemNum*, OnEmpty*)
  • NumTab_NPar (Args, NArgs, ParId, MinItemNum*, MaxItemNum*, LimInf*, LimSup*, OnEmpty*)
  • PosNumTab_NPar (Args, NArgs, ParId, MinItemNum*, MaxItemNum*, LimInf*, LimSup*, OnEmpty*)
  • ZeroOrPosNumTab_NPar (Args, NArgs, ParId, MinItemNum*, MaxItemNum*, LimInf*, LimSup*, OnEmpty*)
  • IntTab_NPar (Args, NArgs, ParId, MinItemNum*, MaxItemNum*, LimInf*, LimSup*, OnEmpty*)
  • PosIntTab_NPar (Args, NArgs, ParId, MinItemNum*, MaxItemNum*, LimInf*, LimSup*, OnEmpty*)
  • ZeroOrPosIntTab_NPar (Args, NArgs, ParId, MinItemNum*, MaxItemNum*, LimInf*, LimSup*, OnEmpty*)

See the examples in Module:SimpleArgs/Tests/SVals

External links[edit source]


local p = {}

--[[ 
1. Get arguments (whether the arguments are called with #invoke or from a template)
2. Get parameters (of several types with their verification) from frame arguments.
	ParId parameter is identified by a position (1, 2, 3 ... ), single name (|name= |other name=) or table of two names for each parameter.
	This last options is used in translations that retain the original language (or main), usually English, i.e.:
	local keywords = { -- in this case with Spanish
		name =		 {'name',		'nombre'},
		other name = {'other name',	'otro nombre'},
	}
	Then the parameter can be obtained with p.GetStr_Par (Args, keywords[name])
--]]

--[[ 
TRANSLATION, in :Commons:Data:I18n/SimpleArgs.tab
local RS_SIsNotNumber = '$1 is not a number'
local RS_NIsNotPosNumber = '$1 is not a positive number'
local RS_NIsNotZeroOrPosNumber = '$1 is not zero or a positive number'
local RS_NIsNotInt = '$1 is not an integer number'
local RS_NIsNotInRange = '$1 is not between $2 and $3'
local RS_NIsLessThan = '$1 is less than $2'
local RS_NIsGreaterThan = '$1 is greater than $2'
local RS_STabIsNotInRange = The item number ($1) is not between $2 and $3'
local RS_STabFewItems = 'The item number ($1) is not between $2 and $3'
local RS_SIsNotAssigned = 'It has not assigned value'
local RS_CharNotFoundInPattern = '"\"$1\" is not a character of \"$2\""'
local RS_SNotFoundInTab = '\"$1\" is not found in \"$2\"'
local RS_EmptyValue = '\"$1\" has not a value'
--]]
local RS_SIsNotNumber = 'SIsNotNumber'
local RS_NIsNotPosNumber = 'NIsNotPosNumber'
local RS_NIsNotZeroOrPosNumber = 'NIsNotZeroOrPosNumber'
local RS_NIsNotInt = 'NIsNotInt'
local RS_NIsNotInRange = 'NIsNotInRange'
local RS_NIsLessThan = 'NIsLessThan'
local RS_NIsGreaterThan = 'NIsGreaterThan'
local RS_STabIsNotInRange = 'STabIsNotInRange'
local RS_STabFewItems = 'STabFewItems'
local RS_SIsNotAssigned = 'SIsNotAssigned'
local RS_CharNotFoundInPattern = 'CharNotFoundInPattern'
local RS_SNotFoundInTab = 'SNotFoundInTab'
local RS_EmptyValue = 'EmptyValue'

local yesno = require('Module:YesnoTNT')
local SD = require('Module:SimpleDebug')
local TNTT = require('Module:TNTTools')

local function I18nStr (S, ...)
	return TNTT.GetMsgP ('SimpleArgs', S, {...})
end

----------

p.Error = {
	handle = false,
	yes = false,
	msg = '',
	samesize = false
	}
function p.MsgError (S)
	if S == nil then
		if p.Error.samesize then
			return '<span style="color:red;font-weight:bold">'..p.Error.msg..'</span>'
		else	
			return '<strong class="error">'..p.Error.msg..'</strong>'
		end
	else
		if p.Error.handle then
			p.Error.msg = S
			p.Error.yes = true
		else
			error (S, 0)
		end
	end
end--MsgError
	
function p.GetArgs (frame, HandleError, SameSize)
	local origArgs
	if frame == mw.getCurrentFrame() then
		-- We're being called via #invoke. If the invoking template passed any arguments,
		-- use them. Otherwise, use the arguments that were passed into the template.
		origArgs = frame:getParent().args
		for k, v in pairs( frame.args ) do
			origArgs = frame.args
			break
		end
	else		
		-- We're being called from another module or from the debug console, so assume
		-- the arguments are passed in directly.
		origArgs = frame
	end
	Nargs = 0
	for k, v in pairs(origArgs) do
		Nargs = Nargs + 1
	end
	if (HandleError ~= nil) and (HandleError == true) then
		p.Error.handle = true
		if (SameSize ~= nil) and (SameSize == true) then
			p.Error.samesize = true
		end
	end
	if p.Error.handle and (Nargs == 0) then 
		p.MsgError ('')
	end
	return origArgs, Nargs
end --GetArgs

p.ParaSep = '/'
function p.ConcatParams (tab)
	return '"'..table.concat(tab,p.ParaSep)..'"'
end

function ParamErrorS (ParId, S)
	if ParId == nil then
		error ('Not assigned ParId') --Not require translation, only debug
	elseif ParId ~= '' then
		local SParaId = ''
		if type(ParId)=='table' then
			SParaId = p.ConcatParams (ParId)
		else
			if type(ParId)=='number' then
				ParId = '#'..ParId
			end
			SParaId = ParId 
		end
		S = SParaId..' = '..S
	end
	p.MsgError (S)
end--ParamErrorS

function ParamError (ParId, RS, Value)
	if Value == '' then
		Value = '""'
	end
	local S = I18nStr (RS, tostring(Value))
	ParamErrorS (ParId, S)
end--ParamError

----------
function prepNum (N)
	return mw.getContentLanguage():formatNum (N)
end

function p.CheckNum (N, ParId, LimInf, LimSup)
	if (p.Error.yes) or (not N) then return end
	if ((LimInf ~= nil) and (N < LimInf)) and ((LimSup ~= nil) and (N > LimSup)) then
		ParamErrorS (ParId, I18nStr (RS_NIsNotInRange, prepNum(N), prepNum(LimInf), prepNum(LimSup)))
	elseif (LimInf ~= nil) and (N < LimInf) then
		ParamErrorS (ParId, I18nStr (RS_NIsLessThan, prepNum(N), prepNum(LimInf)))
	elseif (LimSup ~= nil) and (N > LimSup) then
		ParamErrorS (ParId, I18nStr (RS_NIsGreaterThan, prepNum(N), prepNum(LimSup)))
	end
end --p.CheckNum

function p.CheckNumIsInt (N, ParId, LimInf, LimSup)
	if p.Error.yes then return end
	if N == math.floor(N) then
		p.CheckNum (N, ParId, LimInf, LimSup)
	else
		ParamError (ParId, RS_NIsNotInt, prepNum(N))
	end
end --CheckNumIsInt

function p.CheckNumIsPos (N, ParId, LimInf, LimSup)
	if p.Error.yes then return end
	if N > 0 then
		p.CheckNum (N, ParId, LimInf, LimSup)
	else	
		ParamError (ParId, RS_NIsNotPosNumber, N)
	end
end --CheckNumIsPos

function p.CheckNumIsZeroOrPos (N, ParId, LimSup)
	if p.Error.yes then return end
	if N >= 0 then
		p.CheckNum (N, ParId, 0, LimSup)
	else	
		ParamError (ParId, RS_NIsNotZeroOrPosNumber, N)
	end
end --CheckNumIsZeroOrPos

-----

function p.CheckSIsNum (S, ParId, LimInf, LimSup)
	if p.Error.yes then return end
	local N = tonumber(S)
	if not N then
		ParamError (ParId, RS_SIsNotNumber, S)
	else
		p.CheckNum (N, ParId, LimInf, LimSup)
	end
end --CheckSIsNum

function p.CheckSIsInt (S, Where, LimInf, LimSup)
	if p.Error.yes then return end
   	p.CheckSIsNum (S, Where, LimInf, LimSup) 
	if p.Error.yes then return end
   	p.CheckNumIsInt (tonumber(S), Where)
end

function p.CheckSIsPosInt (S, ParId, LimInf, LimSup)
	if p.Error.yes then return end
   	p.CheckSIsInt (S, ParId, LimInf, LimSup) 
	if p.Error.yes then return end
   	p.CheckNumIsPos (tonumber(S), ParId)
end

function p.CheckSIsZeroOrPosInt (S, ParId, LimSup)
	if p.Error.yes then return end
   	p.CheckSIsInt (S, ParId, 0, LimSup) 
	if p.Error.yes then return end
   	p.CheckNumIsZeroOrPos (tonumber(S), ParId)
end

function p.NotAssignedValue (ParId)
	ParamErrorS (ParId, I18nStr (RS_SIsNotAssigned))
end

----------

function p.Str_Par (Args, ParId, Default)
	if p.Error.yes then return end
	local S = nil
	if type(ParId) == 'table' then
		for I, W in ipairs(ParId) do
			S = Args[W]
			if S ~= nil then
				break
			end
		end
	else	
		S = Args[ParId]
	end
	if S == nil then
		if Default ~= nil then
			S = Default
		end
	else
		S = mw.text.trim (S)
		if (S == '') and (Default ~= nil) then
			S = Default
		end
	end
	return S
end --Str_Par

function p.RStr_Par (Args, ParId, OKEmpty)
	if p.Error.yes then return end
	local S = p.Str_Par (Args, ParId)
	if (S == nil) or ((S == '') and ((OKEmpty == nil) or (not OKEmpty))) then
		p.NotAssignedValue (ParId)
	else
		return S
	end
end --RStr_Par

function p.Char_Par (Args, ParId, Pattern, Default)
	if p.Error.yes then return end
	local Char = p.Str_Par (Args, ParId, Default)
	if p.Error.yes then return end
	if Char ~= nil then
		local Valid = ((Default ~= nil) and (Char == Default)) or (string.len(Char) == 1) and (string.find(Pattern,Char) ~= nil)
		if not Valid then
			ParamErrorS (ParId, I18nStr (RS_CharNotFoundInPattern, Char, Pattern))
		end
	end
	return Char
end --Char_Par

function p.RChar_Par (Args, ParId, Pattern)
	if p.Error.yes then return end
	local Char = p.Char_Par (Args, ParId, Pattern)
	if p.Error.yes then return end
	if Char == nil then
		p.NotAssignedValue (ParId)
	else
		return Char
	end
end --RChar_Par

function p.NulOrWhitespace_Par (Args, ParId)
	if p.Error.yes then return end
	local S = p.Str_Par (Args, ParId)
	if p.Error.yes then return end
	return (S == nil) or (S == '')
end

function PerhapsLow (CaseSens, Wd)
	if CaseSens then
		return Wd
	else
		return string.lower(Wd)
	end
end --PerhapsLow

function p.StrChkTab_Par0 (ParId, S, Tab, CaseSens, Default) 
	if (S ~= nil) and (S ~= Default) then
		local SIni = S
		S = PerhapsLow(CaseSens,S)
		local found = false
		for I, W in ipairs(Tab) do
			if S == PerhapsLow(CaseSens,W) then
				S = W
				found = true
				break
			end
		end
		if not found then
			ParamErrorS (ParId, I18nStr (RS_SNotFoundInTab, SIni, table.concat(Tab,', ')))
			S = nil
		end
	end
	return S
end --StrChkTab_Par0

function p.StrChkTab_Par (Args, ParId, Tab, CaseSens, Default)
	if p.Error.yes then return end
	local S = p.Str_Par (Args, ParId, Default)
	if p.Error.yes then return end
	return p.StrChkTab_Par0 (ParId, S, Tab, CaseSens, Default)
end --StrChkTab_Par

function p.RStrChkTab_Par (Args, ParId, Tab, CaseSens)
	if p.Error.yes then return end
	local S = p.StrChkTab_Par (Args, ParId, Tab)
	if p.Error.yes then return end
	if S == nil then
		p.NotAssignedValue (ParId)
	else
		return S
	end
end --RStrChkTab_Par

function p.StrIdxChkTab_Par (Args, ParId, Tab, CaseSens, Default)
	if p.Error.yes then return end
	local S = p.Str_Par (Args, ParId, Default)
	if p.Error.yes then return end
	if (S ~= nil) and (S ~= Default) then
		local SIni = S
		S = PerhapsLow(CaseSens,S)
		local found = false
		for I, W in ipairs(Tab) do
			if S == PerhapsLow(CaseSens,W) then
				S = I
				found = true
				break
			end
		end
		if not found then
			ParamErrorS (ParId, I18nStr (RS_SNotFoundInTab, SIni, table.concat(Tab,', ')))
			S = nil
		end
	end
	return S
end --StrIdxChkTab_Par

function p.RStrIdxChkTab_Par (Args, ParId, Tab, CaseSens)
	if p.Error.yes then return end
	local S = p.StrIdxChkTab_Par (Args, ParId, Tab)
	if p.Error.yes then return end
	if S == nil then
		p.NotAssignedValue (ParId)
	else
		return S
	end
end --RStrIdxChkTab_Par

function p.Num_Par (Args, ParId, Default, LimInf, LimSup)
	if p.Error.yes then return end
	local N = p.Str_Par (Args, ParId)
	if p.Error.yes then return end
	if N == nil then
		if Default ~= nil then
			N = Default
		end
		return N, true
	else
		p.CheckSIsNum (N, ParId, LimInf, LimSup)
		if p.Error.yes then return end
		return tonumber(N), false
	end
end --Num_Par

function p.RNum_Par (Args, ParId, LimInf, LimSup)
	if p.Error.yes then return end
	local N = p.Num_Par (Args, ParId, nil, LimInf, LimSup)
	if p.Error.yes then return end
	if N == nil then
		p.NotAssignedValue (ParId)
	else
		return N, false
	end
end --RNum_Par

function p.PosNum_Par (Args, ParId, Default, LimInf, LimSup)
	if p.Error.yes then return end
	local N, IsDefault = p.Num_Par (Args, ParId, Default, LimInf, LimSup)
	if p.Error.yes then return end
	if not IsDefault then
		p.CheckNumIsPos (N, ParId)
		if p.Error.yes then return end
	end
	return N
end --PosNum_Par

function p.RPosNum_Par (Args, ParId, LimInf, LimSup)
	if p.Error.yes then return end
	local N = p.PosNum_Par (Args, ParId, nil, LimInf, LimSup)
	if p.Error.yes then return end
	if N == nil then
		p.NotAssignedValue (ParId)
	else
		return N
	end
end --RNum_Par

function p.ZeroOrPosNum_Par (Args, ParId, Default, LimInf, LimSup)
	if p.Error.yes then return end
	local N, IsDefault = p.Num_Par (Args, ParId, Default, LimInf, LimSup)
	if p.Error.yes then return end
	if not IsDefault then
		p.CheckNumIsZeroOrPos (N, ParId)
		if p.Error.yes then return end
	end
	return N
end --ZeroOrPosNum_Par

function p.RZeroOrPosNum_Par (Args, ParId, LimInf, LimSup)
	if p.Error.yes then return end
	local N = p.ZeroOrPosNum_Par (Args, ParId, nil, LimInf, LimSup)
	if p.Error.yes then return end
	if N == nil then
		p.NotAssignedValue (ParId)
	else
		return N
	end
end --RZeroOrPosNum_Par

function p.Int_Par (Args, ParId, Default, LimInf, LimSup)
	if p.Error.yes then return end
	N, IsDefault = p.Num_Par (Args, ParId, Default, LimInf, LimSup)
	if p.Error.yes then return end
	if not IsDefault then
		p.CheckNumIsInt (N, ParId)
		if p.Error.yes then return end
	end
	return N
end --Int_Par

function p.RInt_Par (Args, ParId, LimInf, LimSup)
	if p.Error.yes then return end
	local N = p.Int_Par (Args, ParId, nil, LimInf, LimSup)
	if p.Error.yes then return end
	if N == nil then
		p.NotAssignedValue (ParId)
	else
		return N, true
	end
end --RInt_Par

function p.PosInt_Par (Args, ParId, Default, LimInf, LimSup)
	if p.Error.yes then return end
	local N = p.Int_Par (Args, ParId, Default, LimInf, LimSup)
	if p.Error.yes then return end
	if N ~= nil then
		p.CheckNumIsPos (N, ParId)
		if p.Error.yes then return end
	end
	return N
end --PosInt_Par

function p.RPosInt_Par (Args, ParId, LimInf, LimSup)
	if p.Error.yes then return end
	local N = p.PosInt_Par (Args, ParId, nil, LimInf, LimSup)
	if p.Error.yes then return end
	if N == nil then
		p.NotAssignedValue (ParId)
	else
		return N, false
	end
end --RPosInt_Par

function p.ZeroOrPosInt_Par (Args, ParId, Default, LimSup)
	if p.Error.yes then return end
	local N = p.Int_Par (Args, ParId, Default, Default, 0, LimSup)
	if p.Error.yes then return end
	if N ~= nil then
		p.CheckNumIsZeroOrPos (N, ParId)
		if p.Error.yes then return end
	end
	return N
end --ZeroOrPosInt_Par

function p.RZeroOrPosInt_Par (Args, ParId, LimSup)
	if p.Error.yes then return end
	local N = p.ZeroOrPosInt_Par (Args, ParId, nil, LimSup)
	if p.Error.yes then return end
	if N == nil then
		p.NotAssignedValue (ParId)
	else
		return N, true
	end
end --RZeroOrPosInt_Par

---

function p.Bool_Par (Args, ParId, Default)
	if p.Error.yes then return end
	local B = p.Str_Par (Args, ParId)
	if p.Error.yes then return end
	if B == '' then
		return Default
	else	
		return yesno (B, Default)
	end
end --Bool_Par

function p.RBool_Par (Args, ParId, Default)
	if p.Error.yes then return end
	local B = p.Bool_Par (Args, ParId, nil)
	if p.Error.yes then return end
	if B == nil then
		p.NotAssignedValue (ParId)
	else
		return B
	end
end --RBool_Par

---

function SFoundInArr (val, CaseSens, ParId)
	found = false
	if type(ParId) == 'table' then
		for I, W in ipairs(ParId) do
			if val == PerhapsLow(CaseSens, W) then
				found = true
				break
			end
		end
	else
		if val == PerhapsLow(CaseSens, ParId) then
			found = true
		end
	end
	return found
end --SFoundInArr

function StrIdxChkTab0 (val, CaseSens, Default, ...)
	if p.Error.yes then return end
	if arg == nil then
		error('Not arguments trying to find "'..W..'"') --It doesn't require translation, only for degug
	end
	local Idx = 0
	if not p.Error.yes then 
		if not CaseSens then
			val = string.lower(val)
		end
		local tab = unpack(arg)
		for I, W in ipairs(tab) do
			if SFoundInArr (val, CaseSens, W) then
				Idx = I
				break
			end
		end
		if (Idx == 0) and (Default ~= nil) then
			Idx = Default
		end
	end
	if p.Error.yes then 
		return p.MsgError()
	else
		return Idx
	end
end --StrIdxChkTab0

function p.StrIdxChkTab (Args, ParId, CaseSens, Default, ...)
	if p.Error.yes then return end
	local W = p.Str_Par (Args, ParId, Default)
	local Idx = StrIdxChkTab0 (W, CaseSens, Default, arg)
	if p.Error.yes then 
		return p.MsgError()
	else
		return Idx
	end
end--StrIdxChkTab
	
function p.RStrIdxChkTab (Args, ParId, CaseSens, ...)
	if p.Error.yes then return end
	local W = p.RStr_Par (Args, ParId)
	local Idx = StrIdxChkTab0 (W, CaseSens, nil, arg)
	if p.Error.yes then 
		return p.MsgError()
	else
		return Idx
	end
end --RStrIdxChkTab

function IdxOrNotFound (ParId, W, Idx, ...)
	local Err = {}
	if Idx == 0 then
		local tab = unpack(arg)
		for I, Wd in ipairs(tab) do
			if type(Wd) == 'table' then
				table.insert (Err, table.concat(Wd,p.ParaSep))
			else
				table.insert (Err, Wd)
			end
		end
		ParamErrorS (ParId, I18nStr (RS_SNotFoundInTab, W, table.concat(Err,', ')))
	else
		return Idx
	end
end --IdxOrNotFound	

function p.StrIdxChkTabE (Args, ParId, CaseSens, Default, ...)
	if p.Error.yes then return end
	local W = p.Str_Par (Args, ParId, Default)
	local Idx = StrIdxChkTab0 (W, CaseSens, Default, arg)
	if p.Error.yes then 
		return p.MsgError()
	else
		return IdxOrNotFound (ParId, W, Idx, arg)
	end
end--StrIdxChkTabE
	
function p.RStrIdxChkTabE (Args, ParId, CaseSens, ...)
	if p.Error.yes then return end
	local W = p.RStr_Par (Args, ParId)
	local Idx = StrIdxChkTab0 (W, CaseSens, nil, arg)
	if p.Error.yes then 
		return p.MsgError()
	else
		return IdxOrNotFound (ParId, W, Idx, arg)
	end
end --RStrIdxChkTabE

-----

function InRange (Num, ParId, MinItemNum, MaxItemNum)
	out = ((MinItemNum ~= nil) and (Num < MinItemNum)) or ((MaxItemNum ~= nil) and (Num > MaxItemNum))
	if out then
		if MaxItemNum ~= nil then
			ParamErrorS (ParId, I18nStr (RS_STabIsNotInRange, Num, tostring(MinItemNum), tostring(MaxItemNum)))
		else
			ParamErrorS (ParId, I18nStr (RS_STabFewItems, Num, tostring(MinItemNum)))
		end
	end
	return not out
end--InRange

function p.StrTab_1Par (Args, ParId, Sep, MinItemNum, MaxItemNum, LimInf, LimSup, OnEmpty)
	if p.Error.yes then return end
	if Sep == nil then
		error ('Undefined items separator') -- Don't translate, it ies only for debug
	end
	if OnEmpty == nil then
		OnEmpty = 2  --set an empty value error
	end
	local tab = mw.text.split (p.Str_Par (Args, ParId), Sep)
	if p.Error.yes then return end
	if InRange (#tab, ParId, MinItemNum, MaxItemNum) then
		for I, W in ipairs(tab) do
			tab[I] = mw.text.trim (tab[I])
		end
		if OnEmpty == 0 then
			return tab
		elseif OnEmpty == 1 then
			local tab2 = {} 
			for I, W in ipairs(tab) do
				if W ~= '' then
					table.insert (tab2, W)
				end
			end
			return tab2
		else
			for I, W in ipairs(tab) do
				if W == '' then
					ParamError (ParId, RS_EmptyValue)
				end
			end
			return tab
		end
	end
end --StrTab_1Par

function p.NumTab_1Par (Args, ParId, Sep, MinItemNum, MaxItemNum, LimInf, LimSup, OnEmpty)
	if p.Error.yes then return end
	tab = p.StrTab_1Par (Args, ParId, Sep, MinItemNum, MaxItemNum, OnEmpty)
	if p.Error.yes then return end
	for I, W in ipairs(tab) do
		if W ~= nil then
			local J = tonumber(W)
			if not J then
				ParamError (ParId, RS_SIsNotNumber, W)
				return tab
			else
				p.CheckNum (J, Pos, LimInf, LimSup)
				if p.Error.yes then return end
				tab[I] = J
			end
		end
	end
	return tab
end --NumTab_1Par	

function p.PosNumTab_1Par (Args, ParId, Sep, MinItemNum, MaxItemNum, LimInf, LimSup, OnEmpty)
	if p.Error.yes then return end
	tab = p.NumTab_1Par (Args, ParId, Sep, MinItemNum, MaxItemNum, LimInf, LimSup, OnEmpty)
	if p.Error.yes then return end
	for I, W in ipairs(tab) do
		if W ~= nil then
			p.CheckNumIsPos (W, ParId)
		end
		if p.Error.yes then return end
	end
	return tab
end --ZeroOrPosNumTab_1Par	

function p.ZeroOrPosNumTab_1Par (Args, ParId, Sep, MinItemNum, MaxItemNum, LimInf, LimSup, OnEmpty)
	if p.Error.yes then return end
	tab = p.NumTab_1Par (Args, ParId, Sep, MinItemNum, MaxItemNum, LimInf, LimSup, OnEmpty)
	if p.Error.yes then return end
	for I, W in ipairs(tab) do
		if W ~= nil then
			p.CheckNumIsZeroOrPos (W, ParId)
		end
		if p.Error.yes then return end
	end
	return tab
end --ZeroOrPosNumTab_1Par	

function p.IntTab_1Par (Args, ParId, Sep, MinItemNum, MaxItemNum, LimInf, LimSup, OnEmpty)
	if p.Error.yes then return end
	tab = p.NumTab_1Par (Args, ParId, Sep, MinItemNum, MaxItemNum, LimInf, LimSup, OnEmpty)
	if p.Error.yes then return end
	for I, W in ipairs(tab) do
		if W ~= nil then
			p.CheckNumIsInt (W, ParId)
		end
		if p.Error.yes then return end
	end
	return tab
end--IntTab_1Par

function p.PosIntTab_1Par (Args, ParId, Sep, MinItemNum, MaxItemNum, LimInf, LimSup, OnEmpty)
	if p.Error.yes then return end
	tab = p.IntTab_1Par (Args, ParId, Sep, MinItemNum, MaxItemNum, LimInf, LimSup, OnEmpty)
	if p.Error.yes then return end
	for I, W in ipairs(tab) do
		if W ~= nil then
			p.CheckNumIsPos (W, ParId)
		end
		if p.Error.yes then return end
	end
	return tab
end --PosIntTab_1Par

function p.ZeroOrPosIntTab_1Par (Args, ParId, Sep, MinItemNum, MaxItemNum, LimInf, LimSup, OnEmpty)
	if p.Error.yes then return end
	tab = p.IntTab_1Par (Args, ParId, Sep, MinItemNum, MaxItemNum, LimInf, LimSup, OnEmpty)
	if p.Error.yes then return end
	for I, W in ipairs(tab) do
		if W ~= nil then
			p.CheckNumIsZeroOrPos (W, ParId)
		end
		if p.Error.yes then return end
	end
	return tab
end --ZeroOrPosIntTab_1Par

--------

function p.StrTab_NPar (Args, NArgs, ParId, MinItemNum, MaxItemNum, OnEmpty)
	local tab = {}
	if OnEmpty == nil then
		OnEmpty = 2  --set an empty value error
	end
	function IncInTab (val)
		val = mw.text.trim(val)
		if OnEmpty == 0 then
	 		if val ~= '' then
				table.insert(tab,val)
			end
		elseif OnEmpty == 1 then
	 		table.insert(tab,val)
		else
			if val == '' then
				ParamError (ParId, RS_EmptyValue)
			else	
	 			table.insert(tab,val)
			end
	 	end
	end
	if p.Error.yes then return end
	if type(ParId) == 'number' then
		for k = ParId, NArgs do
			local S = Args[k]
			IncInTab (S)
			if p.Error.yes then return end
		end
	elseif type(ParId) == 'string' then
		found = false
		local Pos = 1
		while not found do
			local key = string.format (ParId, Pos)
			for k, v in pairs(Args) do
				if k == key then
					IncInTab (v)
					if p.Error.yes then return end
					found = true
					break
				end
			end
			if not found then 
				break
			end
			found = false
			Pos = Pos + 1
		end
	elseif type(ParId) == 'table' then
		found = false
		local Pos = 1
		while not found do
			for a, b in ipairs(ParId) do
				local key = string.format (b, Pos)
				for k, v in pairs(Args) do
					if k == key then
						IncInTab (v)
						if p.Error.yes then return end
						found = true
						break
					end
				end
				if found then
					break
				end
			end
			if not found then 
				break
			end
			found = false
			Pos = Pos + 1
		end
	end
	InRange (#tab, ParId, MinItemNum, MaxItemNum)
	return tab, #tab
end --StrTab_NPar

function p.NumTab_NPar (Args, NArgs, ParId, MinItemNum, MaxItemNum, LimInf, LimSup, OnEmpty)
	if p.Error.yes then return end
	local tab = p.StrTab_NPar (Args, NArgs, ParId, MinItemNum, MaxItemNum, OnEmpty)
	if p.Error.yes then return end
	local Pos = ParId
	for I, W in ipairs(tab) do
		if W ~= nil then
			local J = tonumber(W)
			if not J then
				ParamError (Pos, RS_SIsNotNumber, W)
			else
				p.CheckNum (J, Pos, LimInf, LimSup)
				if p.Error.yes then return end
				tab[I] = J
			end
		end
		Pos = Pos + 1
	end
	return tab
end --NumTab_NPar

function p.PosNumTab_NPar (Args, NArgs, ParId, MinItemNum, MaxItemNum, LimInf, LimSup, OnEmpty)
	if p.Error.yes then return end
	local tab = p.NumTab_NPar (Args, NArgs, ParId, MinItemNum, MaxItemNum, LimInf, LimSup, OnEmpty)
	if p.Error.yes then return end
	local Pos = ParId
	for I, W in ipairs(tab) do
		if W ~= nil then
			p.CheckNumIsPos (W, Pos) 
		end
		if p.Error.yes then return end
		Pos = Pos + 1
	end
	return tab
end --PosNumTab_NPar

function p.ZeroOrPosNumTab_NPar (Args, NArgs, ParId, MinItemNum, MaxItemNum, LimInf, LimSup, OnEmpty)
	if p.Error.yes then return end
	local tab = p.NumTab_NPar (Args, NArgs, ParId, MinItemNum, MaxItemNum, LimInf, LimSup, OnEmpty)
	if p.Error.yes then return end
	local Pos = ParId
	for I, W in ipairs(tab) do
		if W ~= nil then
			p.CheckNumIsZeroOrPos (W, Pos) 
		end
		if p.Error.yes then return end
		Pos = Pos + 1
	end
	return tab
end --ZeroOrPosNumTab_NPar

function p.IntTab_NPar (Args, NArgs, ParId, MinItemNum, MaxItemNum, LimInf, LimSup, OnEmpty)
	if p.Error.yes then return end
	local tab = p.NumTab_NPar (Args, NArgs, ParId, MinItemNum, MaxItemNum, LimInf, LimSup, OnEmpty)
	if p.Error.yes then return end
	local Pos = ParId
	for I, W in ipairs(tab) do
		if W ~= nil then
			p.CheckSIsInt (W, Pos) 
		end
		if p.Error.yes then return end
		Pos = Pos + 1
	end
	return tab
end --IntTab_NPar

function p.PosIntTab_NPar (Args, NArgs, ParId, MinItemNum, MaxItemNum, LimInf, LimSup, OnEmpty)
	if p.Error.yes then return end
	local tab = p.IntTab_NPar (Args, NArgs, ParId, MinItemNum, MaxItemNum, LimInf, LimSup, OnEmpty)
	if p.Error.yes then return end
	local Pos = ParId
	for I, W in ipairs(tab) do
		if W ~= nil then
			p.CheckNumIsPos (W, Pos) 
		end
		if p.Error.yes then return end
		Pos = Pos + 1
	end
	return tab
end --PosIntTab_NPar

function p.ZeroOrPosIntTab_NPar (Args, NArgs, ParId, MinItemNum, MaxItemNum, LimInf, LimSup, OnEmpty)
	if p.Error.yes then return end
	local tab = p.IntTab_NPar (Args, NArgs, ParId, MinItemNum, MaxItemNum, LimInf, LimSup, OnEmpty)
	if p.Error.yes then return end
	local Pos = ParId
	for I, W in ipairs(tab) do
		if W ~= nil then
			p.CheckNumIsZeroOrPos (W, Pos)
		end
		if p.Error.yes then return end
		Pos = Pos + 1
	end
	return tab
end --ZeroOrPosIntTab_NPar

return p