« Module:Unité » : différence entre les versions
retouche de la modification précédente : échappement tiret dans les regex |
parseUnit : retourne la valeur d'origine si tout n'est pas correctement décoder. |
||
Ligne 99 : | Ligne 99 : | ||
function p.parseUnit( texte ) | function p.parseUnit( texte ) | ||
if trim( texte ) then | if trim( texte ) then | ||
local toParse = texte | |||
local result | local result | ||
local nombre = | -- valeur numérique | ||
local nombre = toParse:match( '^%-?%f[%d][%d., \194\160]*%d%f[%D]' ) or false | |||
if nombre then | if nombre then | ||
toParse = toParse:sub( nombre:len() + 1 ) | |||
end | end | ||
result = { nombre } | result = { nombre } | ||
local e = | |||
-- 10 exposant ( \195\151 = ×, signe multiplié) | |||
if | local match, e = toParse:match( '^(%s*[x\195]\151?10e(%-?%d+))' ) | ||
if not match then | |||
match, e = toParse:match( '^(%s*e(%-?%d+))' ) | |||
end | |||
if match then | |||
table.insert( result, '10' ) | table.insert( result, '10' ) | ||
table.insert( result, e ) | table.insert( result, e ) | ||
toParse = toParse:sub( match:len() + 1 ) | |||
end | end | ||
-- unités | |||
toParse = toParse:gsub( '⋅', '.' ) | |||
local match, unit, exp = mw.ustring.match( toParse, '^(%s*%.?([%a°/]+)(%-?%d*))' ) | |||
while match and unit:len() < 5 do | |||
table.insert( result, unit ) | table.insert( result, unit ) | ||
table.insert( result, exp ) | table.insert( result, exp ) | ||
toParse = toParse:sub( match:len() + 1 ) | |||
match, unit, exp = mw.ustring.match( toParse, '^(%s*%.?([%a°/]+)(%-?%d*))' ) | |||
end | end | ||
return result | if trim( toParse ) then | ||
-- une partie de la chaine n'a pas pu être décodée, on retourne la chaine originale | |||
return { texte } | |||
else | |||
return result | |||
end | |||
else | else | ||
return { } | return { } | ||
Ligne 130 : | Ligne 146 : | ||
local exp = trim( args.e ) | local exp = trim( args.e ) | ||
if nombre then | if nombre then | ||
nombre = nombre:gsub( '%−%f[d]', '-') -- U+2212 | nombre = nombre | ||
:gsub( '−%f[d]', '-') -- html − | -- remplacement des signes moins par des tirets pour facilité les traitements ultérieurs | ||
:gsub( '\226\128[\146\147]%f[d]', '-') -- U+2212, U+2213 (tiret numérique et demi-cadratin) | :gsub( '%−%f[%d]', '-') -- U+2212 | ||
:gsub( '−%f[%d]', '-') -- html − | |||
:gsub( '\226\128[\146\147]%f[%d]', '-') -- U+2212, U+2213 (tiret numérique et demi-cadratin) | |||
-- remplacement des espaces insécable par des espace simple | |||
:gsub( '\194\160', ' ' ) | |||
end | end | ||
Ligne 143 : | Ligne 162 : | ||
end | end | ||
-- formatage du nombre | |||
if nombre then | if nombre then | ||
nombre = nombre:gsub( '%-?%f[%d][%d., | nombre = nombre:gsub( '%-?%f[%d][%d., ]+%f[%D]', p.formatNombre ) | ||
table.insert( wiki, nombre ) | table.insert( wiki, nombre ) | ||
sep = ' | sep = ' ' | ||
end | end | ||
-- puissance de 10 | |||
local i = 1 | local i = 1 | ||
if not exp and unit == '10' then | if not exp and unit == '10' then | ||
Ligne 161 : | Ligne 182 : | ||
table.insert( wiki, '10<sup>' .. exp .. '</sup>' ) | table.insert( wiki, '10<sup>' .. exp .. '</sup>' ) | ||
end | end | ||
sep = ' | sep = ' ' | ||
end | end | ||
-- unités | |||
while unit do | while unit do | ||
table.insert( wiki, sep ) | table.insert( wiki, sep ) | ||
Ligne 177 : | Ligne 199 : | ||
if #wiki > 0 then | if #wiki > 0 then | ||
return '<span class="nowrap">' .. | local result = table.concat( wiki ):gsub( '⋅/', '/' ) -- nettoyage cas particulier de parseunit. | ||
return '<span class="nowrap">' .. result .. '</span>' | |||
end | end | ||
end | end |
Version du 16 avril 2015 à 21:51
local p = { }
--- Copie de Outils.trim acceptant les nombres. local function trim( texte ) if type( texte ) == 'string' then texte = texte:gsub( '^%s*(.*)%f[%s]%s*$', '%1' ) if texte ~= then return texte end elseif type( texte ) == 'number' then return tostring( texte ) end end
--- -- parseNum transforme si possible une chaine formater en un chaine interprétable par tonumber() -- retourne une chaine pour éviter les arrondi éventuels de lua. -- si nombre n'est pas un nombre ou une chaine retourne une chaine vide. -- function p.parseNombre( nombre ) if type( nombre ) == 'number' then nombre = tostring( nombre ) elseif type( nombre ) ~= 'string' then return end
-- remplacement des signes moins ou demi-cadratin par un tiret nombre = nombre:gsub( '^&minus', '-' ) :gsub( '^\226\128[\146\147]', '-' ) -- U+2012, U+2013 (voir Tiret) :gsub( '^\226\136\147', '-' ) -- U+2212
if nombre:match( '^%-?[%d., \194\160]*%d$' ) then -- suppression espaces et espaces insécables nombre = nombre:gsub( ' ', ):gsub( '\194\160', )
if nombre:match( '[.,]' ) then if nombre:match( '%d+,%d%d%d,%d%d%d%f[%D]' ) -- type 1,234,567 or nombre:match( '%d+,%d%d%d%.%d+' ) -- type 1,234.5 --or nombre:match( '%d+,%d00$' ) -- type 1,200 then -- format anglo-saxon nombre = nombre:gsub( ',', ) elseif nombre:match( '%d+%.%d%d%d,%d' ) or nombre:match( '%d+%.%d%d%d.%d%d%d%f[%D]' ) then -- formant germanique type 1.234,5 nombre = nombre:gsub( '%.', ):gsub( ',', '.' ) else nombre = nombre:gsub( ',', '.' ) end end end
return nombre end
--- -- _formantNum transforme un nombre ou une chaine représentant un nombre en chaine formatée suivant les conventions du français -- si le paramètre ne représente pas un nombre lua il est retourné sans modification function p._formatNum( num ) if type( num ) == 'number' then num = tostring( num ) elseif type( num ) ~= 'string' then return num end
local moins, entier, fraction = num:match( '^(%-?)(%d+)%.?(%d*)$' ) if not entier then return num end
if moins == '-' then moins = '−' -- signe moins (U+2212) end
if entier:len() > 3 then local ini = math.fmod( entier:len(), 3 ) entier = ( entier:sub( 1, ini ) or ) .. entier:sub( ini + 1 ):gsub( '(%d%d%d)', '\194\160%1' ) end if fraction ~= then fraction = ',' .. fraction:gsub( '(%d%d%d)', '%1\194\160' ):gsub( '\194\160$', ) end
return moins .. entier .. fraction end
--- -- formatNum transforme les nombres d'une chaine en chaine formatée suivant les conventions du français function p.formatNum( num ) if type( num ) == 'number' then return p._formatNum( num ) elseif type( num ) == 'string' then return num:gsub( '%-?%d*%.?%d+', p.formatNombre ) end end
function p.formatNombre( nombre ) return p._formatNum( p.parseNombre( nombre ) ) end
function p.parseUnit( texte ) if trim( texte ) then local toParse = texte local result -- valeur numérique local nombre = toParse:match( '^%-?%f[%d][%d., \194\160]*%d%f[%D]' ) or false if nombre then toParse = toParse:sub( nombre:len() + 1 ) end result = { nombre }
-- 10 exposant ( \195\151 = ×, signe multiplié) local match, e = toParse:match( '^(%s*[x\195]\151?10e(%-?%d+))' ) if not match then match, e = toParse:match( '^(%s*e(%-?%d+))' ) end if match then table.insert( result, '10' ) table.insert( result, e ) toParse = toParse:sub( match:len() + 1 ) end
-- unités toParse = toParse:gsub( '⋅', '.' ) local match, unit, exp = mw.ustring.match( toParse, '^(%s*%.?([%a°/]+)(%-?%d*))' ) while match and unit:len() < 5 do table.insert( result, unit ) table.insert( result, exp ) toParse = toParse:sub( match:len() + 1 ) match, unit, exp = mw.ustring.match( toParse, '^(%s*%.?([%a°/]+)(%-?%d*))' ) end if trim( toParse ) then -- une partie de la chaine n'a pas pu être décodée, on retourne la chaine originale return { texte } else return result end else return { } end end
function p._unite( args ) local wiki = { } local sep = local nombre = trim( args[1] ) local unit = trim( args[2] ) local exp = trim( args.e )
if nombre then nombre = nombre -- remplacement des signes moins par des tirets pour facilité les traitements ultérieurs :gsub( '%−%f[%d]', '-') -- U+2212 :gsub( '−%f[%d]', '-') -- html − :gsub( '\226\128[\146\147]%f[%d]', '-') -- U+2212, U+2213 (tiret numérique et demi-cadratin) -- remplacement des espaces insécable par des espace simple :gsub( '\194\160', ' ' ) end
if nombre and not unit and not exp and nombre:match('[^%d,. -]') then args = p.parseUnit( nombre ) nombre = args[1] unit = args[2] end
-- formatage du nombre if nombre then nombre = nombre:gsub( '%-?%f[%d][%d., ]+%f[%D]', p.formatNombre ) table.insert( wiki, nombre ) sep = ' ' end
-- puissance de 10 local i = 1 if not exp and unit == '10' then exp = args[3] i = 2 unit = trim( args[4] ) end if exp then if #wiki > 0 then table.insert( wiki, '×10' .. exp .. '' ) else table.insert( wiki, '10' .. exp .. '' ) end sep = ' ' end
-- unités while unit do table.insert( wiki, sep ) table.insert( wiki, unit ) exp = trim( args[ 2 * i + 1 ] ) if exp then table.insert( wiki, '' .. exp:gsub( '%-', '−' ) .. '' ) end i = i + 1 unit = trim( args[ 2 * i ] ) sep = '⋅' end
if #wiki > 0 then local result = table.concat( wiki ):gsub( '⋅/', '/' ) -- nettoyage cas particulier de parseunit. return '' .. result .. '' end end
function p.unite( frame ) local args if type( frame ) == 'table' and type( frame.getParent ) == 'function' then args = frame:getParent().args; end if args then return p._unite( args ) end end
return p